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标准谓词总是成功的。解决方案是仅在实例化谓词的参数时调用谓词:

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 回答
1

只要有可能,使用dif/2代替(\==)/2.

dif/2将帮助您编写逻辑合理的程序。

有关详细信息,请查看

于 2015-06-03T03:40:01.703 回答