在Prolog中停止递归?

Rah*_*hul 2 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).
Run Code Online (Sandbox Code Playgroud)

所以现在,在查询时,

171 ?- p(raj,marks,100).
true .

172 ?- p(raj,marks,200).
true .
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我想p(raj,marks,200)失败.

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

lur*_*ker 5

我想你在确认这些例子之后,是不是希望Prolog不要提示更多解决方案true?你可以潜在地做到这一点有切口,由于切口修剪在某一点回溯:

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).
Run Code Online (Sandbox Code Playgroud)

现在,在确认解决方案之后,正如我认为您要求的那样,您所提出的查询不会回溯:

| ?- p(raj, marks, 100).

yes
| ?- p(raj, marks, 200).

(1 ms) yes
| ?-
Run Code Online (Sandbox Code Playgroud)

但这提出了一个问题.您的谓词将不再找到查询的所有有效解决方案p(raj, marks, X).它只会在找到一个之后停止,即使还有更多.

| ?- p(raj, marks, X).

X = 100

yes
| ?-
Run Code Online (Sandbox Code Playgroud)

如果我们从代码中删除(返回原始代码),它会为所有有效的解决方案提供正确的响应X:

| ?- p(raj, marks, X).

X = 100 ? ;

X = 200 ? ;

no
| ?-
Run Code Online (Sandbox Code Playgroud)

获得结果的另一个选择是使用once/1谓词,它只会寻找第一个解决方案,然后停止回溯:

| ?- once(p(raj,marks,100)).

(1 ms) yes
| ?-
Run Code Online (Sandbox Code Playgroud)

现在,我们还没有打破p/3查询,并且有办法在没有回溯的情况下获得第一个解决方案.如果您愿意,可以围绕此构建一个单独的谓词:

p_once(Node, Marks, Number) :- once(p(Node, Marks, Number)).
Run Code Online (Sandbox Code Playgroud)

然后,当然:

| ?- p_once(raj,marks,100).

(1 ms) yes
| ?-
Run Code Online (Sandbox Code Playgroud)

once/1在我看来,明确使用是首选,因为它简洁明了,并且保留了原始谓词的完整性.

  • 为什么不走高端路?问题是恕我直言在不同的层面(建模,表示).`(!)/ 0`*有*它的用途,但鼓励初学者从一开始就适应"糟糕的编码+快速修复"风格,你不同意吗? (3认同)