2

次の gprolog プログラムがあります。

father(charles, harry). 
daughter(elizabeth, george).
son(william, charles). 
father(X, Y) :- son(Y, X).
father(X, Y) :- daughter(Y, X).
daughter(X, Y) :- \+son(X, Y), father(Y, X).
son(X, Y) :- \+daughter(X, Y), father(Y, X).

私が持っているものを考えて、私はこのクエリを試しました:

| ?- son(harry, charles).

...そして、no(別名、私が理解していることから、「Prologはこれを証明できません。」)を得ました。トレースを実行したところ、あまり役に立たなかったようです。

{trace}
| ?- son(harry, charles).
      1    1  Call: son(harry,charles) ? 
      1    1  Fail: son(harry,charles) ? 

son(harry, charles)私のコードの最後の行まで一致するはずなので、プログラムは最初の部分をチェックするだけで始まると思いました: \+daughter(X, Y)(「プロローグはハリーがチャールズの娘であることを証明できません」よね?)。それはそう:

| ?- \+daughter(harry, charles).
      1    1  Call: \+daughter(harry,charles) ? 
      2    2  Call: daughter(harry,charles) ? 
      2    2  Fail: daughter(harry,charles) ? 
      1    1  Exit: \+daughter(harry,charles) ? 

(1 ms) yes

では、第二部に進むということでしょうか。father(Y, X)つまり、father(charles, harry)事実として与えられた をチェックします!

| ?- father(charles, harry).
      1    1  Call: father(charles,harry) ? 
      1    1  Exit: father(charles,harry) ? 

(1 ms) yes

これらの両方が真であるのに、なぜyesforが与えられないのson(harry, charles)でしょうか? 重要な注意として、これは不連続な述語の警告でコンパイルされました。

compiling /Users/nicolejulian/Dropbox/AI/test.pl for byte code...
/Users/nicolejulian/Dropbox/AI/test.pl:4: warning: discontiguous predicate father/2 - clause ignored
/Users/nicolejulian/Dropbox/AI/test.pl:5: warning: discontiguous predicate father/2 - clause ignored
/Users/nicolejulian/Dropbox/AI/test.pl:6: warning: discontiguous predicate daughter/2 - clause ignored
/Users/nicolejulian/Dropbox/AI/test.pl:7: warning: discontiguous predicate son/2 - clause ignored
/Users/nicolejulian/Dropbox/AI/test.pl compiled, 8 lines read - 617 bytes written, 11 ms

(1 ms) yes

以前のいくつかの実験では、基本的に警告と無限ループのどちらかを選択できるように見えたので、そのまま使用しました。(たとえば、左側のラベルをすべてグループ化すると、警告は削除されますが、クエリ| ?- father(elizabeth, george).がクラッシュする原因になります)。

いずれにせよ、「ごまかして」son(harry, charles)事実として付け加えることができないとすれば、Prolog の実行ステップについて何が理解できないのでしょうか?

4

1 に答える 1

1

あなたが表示する警告のキーフレーズは、句が無視されます。したがって、あなたの父/息子の論理、過去のすべてfather(charles, harry)は無視されています。それらを連続させてみてください:

father(charles, harry). 
father(X, Y) :- son(Y, X).
father(X, Y) :- daughter(Y, X).

daughter(elizabeth, george).
daughter(X, Y) :- \+son(X, Y), father(Y, X).

son(william, charles). 
son(X, Y) :- \+daughter(X, Y), father(Y, X).

次に、クエリに対する回答としてtrueを取得します。

ただし、 (すべての解決策を求める)のa後に入力すると、ロジックにさらに問題があります。true正常に終了するのではなく、ループに入り、スタックをオーバーフローさせます。それは、父、息子、娘の間の循環論理によるものです。ですから、その部分をよく考えてみてください。

循環ロジックを回避するには、このチュートリアルで示されている例を検討してください。このケースでは、主張された事実を使用してperson(名前、性別、および各親を指定し、述語を使用してそれらおよびその他の関係を確立し、他の述語に無限にループバックするのではなく、事実に到達することによってループを回避します。おそらく他の同様のアプローチがあります。とありますが、これは一例です。

于 2013-06-28T02:15:55.910 に答える