我建議你不要遵循JuhoÖstman提出的路徑並保持純潔 - 否則,爲什麼要在第一個例子中使用Prolog?如果你堅持邏輯範式太寬大,你會得到一些令人不快的結果。在這種情況下,Juho的謂詞絕對不同於你的,我會告訴你爲什麼。正如larsmans所說,首先,放棄無用的edu_le(A,B) :- edu_less(A,B).
規則。你會得到你原來的謂詞的少冗餘版本:
edu_le1(A, A).
edu_le1(A, B) :- edu_less(A, C), edu_le1(C, B).
它只是表現爲edu_le
,意思是:給定一個任意的查詢,它產生完全一樣的答案,除了重複(edu_le1
具有以下)。你可能只是對它感到滿意,但它仍然有一些你可能不喜歡的冗餘答案;例如,SWI下:
?- edu_le1(hs, hs)
true ;
false.
現在你可以說你不喜歡它,因爲它仍然具有冗餘false
,但如果你使用的Juho的謂詞代替(沒有無用的規則):
edu_le2(A, A) :- !.
edu_le2(A, B) :- edu_less(A, C), edu_le2(C, B).
你消除它是真的沒用的最終false
:
?- edu_le2(hs, hs)
true.
?-
,但你失去不止於此:你輸了,作爲墊的話,產生的所有次的可能性當一個變量沒有實例化Ê解決方案:
?- edu_le1(hs, B) %same, with more copies, for edu_le
B = hs ;
B = college ;
B = masters ;
B = phd ;
false.
?- edu_le2(hs, B)
B = hs. %bad!
?-
換句話說,後者謂詞不是相當於前者:edu_le
和edu_le1
具有類型edu_le(?A, ?B)
,而代替edu_le2
具有類型edu_le2(+A, +B)
(參見[1]的含義)。請確保:edu_le2
不太有用,因爲它的功能較少,因此可以在較少的上下文中重複使用。這是因爲edu_le2
中的剪切是一種紅色剪切,即剪切,它改變了引入謂詞的含義。鑑於您瞭解兩者之間的差異,您可能會滿意它。這完全取決於你想用它做什麼。
如果你想獲得最好的兩個世界,你需要在edu_le1
中引入一個適當的綠色切割,當A和B被完全實例化時,降低冗餘度。在此目的下,您必須檢查A和B在切割前是否被實例化爲相同的術語。你不能用=
來做,因爲=
不檢查,但統一。正確的操作是==
:
edu_le3(A, B) :- (A == B -> ! ; true), A = B.
edu_le3(A, B) :- edu_less(A, C), edu_le3(C, B).
注意的是,在第一條規則的附加切口才能處於激活A
和B
碰巧是同一個術語。現在的髮型是一種合適的綠色切,謂語也工作在最一般的情況下,你原來一個:
?- edu_le3(A, A).
true.
?- edu_le3(A, B). %note that A and B are not the same term
A = B ;
A = hs,
B = college ;
A = hs,
B = masters ;
A = hs,
B = phd ;
A = college,
B = masters ;
A = college,
B = phd ;
A = masters,
B = phd ;
false.
?-
與Prolog的通過所有的解決方案回溯。
我不認爲有一種方法可以消除最後的false
而不會對edu_lt
引入太強的依賴性。這是因爲我們必須保持開放的可能性,以便在後來決定用更多的基礎事實來豐富它時再探索另一個edu_lt
。所以,在我看來,這是最好的你可以擁有。
[1] SWI Prolog的參考手冊,第4.1節。
AHHHHHHHH(像聖潔啊)。謝謝。感謝上帝,我不是純粹主義者吧? – Matt 2010-10-18 04:35:02