考虑这个小程序:
married(bill, hillary).
spouse(X, Y) :- married(X, Y); married(Y, X).
likes(X, Y) :- spouse(X, Y).
现在我想评估一个目标
?- likes(X, Y).
X = bill
Y = hillary ?;
X = hillary
Y = bill
yes
有没有办法防止在回溯时重复这种对称关系,并仍然保持?- likes(hillary, X).
等目标的对称性?
答案 0 :(得分:2)
以下是定义spouse/2
:
married(bill, hillary).
married(tom, mary).
married(sam, linda).
spouse(X, Y) :-
\+ married(X, Y) -> married(Y, X) ; married(X, Y).
因此,如果无法使married(X, Y)
成为真,那么它将尝试married(Y, X)
。否则,married(X, Y)
。
| ?- spouse(X, Y).
X = bill
Y = hillary ? ;
X = tom
Y = mary ? ;
X = sam
Y = linda
(1 ms) yes
| ?- spouse(tom, Y).
X = tom
Y = mary
yes
| ?- spouse(X, tom).
X = mary
Y = tom
yes
从表面上看,以下稍微简单的谓词可能是等价的,但它找不到所有的解决方案:
spouse(X, Y) :-
married(X, Y) -> true ; married(Y, X).
| ?- spouse(X, Y).
X = bill
Y = hillary ? ;
(1 ms) yes
| ?-
<强>附录强>
以谢格尔的观察为基础:
| ?- Y = bill, spouse(X, Y).
X = hillary
Y = bill
yes
可是:
| ?- spouse(X, Y), Y = bill.
no
这个结果是不一致的,因为通过将spouse/2
限制在考虑对称解决方案冗余的唯一解决方案中,谓词实质上是说spouse(bill, hillary)
和spouse(hillary, bill)
中只有一个在任何给定的情况下都是真的时间。如果第一个参数预先定义为bill
,则表示第二个参数必须为hillary
。如果两个参数都未实例化且spouse(X, Y)
表示解决方案X = bill
和Y = hillary
,则Y = bill
的后续查询将失败。
所以,正如@Sergey在他的评论中指出的那样,必须谨慎使用这种谓词,理解它的逻辑意义在某些情况下有些限制甚至自相矛盾。
答案 1 :(得分:2)
正如@SergeyDymchenko在评论中所观察到的那样,没有办法定义谓词,使其仍保留其关系属性和满足您的意愿。
我不清楚你为什么要这样做。也许你想减少产量?然后简单地询问另一个问题:
?- spouse(X,Y), X @=< Y.