connect(raj,isa,indian).
connect(indian,isa,man).
attribute(raj,marks,100).
attribute(indian,marks,200).
p(Node,marks,Number) :-
attribute(Node,marks,Number).
p(Node,marks,Number) :-
connect(Node,isa,X),
p(X,marks,Number).
所以现在,在查询时,
171 ?- p(raj,marks,100).
true .
172 ?- p(raj,marks,200).
true .
在这种情况下,我希望p(raj,marks,200)
失败。
如何在获得第一个答案时停止递归?
答案 0 :(得分:5)
我想你确认这些例子是true
之后,你是不是希望Prolog不要提示更多解决方案?你可以潜在通过剪切来做到这一点,因为剪辑会在某一点修剪回溯:
p(Node, marks, Number) :-
attribute(Node, marks, Number),
!. % Don't backtrack after confirming the attribute
p(Node, marks, Number) :-
connect(Node, isa, X),
p(X, marks, Number).
现在,在确认解决方案之后,正如我所说,您所提出的查询不会回溯:
| ?- p(raj, marks, 100).
yes
| ?- p(raj, marks, 200).
(1 ms) yes
| ?-
但这是一个问题。您的谓词将不再找到查询的所有有效解决方案p(raj, marks, X)
。它只会在找到一个后停止,即使还有更多。
| ?- p(raj, marks, X).
X = 100
yes
| ?-
如果我们从代码中删除(返回原始代码),它会为X
的所有有效解决方案提供正确的响应:
| ?- p(raj, marks, X).
X = 100 ? ;
X = 200 ? ;
no
| ?-
获得之后的结果的另一个选择是使用once/1
谓词,它只会寻找第一个解决方案,然后停止回溯:
| ?- once(p(raj,marks,100)).
(1 ms) yes
| ?-
现在,我们还没有打破p/3
查询,并且有办法在没有回溯的情况下获得第一个解决方案。如果您愿意,可以围绕此建立一个单独的谓词:
p_once(Node, Marks, Number) :- once(p(Node, Marks, Number)).
然后,当然:
| ?- p_once(raj,marks,100).
(1 ms) yes
| ?-
但在我看来,明确地使用once/1
是首选,因为它简洁明了,并且保留了原始谓词的完整性。