2015-10-19 91 views
2
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). 

所以,现在,在查询时,在Prolog中停止递归?

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

172 ?- p(raj,marks,200). 
true . 

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

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

+2

这两个查询都很好地完成。你发布了错误的查询吗? – Enigmativity

+0

Raj的分数应该是100,并且应该抛出200.当我得到100时,如何停止递归? – Rahul

+3

但prolog不会“抛出错误”。当它得到第一个答案时它会停止。你的程序对'p(raj,marks,200)有效.'' connect(raj,isa,indian)和'attribute(indian,marks,200)'这些事实使规则起作用。 – Enigmativity

回答

4

我想你想让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). 

现在你的查询,表示不会走回头路,因为我认为你问,确认后的解决方案:

| ?- 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明确是首选,在我看来,因为它简洁,使意图明确,同时保留原始谓词的完整性。

+3

为什么不走高路?问题是恕我直言在不同的水平(建模,表示)。 '(!)/ 0' *有*其用途,但鼓励初学者从一开始就适应“错误编码+快速修复”风格,你不同意吗? – repeat

+1

@repeat相反,我不鼓励在这里使用cut。我解释了为什么这不是一个好主意。我相信我的回答正在说明您的评论正在做出的观点(请参阅以*开头)但是这存在问题*)!为什么downvote? – lurker

+1

好的,好点。我刚查过我的投票记录和我的名誉信息;根据我今天没有降低任何*任何*。 – repeat