1

私は、A *の反復で可能なすべての継承状態を見つけて、それらを[(cost、state)、...]のようなリストに入れるための述語を書いています。これは、現時点では次のようになっています。

addSuccessors(L, [], _).
addSuccessors(L, [X|T], OrigList) :- memb(OrigList, Index, X),
                                     add((X, Index), L, List2),
                                     addSuccessors(List2, T, OrigList).
addSuccessors(L, [X|[]], OrigList) :- memb(OrigList, Index, X),
                                     add((X, Index), L, L2),
                                     addSuccessors(L2, [], OrigList).

Addはリストの最後に何かを追加し、membはリストの(インデックス)番目の要素を取得します。私はそれらが機能することを知っています、そして私が一番下の述語のL2を見るとき、私はこのようなものを手に入れます

?- addSuccessors(X, [1500, 3670], [0, 0, 0, 1500, 3670]).
X = [] ;
[ (1500, 3), (3670, 4)]
X = [] ;
X = [_G1175] ;
[_G1175, (1500, 3), (3670, 4)]
X = [_G1175] ;
X = [_G1175, _G1181] ;
[_G1175, _G1181, (1500, 3), (3670, 4)]
X = [_G1175, _G1181] ;
...

[(1500、3)、(3670、4)]リストは、Xを呼び出した後のリストであるため、非常に苛立たしいものです。

どうすればこれを修正できますか?

4

2 に答える 2

1

Prolog でプログラミングしてからしばらく経ちましたが、作成中のリストと返されるリストを分離する (つまり、別のパラメーターを追加する) 必要があると思います。[X|[]] のルールは、出力変数をバインドし、再帰しないようにする必要があります。

于 2010-02-01T21:19:12.750 に答える
1

L が実際に初期値を取得する方法を考えてみてください。問題はそうではないということです。あなたがやろうとしているのは、ゼロからリストを作成することです。そのため、バインドされていない変数ではなく、空のリストから始める必要があります。これを解決する 1 つの方法は、現在の述語がアキュムレータ述語として機能できるようにするラッパー述語を作成することです。

これは次のようになります。ここで、addSuccessors_accすでに定義した句が含まれます。

addSuccessors(L, X, Y) :-
    addSuccessors_acc(L,[],X,Y).

述語の 2 番目の引数がaddSuccessors_accアキュムレータとして機能するという考え方です。アキュムレータは、再帰呼び出しごとに作成されるリストです。次に、アキュムレータ述語の基本ケースでは、最終的なリストを渡すために、アキュムレータ変数を最初の引数と統合する必要があります。例えば:

 addSuccessors_acc(L,L,_,_).

また、ergosys が指摘しているように、3 番目の句は実際には基本ケースになる可能性があります。リストの最後の要素を扱っているので、再帰する必要はありません。つまり、基本ケースを 1 つ余分な呼び出しだけ遅らせるだけです。

于 2010-02-03T00:38:44.483 に答える