2016-04-08 31 views
2

我想實現的Prolog二叉樹,我發現了以下錯誤:定義規則,以避免算術錯誤是/ 2序言

ERROR: is/2: Arithmetic: `z/0' is not a function 

據我所知,因爲發生此錯誤is/2的RHS尚未正確實例化。 但我發現很難找出如何在第二個tree_eval/3中實例化我的變量z。

tree_eval(_,tree(empty,Num,empty),Num). 
tree_eval(Value,tree(empty,z,empty),Value):- 
     z = Value. 
tree_eval(Value,tree(L,Op,R),Eval):- 
     tree_eval(Value,L,LEval), 
     tree_eval(Value,R,REval), 
     eval(LEval,REval,Op,Eval). 

eval(LEval,REval,Op,Result):- 
     Op = '+', 
     Result is LEval + REval. 
eval(LEval,REval,Op,Result):- 
     Op = '-', 
     Result is LEval - REval. 
eval(LEval,REval,Op,Result):- 
     Op ='/', 
     Result is LEval/REval. 

如何在此給z賦值?

在此先感謝。

+2

您需要繞過一個額外的參數,可以讓你「擡頭「這些符號常數的值。我建議在關聯列表中傳遞(參見'library(assoc)')這些用例。另外,不需要如此多的'Op =( - )'目標:只需將統一*直接拉入子句頭:'評估(+,左,右,符號,結果): - ...等等。還要注意更多的聲明性名稱,*不*表示特定的方向。 – mat

+1

'z'評估爲零元謂詞。如果你想讓Z成爲一個變量,它需要以大寫字母開頭。即使那樣,'Z = Value'也不是你想要的 - 你需要'Z是Value'。或者你的第二個謂詞可以替換爲'tree_eval(Z,樹(空,Z,空),Z)。「現在我看到它,它似乎與第一個似乎是多餘的。 – vmg

回答

4

通過z=Value你實際上是統一變量Value與原子z。如果你的意思是Z到是你有一個變量,它寫成大寫字母Z作爲@vmg指出:

tree_eval(Value,tree(empty,Z,empty),Value):- 
     Z = Value. 

在這種情況下,有趣的是考慮查詢謂詞時會發生什麼:

?- tree_eval(V,tree(empty,3,empty),E). 
E = 3 ? ; 
E = V = 3 ? ; 
no 

第一個解決方案是由您的第一個規則生成的,其中第一個參數有一個匿名變量。第二個解決方案是由你的第二個規則產生的,你要求第一個和第三個參數是相同的。所以基本上你有兩個派生路徑的值爲3在這兩種情況下。現在,讓我們來看看一個稍微大一點的樹:

?- tree_eval(V,tree(tree(empty,2,empty),+,tree(empty,3,empty)),E). 
E = 5 ? ; 
E = 5, 
V = 3 ? ; 
E = 5, 
V = 2 ? ; 
no 

第一個答案是很難suprising作爲樹的計算結果爲5的確但對於接下來的兩個解決方案?讓我們來看看這些解決方案的前景如何:術語

tree(tree(empty,2,empty),+,tree(empty,3,empty)) 

只與第三條規則相匹配,因爲子樹不是空的。所以tree_eval/3被調用的子樹tree(empty,2,empty)和產率第一溶液:(_,tree(empty,2,empty),2)

然後tree_eval/3被調用的子樹tree(empty,3,empty)與第一溶液:(_,tree(empty,3,empty),3)

現在eval(2,3,+,Eval)產量Eval=5。然而,第一個參數仍然是Value=_。因此查詢的第一個解決方案是:E=5

如果您要求其他答案,prolog會嘗試是否存在第三個目標的進一步解決方案,確定沒有,因此回溯到第二個目標:正確的子樹,實際上您的第二個規則提供:(3,tree(empty,3,empty),3)eval(2,3,+,Eval)再次貢獻Eval=5,因此查詢的第二個解決方案:E=5, V=3

如果您仍然需要更多解決方案,prolog必須進一步回溯到第一個目標:並且您的第二個規則再次提供:(2,tree(empty,2,empty),2)。現在你的第二個進球再次相匹配的第一個規則:(_,tree(empty,3,empty),3),EVAL/4再送Eval=5,所以要查詢的第三個解決方案是:E=5, V=2

回溯一個更多的時間目標2序言再次嘗試第二規則和失敗的原因第一個參數不能同時爲2和3。因此,查詢沒有第四種解決方案。

但是,如果tree_eval/3將使用相同的樹結構進行查詢,但兩者的葉子被二是,通過上面的推理,不是真的suprising有4個解決方案:

?- tree_eval(V,tree(tree(empty,2,empty),+,tree(empty,2,empty)),E). 
E = 4 ? ; 
E = 4, 
V = 2 ? ; 
E = 4, 
V = 2 ? ; 
E = 4, 
V = 2 ? ; 
no 

看着那些多種解決方案顯然你的第三個參數是提供正確的解決方案,而且你並不需要第一個參數。你也可以沒有第二條規則。通過合併建議@mat一些改進,你的斷言可能會再看看這樣的事情:

tree_evaluation(tree(empty,Num,empty),Num). 
tree_evaluation(tree(L,Op,R),Val) :- 
    tree_evaluation(L,LVal), 
    tree_evaluation(R,RVal), 
    evaluation(LVal,RVal,Op,Val). 

evaluation(L,R,+,V) :- 
    V is L + R. 
evaluation(L,R,-,V) :- 
    V is L - R. 
evaluation(L,R,/,V) :- 
    V is L/R. 

這個版本的產量獨特的答案:

?- tree_evaluation(tree(empty,3,empty),E). 
E = 3 ? ; 
no 

    ?- tree_evaluation(tree(tree(empty,2,empty),+,tree(empty,3,empty)),E). 
E = 5 ? ; 
no 
+1

不錯。不需要已經是原子的單引號術語! – mat