0

4つのバスケットがあり、それぞれがユニークな色をしています。いくつかの事実と規則に基づいて色の順序を伝えるプロローグ プログラムを作成します。これは .pl ファイルです。

iright(L, R, [L | [R | _]]).
iright(L, R, [_ | Rest]) :- iright(L, R, Rest).
nextto(L, R, List) :- iright(L, R, List).
nextto(L, R, List) :- iright(R, L, List).

myprogram(Data) :-     =(Data, [_,red,_,_]), 
\+nextto(red,blue,Data), % blue is not next to red
iright(red,green,Data), %green is right to red
member(red,Data),
member(blue,Data),
member(green,Data),
member(yellow,Data).

iright 述語と nextto 述語は正しいです。私のクエリはmyprogram(Data)で、結果は次のようになるはずです

Data = [yellow,red, green, blue]?
yes

しかし、実際にはプロンプトはそれを示しています

| ?- myprogram(Data).

no

問題は否定であることは知っていますが、その方法と理由はわかりません。助けてください。

私が使うときtrace.

      1    1  Call: myprogram(_16) ? 
      2    2  Call: \+nextto(red,blue,[_46,red,_50,_52]) ? 
      3    3  Call: nextto(red,blue,[_46,red,_50,_52]) ? 
      4    4  Call: iright(red,blue,[_46,red,_50,_52]) ? 
      5    5  Call: iright(red,blue,[red,_50,_52]) ? 
      5    5  Exit: iright(red,blue,[red,blue,_52]) ? 
      4    4  Exit: iright(red,blue,[_46,red,blue,_52]) ? 
      3    3  Exit: nextto(red,blue,[_46,red,blue,_52]) ? 
      2    2  Fail: \+nextto(red,blue,[_46,red,_50,_52]) ? 
      1    1  Fail: myprogram(_16) ? 

(2 ms) no
4

1 に答える 1

1

\+nextto(red, blue, Data)を の最後の行に移動するとmyprogram、機能します。

少し直感的ではありませんが、Prolog が式を評価する方法と、否定が実際に何を意味するかについて少し考える必要があります。否定とは、「特定の値のセットに対して真になることはできない」のではなく、「これが真になる可能性がない」ことを意味します。プログラムを単純に削除すると、次のようになります。

 myprogram(Data) :-
    =(Data, [_,red,_,_]),
    \+nextto(red,blue,Data).

あなたはまだ得るでしょうNo.。これは、あなたが宣言したことで、データができるからです [_, red, blue, _]- この決定が で行われたことがわかりますExit: iright(red,blue,[red,blue,_52])。Prolog はバックトラックを試みますが、他に試すことができるものはありません。特定の値を持つように _s をまだ制約していません。

OTOH、すべての nextto、member、および iright ステートメントを否定されたステートメントの前に置く場合、否定された式に到達したときに試すことができる複数の解決策 (まあ、2 つ) がData = [blue,red,green,yellow]ありData = [yellow,red,green,blue]ます。この時点で、否定を見ると、赤が青の隣にある「枝」を「捨て」ますが、バックトラックすることができ、否定を真にする可能性のある世界状態があります。つまり、次のようになります。

myprogram(Data) :-
    =(Data, [_,red,_,_]),
    iright(red,green,Data),
    member(red,Data),
    member(blue,Data),
    member(green,Data),
    member(yellow,Data),
    \+nextto(red,blue,Data).

...望ましい結果が得られます。

TL;DR - Prolog の否定 (および、それらに到達した場合のカット) は、最初に考えるよりもはるかに強力です。それらを使用する前に、最初に他のすべてのことを理解していることを確認してください。

于 2012-11-21T00:43:48.070 に答える