1

ロジックの問題を解決するために、Prolog で STRIPS Planner を定義しました。他のより単純な問題で数回試した後、より複雑な問題を解決できるかどうかを確認することにしました。私は彼にペグ ソリティアの STRIPS 定義、英語版を与え、斜めの動きができないことを考慮し、最後のボールがボードの中央に移動してそれを試してみましたが、プログラムがループに陥りました。ここに問題があります: https://en.wikipedia.org/wiki/Peg_solitaire

これが私の解決策です:

%%%%%%%%%%%%%%%%%%%%%% PLAN %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

accao(nome : move(Xi,Yi,Xf,Yf),
condicoes : [empty(Xf,Yf),ball(Xi,Yi), ball(Xm,Ym)],
efeitos : [ball(Xf,Yf), -ball(Xm,Ym),-ball(Xi,Yi), empty(Xi,Yi), empty(Xm,Ym), -empty(Xf,Yf)],
restricoes : [abs(Xf-Xi)+abs(Yf-Yi)=:=2, abs(Xf-Xi)*abs(Yf-Yi)=:=0, Xi=<Xm, Xm=<Xf, Yi=<Ym, Ym=<Yf]).

inicial([empty(5,5), ball(1,4), ball(1,5), ball(1,6), 
        ball(2,4), ball(2,5), ball(2,6),
        ball(3,4), ball(3,5), ball(3,6),
 ball(4,1), ball(4,2), ball(4,3),ball(4,4), ball(4,5),              ball(4,6),ball(4,7), ball(4,8), ball(4,9),
 ball(5,1), ball(5,2), ball(5,3),ball(5,4),            ball(5,6),ball(5,7), ball(5,8), ball(5,9),
 ball(6,1), ball(6,2), ball(6,3),ball(6,4), ball(6,5), ball(6,6),ball(6,7), ball(6,8), ball(6,9),
        ball(7,4), ball(7,5), ball(7,6), 
        ball(8,4), ball(8,5), ball(8,6),
        ball(9,4), ball(9,5), ball(9,6)]).

objectivos([ball(5,5), empty(1,4), empty(1,5), empty(1,6), 
                    empty(2,4), empty(2,5), empty(2,6),
                    empty(3,4), empty(3,5), empty(3,6),
empty(4,1), empty(4,2), empty(4,3),empty(4,4), empty(4,5), empty(4,6),empty(4,7), empty(4,8), empty(4,9),
empty(5,1), empty(5,2), empty(5,3),empty(5,4),            empty(5,6),empty(5,7), empty(5,8), empty(5,9),
empty(6,1), empty(6,2), empty(6,3),empty(6,4), empty(6,5), empty(6,6),empty(6,7), empty(6,8), empty(6,9),
                    empty(7,4), empty(7,5), empty(7,6), 
                    empty(8,4), empty(8,5), empty(8,6),
                    empty(9,4), empty(9,5), empty(9,6)]).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%




%%%%%%%%%%%%%%%%%%%%%% PRINT FUNCTION %%%%%%%%%%%%%%%%%%%%%%%%%%%
printExec([]).
printExec([A,E|T]) :- write("Action performed: "),
                  write(A),nl,
                  write("Situation: "),
                  write(E),nl,
                  printExec(T).

 writeExec([I|T]):- write("Initial Situation"),
               write(I),nl,
               printExec(T),
               write("Goal: "),
               objectivos(G),
               write(G),
               write(" satisfied."),nl.
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%




 %%%%%%%%%%%%%%%%%%%% AUXILIAR FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%
 member(E,[E|_]).
 member(E,[_|T]):-member(E,T).

 sub([],_).
 sub([H|T],L):- member(H,L),
           sub(T,L).

 remove(_,[],[]):-!.
 remove(E1, [E2|T], T):- E1 == E2, !. 
 remove(E,[H|T1],[H|T2]):- remove(E,T1,T2).

 add(E,[],[E]):-!.
 add(E1,[E2|T],[E1,E2|T]):- E1 \== E2, !. 
 add(E,[H|T1],[H|T2]):-add(E,T1,T2).

 effects([],S,S).
 effects([-H|Fx],S,N) :-!, 
                   remove(H,S,NS), 
                   effects(Fx,NS,N).
 effects([H|Fx],S,N) :- !, 
                   add(H,S,NS), 
                   effects(Fx,NS,N).

 restriction([]).                                              
 restriction([R|T]) :- R,
                  restriction(T).            
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%




 %%%%%%%%%%%%%%%%%%%%%%% PLAN EXECUTE %%%%%%%%%%%%%%%%%%%%%%%%%%%
 planExecute(P):-testPlan(P,E),writeExec(E),!.

 satisfiedGoal(E):- objectivos(Fn),!,
               sub(Fn,E).

 testPlan(Plan,[I|Exec]) :- inicial(I),              
                       testPlan(Plan,I,Exec,Fn),
                       satisfiedGoal(Fn).   

 testPlan([],Fn,[],Fn).
 testPlan([H|T],S,[H,N|Exec],Fn) :- accao(nome:H, condicoes:C,efeitos:E, restricoes:R), 
                               sub(C,S), 
                               effects(E,S,N), 
                               restriction(R), 
                               testPlan(T,N,Exec,Fn).
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%




 %%%%%%%%%%%%%%%%%%%%%%% FIND PLAN %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 plano(P) :- progressivePlan(P, 0).

 progressivePlan(P, N) :- createPlan(P,_,0,N).
 progressivePlan(P, N) :- \+ createPlan(P,_,0,N),
                     NewN is N + 1, 
                     progressivePlan(P, NewN).

 createPlan(Plan,[I|Exec],N,Max) :- inicial(I),       
                               createPlan(Plan,I,Exec,Fn,N,Max),
                               satisfiedGoal(Fn).       

 createPlan([],Fn,[],Fn,Max,Max):- !.
 createPlan([H|T],S,[H,N|Exec],Fn,Acc, Max) :- accao(nome:H, condicoes:C, efeitos:E, restricoes:R), 
                                          sub(C,S), 
                                          effects(E,S,N),
                                          restriction(R),
                                          NewAcc is Acc+1, 
                                          createPlan(T,N,Exec,Fn,NewAcc, Max). 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%`

1 つまたは 2 つの移動を行うだけで目標を単純化しようとしましたが、これは 1 つに対して機能し、2 つの移動が互いに矛盾しない場合 (既に移動されたビー玉を通過して 2 つの移動でループに入るなど) です。彼らがそうするとき、上記の目的のように:

objectivos([ボール(4,5)、空(3,5)、空(5,5)、空(6,5)])。

トレースとデバッグを試みましたが、Planner 自体ではなく、問題の定式化にあると考えていますが、問題を見つけることができないようです。何か案は?

4

1 に答える 1

0

コードに少なくとも 1 つの論理エラーがあり、いくつかの簡単なパフォーマンス調整が可能です。これにより、問題の部分的な解決策が得られます。

まず、論理エラーについて: 目標の意図された解決策objectivos([ball(4,5), empty(3,5), empty(5,5), empty(6,5)])は計画のようP = [move(3, 5, 5, 5), move(6, 5, 4, 5)]です。しかし、これらの手の 2 番目は、 の定義では合法ではありませrestricoesん。これらの制約の考え方は、移動中の他の 2 つのボールの間にあることを確認することです。これを保証する別の定式化を次に示します。Xi = 6Xf = 46 =< XmXm <= 4ball(Xm,Ym)

restricoes : [abs(Xf-Xi)+abs(Yf-Yi) =:= 2,
              abs(Xf-Xi)*abs(Yf-Yi) =:= 0,
              abs(Xf-Xm)+abs(Yf-Ym) =:= 1,
              abs(Xi-Xm)+abs(Yi-Ym) =:= 1]

これは、コードをトレースするときに以前に私を混乱させたケースも除外します。以前は、ball(Xi,Yi) = ball(Xm,Ym).

第二に、パフォーマンスを改善するには、 の定義でeffects(E,S,N)とを交換します。以前は、合法性をチェックする前に移動の効果を計算していました! プランナーによって提案されたほとんどの移動は違法であるため、これは多くの時間を無駄にします。restriction(R)createPlan/6

次に、全体を使いやすくするために、 と の定義を次のように変更できplano/1ますcreatePlan/4

 plano(P) :-
     length(P, PlanLength),
     createPlan(P, _, 0, PlanLength).

 createPlan(Plan,[I|Exec],N,Max) :- inicial(I),
                               N =< Max,
                               createPlan(Plan,I,Exec,Fn,N,Max),
                               satisfiedGoal(Fn).

これは以前の定義よりも単純であり、より適切に動作します。完全なプランを渡して合法かどうかを確認するか、固定長のリストを渡して、その長さのプランが存在するかどうかを尋ねることができます。

?- P = [_,_], plano(P).
P = [move(3, 5, 5, 5), move(6, 5, 4, 5)] ;
false.  % no more solutions

あなたの定義では、これはループしてMaxカウンターをカウントアップし、存在できないさらなる解決策を探します。

この定式化により、大きな目標に切り替えて解決策を探すことができます (これは部分的に SWI-Prolog に固有のものです)。

?- length(P, N), format('searching for solutions of length ~w~n', [N]), time(plano(P)).
searching for solutions of length 0
% 58 inferences, 0.000 CPU in 0.000 seconds (71% CPU, 2171959 Lips)
searching for solutions of length 1
% 9,709 inferences, 0.001 CPU in 0.001 seconds (100% CPU, 9123980 Lips)
searching for solutions of length 2
% 79,789 inferences, 0.009 CPU in 0.009 seconds (100% CPU, 8778416 Lips)
searching for solutions of length 3
% 477,230 inferences, 0.051 CPU in 0.051 seconds (100% CPU, 9409315 Lips)
searching for solutions of length 4
% 3,412,088 inferences, 0.361 CPU in 0.361 seconds (100% CPU, 9453315 Lips)
searching for solutions of length 5
% 30,967,699 inferences, 3.503 CPU in 3.503 seconds (100% CPU, 8840598 Lips)
searching for solutions of length 6

この時点で検索を中断する必要があり、遅くなりすぎました。より多くの微調整が確実に可能であり、私はこれを見続けるかもしれません.

于 2016-12-27T11:39:22.243 に答える