2017-03-26 14 views
2

私は、グラフ上のパスファインドであるProlog(gprolog)でプログラムを書いています。私は部分的にそれに基づいてthis SO postに基づいています。名前のない変数を書く

例を挙げておきます。ここで私が描いたグラフ例は次のとおりです。example graph

そしてここでは、コードが最初のように見えたものです:

path([Goal],Goal,Goal). 
path(P,Start,Goal) :- adjacent(Start,X), 
         \+ (memberchk(X,P)), 
         (
         Goal=X 
         ; 
         path([Start|P],X,Goal) 
        ). 

かかわらず、その基本ケースが冗長であるかどうかの、ここでの問題があります。私は

| ?- path(P,a,f). 

の入力スタイルをしたいし、その入力のために、私は、しかし、それはmemberchkと嘘を立つようなコードに問題があることを

P = [a,s,f] 

true ? 

の出力を得るでしょう。 memberchk(a,P)の場合は、統合を試み、memberchk(a,[a|_])を呼び出し、trueを返します。私はこれが起きたくないので、最初にvar/1述語を使ってPがインスタンス化されているかどうかをチェックします。 Pがインスタンス生成されている場合このように、私のコードは

path([Goal],Goal,Goal). 
path(P,Start,Goal) :- var(P), 
         path([],Start,Goal). 
path(P,Start,Goal) :- adjacent(Start,X), 
         \+ (memberchk(X,P)), 
         (
         Goal=X 
         ; 
         path([Start|P],X,Goal) 
        ). 

に変更今、私たちは、空のリストでpath/3を呼び出します。 私の問題はこれです:path([],Start,Goal)P[]に関連付けられていないので、最後にPを印刷できません。

私はwrite/1述語を使用して試してみましたが、それはどちらかのすべてのステップでPをプリントアウトしたりP = _26(それがインスタンス生成PPのではなく、最終的な値を印刷していますという意味)に印刷します。

私はこれが単純な問題であることを願っています。私はPrologを非常に新しくしています。

似たようなことがある場合はお詫び申し上げます。私は助けることができる他の質問に指摘したいと思う。私はそれを投稿する前にSOとGoogleを検索しました。

+1

[この質問](http://stackoverflow.com/q/30328433/7473772)を参照してください。おそらく有用な一般化を示しているでしょうか? –

答えて

0

は、私は私の問題を解決しました。何かがないたかったのではない時に統一することを防止するために、リストのメンバーであるかどうかの確認小さいリスト

  • に再帰、訪れたノード
    1. キープトラック再帰:ソリューションに依存しています

    次のように私のコードは次のとおりです。

    connected(X,Y) :- adjacent(X,Y);adjacent(Y,X). 
    
    not_member(_, []). 
    not_member(X, [Head|Tail]) :- X \== Head, not_member(X, Tail). 
    
    path(P,A,B):-path_helper(P,A,B,[Start]). 
    
    path_helper([X,Y],X,Y,_):-connected(X,Y). 
    path_helper([Goal],Goal,Goal,_). 
    path_helper([Start|[Head|P]],Start,Goal,Visited):-connected(Start,Head),not_member(Head,Visited),path_helper([Head|P],Head,Goal,[Head|Visited]). 
    
  • 2

    必要な概念がアキュムレータ

    のあなたは非常に近く、実際にあったことがある:あなたが実際に実現している[]からPを初期化し、そしてあなたが作業戦略再帰たよう[Start|P]でそれを埋めます。これはアキュムレータと呼ばれ、最終結果を得るには、単にに別の引数を加えるだけです。ここで

    が照会新しいpath/3述語です:あなたが見ることができるように

    path(P, Start, Goal) :- 
        path([], P, Start, Goal). 
    

    、ここで我々はこのように実装され、path/4の最初の引数として[]を追加します。

    path(L, P, Goal, Goal) :- 
        reverse([Goal|L], P). 
    path(L, P, Start, Goal) :- 
        adjacent(Start, X), 
        \+ (memberchk(X, L)), 
        path([Start|L], P, X, Goal). 
    

    最初の句は再帰を終了するためのものです。 StartGoalの引数が指定したものと同じになると、再帰は終了します。アキュムレータを使用する場合、これはアキュムレータを出力引数で統一することを意味します。しかし、アキュムレータには逆の回答が含まれているため(最終目標はありません)、reverse([Goal|L], P)です。

    第2節はあなたが書いたものに非常によく似ていますが、ここでは再帰節にPをそのまま渡す必要があります。その節であなたの論理和を削除しましたが、その場合は不要です。

    完全なコードは:

    path(P, Start, Goal) :- 
        path([], P, Start, Goal). 
    path(L, P, Goal, Goal) :- 
        reverse([Goal|L], P). 
    path(L, P, Start, Goal) :- 
        adjacent(Start, X), 
        \+ (memberchk(X, L)), 
        path([Start|L], P, X, Goal). 
    
    +0

    固定長パスで終了することはできません。 – false

    +0

    これは私が最初に持っていたのと同じ問題を抱えています。これは 'memberchk(X、L)'に依存しています。 –

    +0

    @TylerDurden私が見ることができる限り、あなたが質問で尋ねるもののために働くので、「意図した」ものが何を意味するのかをより明確に説明してください。 – Fatalize

    関連する問題