Prolog の状態空間での検索戦略を研究しています。次のプログラムを見ています。これは有名な水差しの問題です。簡単にするために、2 つの水差し (4 リットルと 3 リットル) があり、水を入れたり、空にしたり、水を入れたりすることができます。最初の水差しが空になるか、2 番目の水差しがいっぱいになるまで、水をもう一方の水差しに移します。目標は 2 リットルを確保することです (水差しには計量がありません)。この実装は幅優先である必要があります。
go:-solution(S).
solution(ActionList):-init(I),nl,write(init),tab(4),write(I),
nl,solution(I,[],ActionList),!.
solution(State,VisitedStates,[]) :- final(State).
solution(State,VisitedStates, [Action|Rest]) :- applicable(Action,State) ,
apply(Action,State,NewState),
\+visited(NewState,VisitedStates), write(Action), tab(4) , write(NewState), nl,
solution(NewState,[State|VisitedStates],Rest).
visited(State,[VisitedState|OtherVisitedStates]) :- sameState(State,VisitedState).
visited(State,[VisitedState|OtherVisitedStates]) :- visited(State,OtherVisitedStates).
sameState(S,S).
init(state(0,0)).
final(state(2,X)).
applicable(emptyA,state(Qa,Qb)) :- Qa > 0.
applicable(emptyB,state(Qa,Qb)) :- Qb > 0.
applicable(fillA,state(Qa,Qb)) :- Qa < 4.
applicable(fillB,state(Qa,Qb)) :- Qb < 3.
applicable(emptyAinB,state(Qa,Qb)) :- Qa > 0 , Qtot is Qa + Qb , Qtot =< 3.
applicable(emptyBinA,state(Qa,Qb)) :- Qb > 0, Qtot is Qa + Qb , Qtot =< 4.
applicable(fillAwithB,state(Qa,Qb)) :- Qa < 4, Qtrasf is 4 - Qa , Qtrasf =< Qb.
applicable(fillBwithA,state(Qa,Qb)) :- Qb < 3, Qtrasf is 3 - Qb , Qtrasf=<Qa.
apply(emptyA,state(Qa,Qb),state(0,Qb)).
apply(emptyB,state(Qa,Qb),state(Qa,0)).
apply(fillA,state(Qa,Qb),state(4,Qb)).
apply(fillB,state(Qa,Qb),state(Qa,3)).
apply(emptyAinB,state(Qa,Qb),state(0,Qtot)) :- Qtot is Qa+Qb.
apply(emptyBinA,state(Qa,Qb),state(Qtot,0)) :- Qtot is Qa+Qb.
apply(fillAwithB,state(Qa,Qb),state(4,NewQb)) :- NewQb is Qb-(4-Qa).
apply(fillAwithB,state(Qa,Qb),state(NewQa,3)) :- NewQa is Qa-(3-Qb).
私には明確ではないのは、コードを見て、たとえば深さではなくビーズが先であることを理解する方法です。私は本「人工知能のためのプロローグプログラミング」(I.Bratko) で BF の実装を見ていますが、すべての代替候補 (私の場合はノードまたは状態) をパス (として理論上のはずです)。別の問題: BF は最初に最短パスを見つける必要がありますが、これは私のプログラムの応答です:
init state(0,0)
fillA state(4,0)
fillB state(4,3)
emptyA state(0,3)
emptyBinA state(3,0)
fillB state(3,3)
fillAwithB state(4,2)
emptyA state(0,2)
emptyBinA state(2,0)
明らかに、これは最短経路ではありません。操作 2 と 4 は不必要です。
追加の詳細: トレースで実行しようとしましたが、「state(0,0)」から開始して直接到達可能な状態は「state(4,0)」と「state(0, 3)"、次に BFS でこれらの 3 つのノードを訪問しますが、トレースを見ると、状態 (4,0) の後に状態 (4,3) を訪問します。これで、私が正しい道を進んでおり、これが BFS ではないことを確認できますか? しかし、Bratko の実装に従おうとすると、問題があります。すべてのノードとその後続ノードを列挙する必要があります。水差しの問題では実行できないと思います。ヒントはありますか?