2016-11-30 36 views
0

我正在創建一個應該允許通過圖進行搜索的程序,但是當findall/3的調用評估爲false時,應該返回後繼節點列表的函數失敗。當我在find_successors函數之外嘗試findall函數時,它完美地工作,但由於某種原因,在find_successors函數中,它只是讀取false。通過圖形調試器,我甚至可以看到它找到所有的解決方案。下面的代碼:findall/3錯誤地評估爲false

find_successors(Start, Out) :- 
    entity(Start), 
    (findall(X, is_a(Start, X), O), append([], O, OL1); OL1 = []), 
    (findall(X, is_a(X, Start), O), OL2 = O; OL2 = []), 

    (findall(X, has(Start, X), O), append([], O, OL3); OL3 = []), 
    (findall(X, has(X, Start), O), append([], O, OL4); OL4 = []), 

    (findall(X, able_to(Start, X), O), append([], O, OL5); OL5 =[]), 
    (findall(X, able_to(X, Start), O), append([], O, OL6); OL6 = []), 

    (findall(X, used_to(Start, X), O), append([], O, OL7); OL7 = []), 
    (findall(X, used_to(X, Start), O), append([], O, OL8); OL8 = []), 

    append([OL1, OL2, OL3, OL4, OL5, OL6, OL7, OL8], Out). 

entity(wings). 
entity(fly). 
entity(bird). 
entity(legs). 
entity(feathers). 
entity('body covering'). 
entity(animal). 
entity(dog). 
entity(fur). 
entity(aves). 
entity(reptile). 
entity(snake). 
entity(scales). 

f_is_a(bird, aves). 
f_is_a(bird, animal). 
f_is_a(snake, reptile). 
f_is_a(snake, animal). 
f_is_a(dog, mammal). 
f_is_a(dog, animal). 
f_is_a(feathers, 'body covering'). 
f_is_a(fur, 'body covering'). 
f_is_a(mammal, animal). 
f_is_a(reptile, animal). 
f_is_a(aves, animal). 
is_a(X, H) :- !, f_is_a(X, H). 
is_a(X, H) :- !, \+f_is_a(X, P), H = X. 
is_a(X, H) :- !, is_a(X, P), is_a(P, H). 

f_has(bird, wings). 
f_has(bird, feathers). 
f_has(bird, legs). 
f_has(aves, wings). 
f_has(aves, feathers). 
f_has(aves, legs). 
f_has(dog, legs). 
f_has(dog, fur). 
f_has(mammal, legs). 
f_has(mammal, fur). 
f_has(snake, scales). 
f_has(reptile, scales). 
has(X, H) :- !, f_has(X, H). 
has(X, H) :- !, \+f_has(X, P), H = X. 
has(X, H) :- !, has(X, P), has(P, H). 

used_to(wings, fly). 
used_to(legs, walk). 

able_to(bird, fly). 
able_to(bird, walk). 
able_to(dog, walk). 
able_to(X, Y) :- used_to(X1, Y), has(X, X1). 

回答

2

你不斷努力,以重複使用相同的變量,但是一旦一個變量綁定,無法再次使用它。所以所有這些:

 here    here 
     |     | 
     v     v 
(findall(X, is_a(Start, X), O), append([], O, OL1); OL1 = []), 
(findall(X, is_a(X, Start), O), OL2 = O; OL2 = []), 

(findall(X, has(Start, X), O), append([], O, OL3); OL3 = []), 
(findall(X, has(X, Start), O), append([], O, OL4); OL4 = []), 

(findall(X, able_to(Start, X), O), append([], O, OL5); OL5 =[]), 
(findall(X, able_to(X, Start), O), append([], O, OL6); OL6 = []), 

(findall(X, used_to(Start, X), O), append([], O, OL7); OL7 = []), 
(findall(X, used_to(X, Start), O), append([], O, OL8); OL8 = []), 

這些線條中的每一條都非常非常奇怪。我需要將其分解,以便真正弄清楚發生了什麼。考慮只是其中之一:

( findall(X, used_to(Start, X), O), 
    append([], O, OL7) 
; OL7 = [] 
) 

(這,順便說一句,你是如何嘗試寫析取,否則他們很容易誤讀)

append([], A, B)只是一樣A = B

然後,findall/3總是成功,即使沒有解決方案;它只是給你一個空的列表!

?- findall(X, between(2, 1, X), Xs). 
Xs = []. 

所以整個事情是完全沒有必要的,你可以一樣好扔掉一切,但調用findall/3

注意事項:您使用的分離不符合您的想法。這裏是一個小例子:

?- (A = 1 ; A = 2). 

你覺得怎麼樣?

+0

平時每次都會出現最愚蠢的錯誤,我一直堅持讓自己陷入堆棧溢出的困境......但是我對你的旁註感到困惑......運行該示例後,它給了我完全的答案我曾預料過它,那就是 'A = 1; A = 2' – bendl

0

你應該建議我們致電find_successors(Start, Out)並說出預期值。

如果沒有它,很難說你的代碼在哪裏出錯,但是......有一點沒有特定的順序......

(1)append/3 concatenate將第三個參數與獲得的列表相結合,並將第一個和第二個列表中的元素連接起來;所以

append([], O, OL1) 

與沒有在它的元件的第一個參數,統一OOL1與如此是無用的;你可以寫在表格中的所有行

(findall(X, is_a(Start, X), O), append([], O, OL1); OL1 = []), 

(findall(X, is_a(Start, X), OL1) ; OL1 = []), 

(2)findall/3也返回true時統一用一個空列表(當沒有找到值)的第三個參數,所以我不明白你爲什麼寫

(findall(X, is_a(Start, X), OL1) ; OL1 = []), 

永遠不會執行第二部分(OL1 = [])時,(如果我沒看錯),當OL1是統一的[]findall/3找不到任何東西;我想你可以簡單地寫

findall(X, is_a(Start, X), OL1), 

(3)我只知道一個append三個參數;所以我不明白的

append([OL1, OL2, OL3, OL4, OL5, OL6, OL7, OL8], Out) 

你的意圖的意思是寫

append([], [OL1, OL2, OL3, OL4, OL5, OL6, OL7, OL8], Out) 

在這種情況下,考慮在計數(1)和(2),你可以寫find_successors/2僅僅作爲

find_successors(Start, [OL1, OL2, OL3, OL4, OL5, OL6, OL7, OL8]) :- 
    entity(Start), 
    findall(X, is_a(Start, X), OL1), 
    findall(X, is_a(X, Start), OL2), 
    findall(X, has(Start, X), OL3), 
    findall(X, has(X, Start), OL4), 
    findall(X, able_to(Start, X), OL5), 
    findall(X, able_to(X, Start), OL6), 
    findall(X, used_to(Start, X), OL7), 
    findall(X, used_to(X, Start), OL8). 

(4)我不喜歡的削減(!),所以也許我錯了但是...爲什麼你把!作爲is_a/2的第一個元素?

is_a(X, H) :- !, f_is_a(X, H). 
is_a(X, H) :- !, \+f_is_a(X, P), H = X. 
is_a(X, H) :- !, is_a(X, P), is_a(P, H). 

如果我沒有錯,在第一條(!, f_is_a(X, H))切斷禁用第二和第三條左右,如果f_is_a(X, H)失敗,第二和第三條款從不驗證。

你確定你的意圖不是

is_a(X, H) :- f_is_a(X, H), !. 
is_a(X, H) :- \+f_is_a(X, P), H = X, !. 
is_a(X, H) :- is_a(X, P), is_a(P, H), !. 

或更好

is_a(X, H) :- f_is_a(X, H), !. 
is_a(X, X) :- \+f_is_a(X, _), !. 
is_a(X, H) :- is_a(X, P), is_a(P, H), !. 

還是根本不切?

(5)與has/3相同的切割問題;我懷疑

has(X, H) :- !, f_has(X, H). 
has(X, H) :- !, \+f_has(X, P), H = X. 
has(X, H) :- !, has(X, P), has(P, H). 

是錯誤的,你的意圖是

has(X, H) :- f_has(X, H), !. 
has(X, H) :- \+f_has(X, P), H = X, !. 
has(X, H) :- has(X, P), has(P, H), !. 

或更好

has(X, H) :- f_has(X, H), !. 
has(X, X) :- \+f_has(X, _), !. 
has(X, H) :- has(X, P), has(P, H), !. 

或者不能切割?