2017-12-04 19 views
0

Prologで再帰がどのように機能するかを理解しようとしています。次のプログラムを考えてみましょう。次のPrologプログラムで予期しない動作が発生する

edge(a,b). 
edge(b,c). 
edge(c,d). 
edge(a,d). 
edge(c,e). 
path(d). 
path(Vertex) :- edge(Vertex, Next), write(Next), path(Next). 

実行パス(a)。

出力:

?- path(a). 
bcd 
true ; 
ed 
true; 
false 

私は理解して静かにしていない何がこのプログラムのループ部分です。だから我々はaで始まり、次にb、c、dに行く。いったんdを見ると、私たちはやめます。私は4行目の出力 'ed'を理解できません。なぜそれがe、dになるのか、真実に戻るのか。私はまた、どのように演算子 ';'を理解していない別の結果を照会するときに機能します。それは次の結果を得ることを意味しますか?

別の例:次のプログラムは、あるノードから別のノードへのすべての可能なパスを書き込みます。私は、このプログラムでどのようにループが動作して、異なるパスのリストを表示するのか理解していません。

link(a, b). 
    link(a, d). 
    link(b, c). 
    link(d, e). 
    link(e, c). 
    link(e, f). 
    link(f, a). 
    link(f, g). 
    link(f, j). 
    link(g, h). 
    link(h, i). 
    link(i, j). 


not(X) :- X, !, fail. 
not(_). 

writeallpaths(Node, Node) :- 
    write(Node), write(' is '), write(Node), nl. 
writeallpaths(Node, Next) :- 
    listpath(Node, Next, [Node], List), 
    write(Node), write(' to '), write(Next), write(' is '), 
    writepath(List), 
    fail. 

writepath([]) :- 
    nl. 
writepath([Head|Tail]) :- 
    write(' '), write(Head), writepath(Tail). 

listpath(Node, End, Outlist) :- 
    listpath(Node, End, [Node], Outlist). 

listpath(Node, Node, _, [Node]). 
listpath(Node, End, Tried, [Node|List]) :- 
    link(Node, Next), 
    not(member(Next, Tried)), 
    listpath(Next, End, [Next|Tried], List). 
+2

基本的な教科書が必要です。プロローグの芸術は良いです。多分今はもっと良いものがあるでしょう。 –

+0

'path(d)'が達成された場合、バックトラックは停止しません。それは継続して、 'ce'パスを見つけます。 'd'で終了しないので失敗しますが、述部で' write'が使用されるため、最終的な成功または失敗が判断される前にパスが出力に書き込まれます。 @TomasByが示唆しているように、 ';'が何をしているのかわからないのであれば、テキストブックを入手するか、オンラインのPrologのドキュメントをもっと読む必要があります。 – lurker

+0

@TomasBy私はこの例を基本的な教科書から取っています。 – patzi

答えて

0

また、私は理解していないどのように演算子 ';'別の結果を照会するときに機能します。それは次の結果を得ることを意味しますか?

はい。あなたが入る時、何が起こるのですか?ソリューション "bcd"を見つけた後、Prologは代替ソリューションを見つけようとします。あなたのケースでは、 "e"への代替パスがあり、そこから "d"に達するまで検索を続けるため、 "c"に "戻る"(バックトラック)します。明らかに、Prologは最初に戻るのではなく、 "c"だけに戻るので、ソリューション "bced"全体を印刷しないので、 "c"の後のノードだけが印刷されます。

また、いつでもPrologがコードを実行する方法を詳しく見ることができるtrace/0述語を使用できます。

+0

奇妙なのは出力です。私は次のノードを印刷するために書き込みを使用しました。私はなぜそれが本当のエドを印刷するのか分からない。 – patzi

関連する問題