SQB*_*SQB 5 prolog prolog-cut prolog-setof
假设我有以下内容:
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.
Run Code Online (Sandbox Code Playgroud)
现在如果我问黛安的兄弟姐妹,我会得到查理和夏娃——两次,一次通过鲍勃,一次通过爱丽丝。我只想要一次。
我不认为我可以在这里使用削减,因为这会完全防止回溯。我会想,是检查的方式任何存在。
释义
sibling(A, B) :-
?(parent(X, A), parent(X, B)),
B \= A.
Run Code Online (Sandbox Code Playgroud)
我尝试了几次切割,但都没有奏效。
我试图findall/3在(parent(X, A), parent(X, B))和检查,如果结果列表是非空的,但这并不统一A或B.
setof/3按照下面的建议使用是有效的,但我真的想找到一种方法将它合并到 的定义中sibling/2,而不必在问题中使用它。我真的很想能够做到以下几点:
?- sibling(diane, X).
X = charlie ;
X = eve ;
false.
Run Code Online (Sandbox Code Playgroud)
或这个
?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.
Run Code Online (Sandbox Code Playgroud)
就像我在下面说的,我有针对这种特定情况的解决方案。我想要的是一个通用的解决方案,我正在为此设置赏金。
代替
sibling(A, B) :-
setof(D, X^(parent(X, A), parent(X, D)), Ds),
member(B, Ds),
B \= A.
Run Code Online (Sandbox Code Playgroud)
我想做
sibling(A, B) :-
exists(X^(parent(X, A), parent(X, B))),
B \= A.
Run Code Online (Sandbox Code Playgroud)
它统一了A和B。
我如何定义exists/1?
在 Prolog 中使用 cut 是非常微妙的。大多数削减基本上是不正确的,但在某些情况下仍然有效。您可以在此处使用剪切,前提是您只需要一个答案。但是由于您想要整个集合,所以您不走运:您需要探索所有答案以确定该集合。
幸运的是,有一个优雅的快捷方式(双关语):setof/3. 所以问
?- setof(t, sibling(diane, S), _).
Run Code Online (Sandbox Code Playgroud)
对于 的这种用法setof/3,最后一个参数没有意义。它实际上是[t]。
对于一般目的exists/1,定义
exists(XGoal) :- setof(t, XGoal, _).
Run Code Online (Sandbox Code Playgroud)
这允许使用存在量词。
| 归档时间: |
|
| 查看次数: |
487 次 |
| 最近记录: |