假设我有以下内容:
parent(alice, charlie).
parent(bob, charlie).
parent(bob, diane).
parent(alice, diane).
parent(bob, eve).
parent(alice, eve).
% people are siblings of each other if they share a parent
% and aren't the same person.
sibling(A, B) :-
parent(X, A),
parent(X, B),
B \= A.
现在,如果我要黛安的兄弟姐妹,我会得到查理和夏娃——两次,一次是通过鲍勃,一次是通过爱丽丝。我只想要一次。
我不认为我可以在这里使用剪切,因为这会完全防止回溯。我想要的是一种检查是否存在的方法。
释义
sibling(A, B) :-
∃(parent(X, A), parent(X, B)),
B \= A.
我尝试了几次削减,但都没有奏效。
我尝试findall/3
检查(parent(X, A), parent(X, B))
结果列表是否为非空,但这并不能统一 A 或 B。
按照下面的建议使用setof/3
是可行的,但我真的想找到一种方法将其合并到 的定义中sibling/2
,而不必在问题中使用它。我真的很想能够做到以下几点:
?- sibling(diane, X).
X = charlie ;
X = eve ;
false.
或这个
?sibling(X, Y).
X = charlie,
Y = diane ;
X = charlie,
Y = eve ;
X = diane,
Y = charlie ;
X = diane,
Y = eve ;
X = eve,
Y = charlie ;
X = eve,
Y = diane ;
false.
就像我在下面所说的那样,我有一个针对这种特定情况的解决方案。我想要的,以及我设置赏金的,是一个通用的解决方案。
代替
sibling(A, B) :-
setof(D, X^(parent(X, A), parent(X, D)), Ds),
member(B, Ds),
B \= A.
我想做
sibling(A, B) :-
exists(X^(parent(X, A), parent(X, B))),
B \= A.
它统一了A
和B
。
我该如何定义exists/1
?