在Prolog中停止递归?

时间:2015-10-19 04:28:28

标签: prolog

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)失败。

如何在获得第一个答案时停止递归?

1 个答案:

答案 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是首选,因为它简洁明了,并且保留了原始谓词的完整性。