5

「7週間で7つの言語」atmを読んでいて、「no」の応答がわからないPrologクエリに困惑しています。

ファイルは次のfriends.plようになります。

likes(wallace, cheese).
likes(grommit, cheese).
likes(wendolene, sheep).

friend(X, Y) :- \+(X = Y), likes(X, Z), likes(Y, Z).

次のような簡単なクエリを実行できます。

| ?- ['friends'].
compiling /home/marc/btlang-code/code/prolog/friends.pl for byte code...
/home/marc/btlang-code/code/prolog/friends.pl compiled, 12 lines read - 994 bytes written, 8 ms

yes
| ?- friend(wallace,grommit).

yes
| ?- friend(wallace,wendolene).

no

これはすべて予想通りです。ここで、クエリに変数を導入します。私の意図は、PrologがWallaceのすべての友達のリストを私に与えるということです。私は期待していX = grommitますが、私は得ていnoます:

| ?- trace.
The debugger will first creep -- showing everything (trace)

yes
{trace}
| ?- friend(wallace,X).
      1    1  Call: friend(wallace,_16) ?
      2    2  Call: \+wallace=_16 ?
      3    3  Call: wallace=_16 ?
      3    3  Exit: wallace=wallace ?
      2    2  Fail: \+wallace=_16 ?
      1    1  Fail: friend(wallace,_16) ?

no
{trace}

X_16)を。と統合しようとさえしませんgrommit。なんで?

4

4 に答える 4

4

上記のPhilipJFのコメントについて:

これらの問題を引き起こさない方法で、「失敗としての否定」タイプの制約を表現できるはずです。

これは可能です:そのような問題の最新の解決策は制約です。この場合、たとえばdif/2、すべての深刻なPrologシステムで利用可能なを使用します。

于 2011-05-12T07:07:59.963 に答える
4

それは友人の定義です:

friend(X, Y) :- \+(X = Y), likes(X, Z), likes(Y, Z).

ここで重要なこと\+(X = Y)は、通常次のように定義されている whichから始めることです。

\+ Goal :- Goal,!,fail

これは、ゴールが成功した場合、必ず失敗することを意味することに注意してください。自由変数 (割り当てられていないもの) は常に統合されるため、等しいため、自由変数では常に失敗します。したがって、X または Y に値が割り当てられていない場合は、値が割り当てられることはありません。

その代わり

friend(X, Y) :-  likes(X, Z), likes(Y, Z), \+(X = Y)

期待どおりに動作します。

ここでの問題は、prolog がプログラムの流れを制御する強力な方法を提供することですが、それらはよりロジック指向の設計にうまく適合しないことです。これらの問題を生じさせない方法で、「失敗としての否定」タイプの制約を表現できるはずです。このため、私はプロローグの大ファンではありません。

于 2011-05-12T00:27:24.077 に答える
3

の最初のサブゴールはfriend/2です\+(X = Y)。これは、最初に の解を見つけようとしX = Y、次にその結果を否定することによって実行されます。述語=/2は とほぼ同じですunify/2。つまり、左側のオペランドを右側のオペランドと統合しようとします。ここで、たとえば を使用してクエリを実行する場合friend(wallace, gromit)、2 つのアトムwallaceとは結合しgromitません。しかし、自由変数がミックスに投入されると、与えられた項が何であれ常に統一されるため、X = Y常に成功し、したがって\+(X = Y)常に失敗し、実行は最初のサブゴールを決して超えません。

于 2011-05-12T00:20:41.297 に答える
1

不等式制約を最初に持つことのもう 1 つの問題は、次のとおりです。バインドされていないものに対するバインディングを見つけることができませんX(現時点ではグロミットで統合するという些細なケースを除きます)。Prolog は、データベースを実行してバインドを見つけ、バインドされていない変数を統一しようとします。データベースに句があるため、さらに処理できるlikes(grommit, Z)バインディングが見つかるのはそのためです。しかし、grommit と何かとの不等式についてはそのような節がないため、Prolog はバインディングを生成できません。現状では、述語は、不等式をテストする前に、すべての変数がバインドされていることを確認する必要があります。Zlikesfriend

于 2011-06-04T20:37:30.813 に答える