2

このコードで「go」を使用しても真の答えが得られない理由を誰かが見つけることができますか?たとえば、私が書いgo(7,3,l)たところ、3リットルの水を2番目の水差しに移動する必要があると思いますが、プロローグによれば、それは誤りです。どうしたの?

:- dynamic go/3.
:- dynamic cur_state/1,init/5.
:- dynamic end_state/1, final/5.

cur_state(State):-State = state(10,0,0,7,l).
end_state(State):-State = state(0,3,3,0,r).

pour(state(D1,D2,D3,n,l),move(D,C,r),state(D,C,D3,n,r)) :-
        D is D1-n,
        C is D2+n.
pour(state(D1,D2,D3,n,r),move(D,C,l),state(D,C,D3,n,l)) :-
        D is D1-n,
        C is D2.
pour(state(D1,D2,D3,n,l),move(D,C,r),state(D,D2,C,n,r)) :-
        D is D1-n,
        C is D3+n.
pour(state(D1,D2,D3,n,l),move(D,C,r),state(D1,D,C,n,r)) :-
        D is D2-n,
        C is D3+n.
pour(state(D1,D2,D3,n,r),move(D,C,l),state(D1,D,C,n,l)) :-
        D is D2-n,
        C is D1+n.
pour(state(D1,D2,D3,n,r),move(D,C,l),state(D1,D,c,n,l)) :-
        D is D2-n,
        C is D3.
pour(state(D1,D2,D3,n,l),move(D,C,r),state(C,D2,D,n,r)) :-
        D is D3-n,
        C is D1.
pour(state(D1,D2,D3,n,r),move(D,C,l),state(D1,C,D,n,l)) :-
        D is D3-n,
        C is D2+n.
pour(state(D1,D2,D3,n,r),move(D,C,l),state(C,D2,D,n,l)) :-
        D is D3-n,
        C is D1+n.

carry(7,0).
carry(3,0).
carry(10,0).
carry(7,0).
carry(7,3).

legal(10,X,Y):-X+Y<10.
legal(X,Y,Z):-X+Y+Z<10.
legal(X,7,Y):-X+Y=<3.
legal(X,Y,3):-X+Y=<7.

newstate(state(D1,D2,D3,n,l),state(D11,D22,D33,n1,r)):-
        carry(M,C),
        M=<7,C=<3,
        D22 is D2+n,
        D11 is D1-n,
    D3 is D33,
    n1 is n,
        D2=<7,D1=<10,
    legal(D1,D2,D3).

newstate(state(D1,D2,D3,n,r),state(D11,D22,D33,n1,l)):-
        carry(M,C),
        M=<10,C=<100,
        D11 is D1-n,
    D22 is D2,
    D33 is D3,
        D1=<10,
    legal(D1,D2,D3).

newstate(state(D1,D2,D3,n,l),state(D11,D22,D33,n1,r)):-
        carry(M,C),
        M=<10,C<3,
        D11 is D1-n,
        D33 is D3+n,
    D22 is D2,
        D1=<10,D3=<3,
    legal(D1,D2,D3).

newstate(state(D1,D2,D3,n,r),state(D11,D22,D33,n1,l)):-
        carry(M,C),
        M=<7,C=<3,
        D22 is D2-n,
        D33 is D1+n,
        D11 is D1,
    D2=<7,D1=<10,
    legal(D1,D2,D3).

newstate(state(D1,D2,D3,n,l),state(D11,D22,D33,n1,r)):-
        carry(M,C),
        M=<7,C=0,
        D22 is D2-n,
        D33 is D3+n,
        D11 is D1,
    D2=<7,D3=<3,
    legal(D1,D2,D3).

newstate(state(D1,D2,D3,n,r),state(D11,D22,D33,n1,l)):-
        carry(M,C),
        M=<7,C=<100,
        D22 is D2-n,
    D33 is D3,
    D11 is D1,    
    D2=<7,
    legal(D1,D2,D3).

newstate(state(D1,D2,D3,n,r),state(D11,D22,D33,n1,l)):-
        carry(M,C),
        M=<3,C=<7,
        D22 is D2+n,
        D33 is D3-n,
        D11 is D1,
    D3=<3,D2=<7,
    legal(D1,D2,D3).

newstate(state(D1,D2,D3,n,r),state(D11,D22,D33,n1,l)):-
        carry(M,C),
        M=<3,C=<100,
        D11 is D1+n,
        D33 is D3-n,
        D22 is D2,
    D3=<3,D1=<10,
    legal(D1,D2,D3).

newstate(state(D1,D2,D3,n,l),state(D11,D22,D33,n1,r)):-
        carry(M,C),
        M=<3,C=<100,
        D33 is D3-n,
        D22 is D2,
    D11 is D1,  
    D3=<3,
    legal(D1,D2,D3).


eisodos(_):- cur_state(State),write(State),nl.

init(S1,S2,S3,S4,S5):-assert(cur_state(State):-State = state(S1,S2,S3,S4,S5)),write('Arxikh:'),
   write(state(S1,S2,S3,S4,S5)),retractall(init(S1,S2,S3,S4,S5)),nl.

final(S1,S2,S3,S4,S5):-assert(end_state(State):-State = state(S1,S2,S3,S4,S5)),write('Telikh:'),
   write(state(S1,S2,S3,S4,S5)),retractall(init1(S1,S2,S3,S4,S5)),nl.

go(Move1,Move2,Move3):-cur_state(State),newstate(State,NextState),
        pour(State,move(Move1,Move2,Move3), NextState),
        retractall(cur_state(State):-State = state(_,_,_,_,_)),asserta(cur_state(NextState)),
        ((end_state(NextState),write('Bravo!!!!')) ;(write(' ---*Eiste sthn katastash --- :'),write(NextState))),nl.
4

3 に答える 3

3

@Mogの答えを拡張して、最短の解決策を見つけたい場合は、反復深化を使用することをお勧めします。以下は、@ Mogによって投稿されたコードに基づいています(したがって、OPによって投稿されたものとはわずかに異なる同じ問題を解決します)。(移動の)リストを記述したいので、DCG表記は便利です:

solution(Path) :- length(Path, _), phrase(path([0-3, 0-5, 8-8]), Path).

path(State) --> { equivalent(State, [0-3, 4-5, 4-8]) }.
path(State0) --> [From-To],
        { move(State0, State), State = [_-From, _-To, _] },
        path(State).

equivalent(State1, State2) :- forall(member(X, State1), member(X, State2)).

move(State, [NewX-From, NewY-To|NewRest]) :-
    select(X-From, State, Rest),
    X \== 0,
    select(Y-To, Rest, NewRest),
    Fillable is To - Y,
    ToFill is min(X, Fillable),
    NewY is Y + ToFill,
    NewX is X - ToFill.

サンプルクエリ:

?- solution(Ps).
Ps = [8-5, 5-3, 3-8, 5-3, 8-5, 5-3, 3-8] .
于 2012-01-06T00:36:56.387 に答える
2

コメントで言ったように、間違ったことがたくさんあるので、あなたの現在の仕事をどうやって手伝うのかわからないでしょう。言語の基本を理解できるように、 Prologに関する優れたチュートリアル(Learn Prolog nowなど)を読むことをお勧めします。興味がある場合は、ここに問題を解決する簡単な方法があります。問題を台無しにしたくない場合は、これ以上読まないでください:](私が投稿したものは、約3/5/8の水差しと4/4の分割です)。

go(Path) :-
    solve([0-3, 0-5, 8-8], [], [], Temp),
    reverse(Temp, Path).

solve(State, _Visited, Path, Path) :-
    equivalent(State, [0-3, 4-5, 4-8]).
solve(State, Visited, Acc, Path) :-
    move(State, NewState),
    NewState = [_-From, _-To|_],
    forall(member(Past, Visited), \+ equivalent(Past, NewState)),
    solve(NewState, [NewState|Visited], [From-To|Acc], Path).

equivalent(State1, State2) :-
    forall(member(X, State1), member(X, State2)).

move(State, [NewX-From, NewY-To|NewRest]) :-
    select(X-From, State, Rest),
    X \== 0,
    select(Y-To, Rest, NewRest),
    Fillable is To - Y,
    ToFill is min(X, Fillable),
    NewY is Y + ToFill,
    NewX is X - ToFill.

プロローグについてもう少し読んだ後でコードについての説明が必要な場合は、遠慮なく!

于 2012-01-05T22:03:54.827 に答える
0

最初に修正する必要があるのは、基本的な構文です。変数は大文字で始まる必要があるため、たとえば、このルールを変更する必要があります。

pour(state(D1,D2,D3,n,l),move(D,C,r),state(D,C,D3,n,r)) :-
    D is D1-n,
    C is D2+n.

pour(state(D1,D2,D3,N,l),move(D,C,r),state(D,C,D3,N,r)) :-
    D is D1-N,
    C is D2+N.

newstate(state(D1,D2,D3,n,l),state(D11,D22,D33,n1,r)):-
        carry(M,C),
        M=<7,C=<3,
        D22 is D2+n,
        D11 is D1-n,
    D3 is D33,
    n1 is n,
        D2=<7,D1=<10,
    legal(D1,D2,D3).

newstate(state(D1,D2,D3,N,l),state(D11,D22,D33,N1,r)):-
    carry(M,C),
    M=<7,C=<3,
    D22 is D2+N,
    D11 is D1-N,
    D3 is D33,
    N1 is N,
    D2=<7,D1=<10,
    legal(D1,D2,D3).

N1は、最初のnewstate / 2プロシージャでのみ評価されていることを理解する必要があります。次に、そのルールの他のインスタンスを修正します。

次に、役に立たない動的アサーションを削除する必要があります。実際のアサート/リトラクトの使用法について考えてください。必要なのは、任意のステップで「水差し」間で「水」を移動する状態を変更することです。したがって、ループイン中に状態/5をアサート/リトラクトする必要があります。初期状態(開始プログラムでこれをアサート)から最終的な許容可能な状態に移動し、サイクルを停止するためにgoでテストします。

しかし、状態変化に基づくこのスタイルは、デバッグを非常に困難にします。代わりに、動的なaltogheterを削除し、assert / retractallを実行して、サイクル内の状態を通過させてください。

于 2012-01-06T10:17:14.033 に答える