1

を返すこの Prolog コードがあります: [[vincent,vincent],[vincent,marcellus],[marcellus,vincent],[marcellus,marcellus],[pumpkin,pumpkin],[honey_bunny,honey_bunny]].

:- initialization main.

loves(vincent, mia).
loves(marcellus, mia).
loves(pumpkin, honey_bunny).
loves(honey_bunny, pumpkin).

jealous(X, Y) :-
    loves(X, Z),
    loves(Y, Z).

main :- 
    findall([X, Y], jealous(X, Y), L),
    write(L),
    halt.

X != Y の場合にのみ結果を取得する方法は? 以前と同じ結果を得るために、次のコードを試しました。

jealous(X, Y) :-
    X \== Y,
    loves(X, Z),
    loves(Y, Z).

\=、私は を得[]ました。結果としてのみ取得する方法は[vincent,marcellus]

4

2 に答える 2

1

試みたソリューションの目標の順序が間違っています。2 つの異なる変数で呼び出された場合、(\==)/2標準の述語は常に成功します。解決策は、引数がインスタンス化されたときにのみ述語を呼び出すことです。

jealous(X, Y) :-
    loves(X, Z),
    loves(Y, Z),
    X \== Y.

この修正により、クエリは次を返すようになりました。

?- findall([X, Y], jealous(X, Y), L).
L = [[vincent, marcellus], [marcellus, vincent]].

だから、もはや誰も自分自身に嫉妬していません。しかし、それでも冗長なソリューションが得られます。jealous/2述語を変更して、返されたソリューションの名前を並べ替えることができます。例えば:

jealous(X, Y) :-
    loves(X0, Z),
    loves(Y0, Z),
    X0 \== Y0,
    (   X0 @< Y0 ->
        X = X0, Y = Y0
    ;   X = Y0, Y = X0
    ).

setof/3の代わりにを使用すると、次のfindall/3ようになります。

?- setof([X, Y], jealous(X, Y), L).
L = [[marcellus, vincent]].

最後の観察。リストは、ペアを表現するためのソリューションとしては不十分です。伝統的な方法は、 または のいずれX-Yかを使用すること(X, Y)です。

于 2015-02-01T22:06:22.173 に答える