2012-01-15 50 views
1

我已經有了一個完整的事實,如數據庫:序言 - 幫助理解規則

checkpoint(checkpoint1,checkpoint2,2). 
checkpoint(checkpoint2,checkpoint3,3). 
checkpoint(checkpoint3,checkpoint4,4). 
checkpoint(checkpoint4,checkpoint5,2). 
checkpoint(checkpoint5,checkpoint6,2). 

e.g檢查點(firstcheckpoint,secondcheckpoint,timeinminutes)。

那麼下面的規則測試,如果一個旅程是在比賽中兩個檢查點之間可能:

journey(X,Y):- checkpoint(X,_,_), checkpoint(_,Y,_),!; checkpoint(Y,_,_), checkpoint(_,X,_),!. 

journey(X,Y):- checkpoint(X,Z,_), journey(Z,Y). 
journey(X,Y):- checkpoint(Z2,Y,_), journey(X,Z2). 

請注意,你不能跳過關卡,你只能得到首先要1,2接3〜checkpoint4 。然而,你可以倒退,例如從檢查點4返回到3.

我知道如果在X和Y之間存在一箇中間檢查點,在這種情況下,該代碼檢查兩個檢查點之間是否可能旅程是Z.但我不太明白Z2在做什麼。我認爲它只是被用作另一個像Z這樣的中間體,然而爲什麼它被命名爲不同的變量呢?不能Z2只是改變爲Z,它仍然會工作?

回答

1

Z2在上一條規則中絕對可以重命名爲Z,規則的邏輯不會改變。作者猶豫使用Z的原因可能是因爲該變量不表示Z在第一條規則中的做法。

就個人而言,我會用更多的描述性的變量名去 - FromTo聽起來像是不錯的候選人:

journey(From,To):- checkpoint(From,Mid,_), journey(Mid,To). 
journey(From,To):- checkpoint(Someplace,To,_), journey(From,Someplace). 
1

您可以在不改變規則的含義重命名一個變量,如果重命名所有的發生的方式相同。

但是第一次旅程規則對我來說看起來很不對勁:您預計會有什麼效果呢? 該分解沒有機會工作,導致第一次切割。

只留下第一個規則,然後嘗試?- findall((X,Y),journey(X,Y),L). 您將看到的唯一答案L = [ (checkpoint1, checkpoint2)].

所以,從@dasblinklight答案(+1)提出了一種深度回調除了變量重命名:剛落一次出遠門規則...

編輯

此過程(不切)擴展了原有的規範,允許列舉所有可能的行程,並且可以匹配的原始定義:

journey(X, Y):- 
    journey([], X, Y). 
journey(Visited, X, Y) :- 
    (checkpoint(X, I, _) ; checkpoint(I, X, _)), 
    \+ memberchk(I, Visited), 
    (I = Y ; journey([X|Visited], I, Y)). 
+0

哼,如果我根本不包括切口,我似乎陷入了一個無限循環,在我變得真實之後,我可以繼續按下;和prolog將繼續返回true。我在添加剛剛工作的剪輯後有點擔心,但我會嘗試你在評論中所說的話。 – Arun22 2012-01-15 18:27:23

+0

做了一些測試後,看起來切割效果非常好?我通過完全刪除分隔線後的行來測試原始代碼,然後測試一個到檢查點的反向行程,如預期的那樣返回false。然而,如果我測試一個反向旅程,那麼這個分離和裁減就會返回true,這表明它的工作原理是完美的嗎? – Arun22 2012-01-15 18:45:17

+0

你是對的,刪除第一條規則禁止任何解決方案。我將編輯答案... – CapelliC 2012-01-15 19:08:28