2015-10-19 85 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