考虑这个小程序:
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).
?
这是一种定义方法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
| ?-
附录
基于 Sergey 的观察:
| ?- 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 在他的评论中指出的那样,这种谓词必须谨慎使用,理解它的逻辑含义在某些情况下是有限的,甚至是自相矛盾的。
正如@SergeyDymchenko 在评论中所观察到的,没有办法定义一个谓词以使其仍然保留其关系属性并满足您的愿望。
我不清楚你为什么想要这个。也许你想减少输出?然后简单地问另一个查询:
?- spouse(X,Y), X @=< Y.