2016-02-16 44 views
2

給出了一組通過謂詞parent/2來表示父子關係的事實,當定義關係「祖先」(祖先)與謂詞pred1時有什麼區別/ 2PRED2/2如下所示?Prolog - 祖先謂詞實現的兩種方式

pred1(X,Z) :- parent(X,Z). 
pred1(X,Z) :- parent(X,Y), pred1(Y,Z). 

pred2(X,Z) :- parent(X,Z). 
pred2(X,Z) :- parent(Y,Z), pred2(X,Y). 

回答

4

主要區別是兩者的終止屬性,只要關係中有一些循環。爲了理解這一點,我將使用一個failure-slice,它將本程序的本質劃分爲w.r.t.終止。

 
pred1(X,Z) :- false, parent(X,Z). 
pred1(X,Z) :- parent(X,Y), pred1(Y,Z). % Z has no influence 

pred2(X,Z) :- false, parent(X,Z). 
pred2(X,Z) :- parent(Y,Z), pred2(X,Y). % X has no influence 

對於pred1/2,第二個參數對終止根本沒有影響,而在pred2/2,第一個參數沒有影響。看到這一點,嘗試原始的定義:與事實:

 
parent(a,a). 

?- pred1(b, _), false. % terminates 
?- pred2(b, _), false. % loops 

?- pred1(_, b), false. % loops 
?- pred2(_, b), false. % terminates 

的一般方法,以避免此類循環見closure/3

爲了完整起見,在這裏是具有某種概念的優點傳遞閉包的另一種變型:

pred3(X,Z) :- parent(X,Z). 
pred3(X,Z) :- pred3(X,Y), pred3(Y,Z). 

唉,其終止性質是最差的。事實上,它從未結束,如IS證明由下面的片段:

 
pred3(X,Z) :- false, parent(X,Z). 
pred3(X,Z) :- pred3(X,Y), false, pred3(Y,Z). 

在這個片段中,第一個參數是隻傳遞。所以,無論什麼爭論,程序總是會循環的!

 
?- pred3(b,b), false. % loops