2016-11-30 11 views
0

findall/3の呼び出しがfalseに評価されると、グラフを検索できるようにするプログラムを作成していますが、後続ノードのリストを返す関数が失敗しています。 find_successors関数の外側でfindall関数を試すと、完璧に機能しますが、何らかの理由でfind_successors関数の内部で単にfalseを読み取るだけです。グラフィカルなデバッガを使って、すべてのソリューションを見つけることさえできます。ここでは、コードです:あなたは同じ変数を再利用しようとし続けるfindall/3が誤って偽に評価されています

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 3番目の引数を、1番目と2番目のリストの要素を連結したリストと連結して連結します。その中の要素なしに最初の引数を持つよう

append([], O, OL1) 

OL1Oを統一するように役に立たないです。フォーム内のすべての行を書くことができます

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

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

(2)(値が見つからない)空のリストを持つ第三引数を統一する際にもfindall/3復帰真、そう(私は間違っていないよ場合)第二部(OL1 = [])が実行されることはありませんときに

(findall(X, is_a(Start, X), 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(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). 

としてfind_successors/2を書くことができます(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)が失敗した場合ので、第2、第3節が検証されることはありません第三句を無効にします。

あなたはあなたの意図が

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), !. 

かは全く切断されたことと思われますか?

関連する問題