prolog中的3-jugs水不起作用

时间:2012-01-27 08:03:53

标签: prolog water-jug-problem

我有3个水罐问题要解决,但有一点小技巧。我不必使用算法,但有一个'功能'允许用户将升液从罐子移动到另一个具有初始和最终状态它也是由他写的。

例如,他写了初始值(10,0,0,0,r),第一个状态首先是10升,另外两个是零,他也写了最终(0,3,3,3,l)最终状态在两个较小的水罐中有3升,在第一个中有零。

水壶之间的“移动”发生在他写下去(7,3,r),他向右移动3升(从右到左,我们将水壶形成更大到更小)从大到第二个水壶,-7是剩下的升数,3是要移动的升数,r是方向 - 。

我已经写了这个prolog代码,但每个go-state都是假的..有谁知道为什么?

:- 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(4,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(final(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.

2 个答案:

答案 0 :(得分:1)

我复制了您的代码并使用SWI-Prolog编译,我收到了以下消息:

?- Warning: /home/carlo/prolog/jug1.pl:20:
    Singleton variables: [D3]
Warning: /home/carlo/prolog/jug1.pl:57:
    Singleton variables: [N1]
Warning: /home/carlo/prolog/jug1.pl:66:
    Singleton variables: [N1]
Warning: /home/carlo/prolog/jug1.pl:75:
    Singleton variables: [N1]
Warning: /home/carlo/prolog/jug1.pl:84:
    Singleton variables: [N1]
Warning: /home/carlo/prolog/jug1.pl:93:
    Singleton variables: [N1]
ERROR: /home/carlo/prolog/jug1.pl:102:
    evaluable `n' does not exist
ERROR: /home/carlo/prolog/jug1.pl:111:
    evaluable `n' does not exist
ERROR: /home/carlo/prolog/jug1.pl:120:
    evaluable `n' does not exist
% /home/carlo/prolog/jug1.pl compiled 0,01 sec, 32 clauses

表面代码检查揭示了其他缺陷,例如第23行的小写“c”。 您应该应用hints所有previous question

对您的代码进行分解,这将帮助您了解正在发生的事情:newstate / 2有9条规则,几乎相同。唯一的变化,错误(再次是错误变量的小写标识符)是不同的常量。看起来状态/ 5确实存在与“移动”相关的值。你应该选择这些(即最后两个参数)并传递给newstate(它应该像newstate(OldState,NumLitres,Direction,NewState))。

答案 1 :(得分:1)

很难理解你所写的内容。如果初始状态是ini(10,0,0,0,r),那么最后两个参数是什么?你只有三个水罐吗?为什么最终状态为fin(0,3,3,3,r)?最后3r是什么意思??

你有三个水壶,所以你的州只有三个值:s(A,B,C)。您似乎希望在移动中动态重新定义它。精细。您的go(...)谓词将调用retract/assert,并且必须处理逻辑。如果你希望你的用户能够说“向右倾”,你为什么还要坚持要写下水壶里剩下多少水?这似乎是错误的,您的系统必须计算该值,并使用它更新您当前的动态数据库。另外,“倒在右边”从哪里?在我看来,你的go(7,3,r)说“从一个'7'-jug倒入3升水到它右边的水壶里”,但如果是这样,为什么你需要指定数量呢? ?是不是违反了水壶问题的通常规格,你没有有任何测量能力,只是给了水壶的能力?它是否意味着“将所有的水从'7'水壶倒入'3'水壶”?如果是这样,r没有任何功能。

所以请澄清你的问题。最后, 你的水壶的能力是什么?

编辑: 好吧,在下面关于规则的评论中作出澄清之后,我会将其编码如下:

%% to be called: initial(10-10,7-0,3-0).
%% to be called: final(10-0,7-3,3-3).

initial(C1-W1,C2-W2,C3-W3):- % capacity-water_content
  retractall( jug(_,_) ), 
  asserta( jug(C1,W1) ),
  asserta( jug(C2,W2) ),
  asserta( jug(C3,W3) ).

final(C1-W1,C2-W2,C3-W3):- 
  retractall( end_jug(_,_) ), 
  asserta( end_jug(C1,W1) ),
  asserta( end_jug(C2,W2) ),
  asserta( end_jug(C3,W3) ).

jugsState(L) :- findall(X-W, jug(X,W), L). % see the state

go(Cfrom,0):-  !, % pour out the water
  retract( jug(Cfrom,_) ), 
  asserta( jug(Cfrom,0) ),
  is_final_state.

go(Cfrom,Cto):-
  retract( jug(Cfrom,Wfrom) ),
  retract( jug(Cto,Wto) ),
  Space is Cto-Wto,
  (  Wfrom >= Space
  -> Wleft is Wfrom - Space,
     asserta( jug(Cfrom,Wleft) ),
     asserta( jug(Cto,Cto) )
  ;  Wnew is Wto+Wfrom,
     asserta( jug(Cfrom,0) ),
     asserta( jug(Cto,Wnew) ) ),
  is_final_state.

is_final_state :- true.

现在剩下的就是定义is_final_state,它将检查jug个事实,查看是否已达到最终状态,如果是,则打印出祝贺消息,并始终返回true 。或类似的东西。样本运行可以是例如。

?- initial(10-10,7-0,3-0).
?- final(10-0,7-3,3-3).
?- go(10,7).
?- go(7,3).
?- go(7,0).
?- jugsState(X).
X = [7-0, 3-3, 10-3]
?- ....