2011-04-11 81 views
0

我試圖在Prolog中建模一組齒輪。並查詢兩個車輪是否通過其他鏈條連接。序言:計算出的最終條件的遞歸問題

我有一個簡單的遞歸:

connected(X,Y) :- 
    engages(X,Y). 

connected(X,Y) :- 
    engages(X,Z), 
    connected(Z,Y). 

如果我在一個硬連線謂詞來定義齧合:

engages(X,Y) :- touches(X,Y). 

touches(z1,z2). 
touches(z2,z3). 
touches(z3,z4). 

然後這個作品。

connected(z1,z4). 

測試產生真和

connected(z1,z5). 

產生假。但是,如果我用計算(即兩個半徑的總和大致是兩個中心之間的距離)來替換我的觸摸謂詞,那麼這個搜索進入看起來像無限遞歸(堆棧溢出)答案應該是錯誤的。

爲什麼這應該是,因爲我的「觸摸」計算本身並不稱之爲「連接」仿函數?是否因爲觸摸函子會試圖匹配比明確謂詞更多的原子?

這大體上是我的計算觸摸(A和B是車輪,ARAD和布拉德是其半徑,d是距離,大約是一個「近似等於」功能。

touches(A,B) :- 
    wheel(A,_,_,ARAD), 
    wheel(B,_,_,BRAD), 
    distance(A,B,D), 
    approx(D,(ARAD+BRAD),2), 
    A \== B. 

回答

3

的無限遞歸是因爲該程序不檢查週期下面是可能發生的事情:。

  1. 程序發現車輪AB,那一抹
  2. 鑑於B,我t尋找接觸的輪子。它發現A
  3. 轉到1.

可以防止這種維持一個額外的參數已經被認爲connected車輪的「封閉集合」:

connected(X,Y) :- 
    connected(X,Y,[]). 
connected(X,Y,Closed) :- 
    touches(X,Y), 
    \+ memberchk(Y,Closed). 
connected(X,Z,Closed) :- 
    touches(X,Y), 
    \+ memberchk(Y,Closed), 
    connected(Y,Z,[Y|Closed]). 

(讀者練習:縮短這個。 )

+0

OK。而且它只發生在第二種情況下,在那裏計算觸摸,因爲觸摸(A,B)和觸摸(B,A)都是真實的。讓我嘗試一下... – interstar 2011-04-11 19:29:18

+0

好吧,那太好了。謝謝。 :-) – interstar 2011-04-11 19:42:15