SWI Prolog中的水壶拼图

SWI Prolog中的水壶拼图,prolog,water-jug-problem,Prolog,Water Jug Problem,我是一个AI和Prolog新手。我试图在SWI Prolog中实现2个水罐的问题。但是,我的解决方案是返回一个全局堆栈溢出 我知道这个问题过去有人问过,有很多答案/解决方案,作为一个完全的新手,我的方法有点幼稚,因此我想知道我做错了什么 问题: 有两个罐子,一个容量为4加仑,另一个最多可容纳3加仑。我需要2加仑装在4加仑的罐子里,另一个应该是空的 代码如下: member(X, [X|R]). member(X, [Y|R]) :- member(X,R). append([X|Y], Z,

我是一个AI和Prolog新手。我试图在SWI Prolog中实现2个水罐的问题。但是,我的解决方案是返回一个
全局堆栈溢出

我知道这个问题过去有人问过,有很多答案/解决方案,作为一个完全的新手,我的方法有点幼稚,因此我想知道我做错了什么

问题:

有两个罐子,一个容量为4加仑,另一个最多可容纳3加仑。我需要2加仑装在4加仑的罐子里,另一个应该是空的

代码如下:

member(X, [X|R]).
member(X, [Y|R]) :- member(X,R).

append([X|Y], Z, [X|W]) :- append(Y,Z,W).
append([], X, X).

/*                                                                                                                                            
production rules for the water jug problem                                                                                                    
*/
maneuver(X, Y, Z):-X=:=2, Y=:=0, write('done').
maneuver(X, Y, Z):-X<4, \+ member(Z, (4,Y)), append(Z, [(4,Y)], A), write('Fill 4 gallon jug\n'), maneuver(4,Y,A).
maneuver(X, Y, Z):-Y<3, \+ member(Z, (X,3)), append(Z, [(X,3)], A), write('Fill 3 gallon jug\b'), maneuver(X,3,A).
maneuver(X, Y, Z):-X>0, \+ member(Z, (0,Y)), append(Z, [(0,Y)], A), write('Empty the 4 gallon jug\n'), maneuver(0,Y,A).
maneuver(X, Y, Z):-Y>0, \+ member(Z, (X,0)), append(Z, [(X,0)], A), write('Empty the 3 gallon jug\n'), maneuver(X,0,A).
maneuver(X, Y, Z):-X+Y>=4, Y>0, \+ member(Z, (4,Y-(4-X))), append(Z, [(4,Y-(4-X))], A), write('Pour from 3 gallon jug to 4 gallon jug\n'), ma$
maneuver(X, Y, Z):-X+Y>=3, X>0, \+ member(Z, (X-(3-Y),3)), append(Z, [(X-(3-Y),3)], A), write('Pour from 4 gallon jug to 3 gallon jug\n'), ma$
maneuver(X, Y, Z):-X+Y=<4, Y>0, \+ member(Z, (X+Y, 0)), append(Z, [(X+Y, 0)], A), write('Pour the water in the 3 gallon jug into the 4 gallon$
maneuver(X, Y, Z):-X+Y=<4, Y>0, \+ member(Z, (0, X+Y)), append(Z, [(0, X+Y)], A), write('Pour the water in the 4 gallon jug into the 3 gallon$

在Prolog中,输出操作“描述”没有什么意义,因为任何失败的操作序列都将被撤消,从而尝试任何可用的替代方法。 然后,我将采取的第一步是“装饰性的一步”:移开可以从解的两个相邻步骤(列表Z)推断出的描述,并添加一个解参数

另一个重要的改进:你所有的步骤都重复相同的错误模式:例如

\+ member(Z, (4,Y)), append(Z, [(4,Y)], A)
制作一个“子程序”(并纠正错误,我认为这会导致循环):


代码中有两个错误需要更正

  • 你不能直接写或引用Y-(4-X)类方程
  • 例如:如果X=3,Y=5。 它将被认为是5 -(4-3),但它不认为它是3。因此,需要使用额外的变量来获取值

  • 您不需要编写append函数,因为您只添加了一个元素 可以直接连接到
  • Z为[(4,Y)| Z]

    修改后的代码如下所示:

    member(X,[X|_]).
    member(X,[Y|Z]):-member(X,Z).
    
    move(X,Y,_):-X=:=2,Y=:=0,write('done'),!.
    move(X,Y,Z):-X<4,\+member((4,Y),Z),write("fill 4 jug"),nl,move(4,Y,[(4,Y)|Z]).
    move(X,Y,Z):-Y<3,\+member((X,3),Z),write("fill 3 jug"),nl,move(X,3,[(X,3)|z]).
    move(X,Y,Z):-X>0,\+member((0,Y),Z),write("pour 4 jug"),nl,move(0,Y,[(0,Y)|Z]).
    move(X,Y,Z):-Y>0,\+member((X,0),Z),write("pour 3 jug"),nl,move(X,0,[(X,0)|Z]).
    move(X,Y,Z):-P is X+Y,P>=4,Y>0,K is 4-X,M is Y-K,\+member((4,M),Z),write("pour from 3jug to 4jug"),nl,move(4,M,[(4,M)|Z]).
    move(X,Y,Z):-P is X+Y,P>=3,X>0,K is 3-Y,M is X-K,\+member((M,3),Z),write("pour from 4jug to 3jug"),nl,move(M,3,[(M,3)|Z]).
    move(X,Y,Z):-K is X+Y,K<4,Y>0,\+member((K,0),Z),write("pour from 3jug to 4jug"),nl,move(K,0,[(K,0)|Z]).
    move(X,Y,Z):-K is X+Y,K<3,X>0,\+member((0,K),Z),write("pour from 4jug to 3jug"),nl,move(0,K,[(0,K)|Z]).
    
    输出为:


    您的代码被截断了,请发布一个已更正的代码。您还可以通过将
    Updated
    参数用作堆栈而不是队列来避免
    append/3
    。然而,这将以相反的顺序给出解决方案。
    update(State, Step, Updated) :-
       \+ member(Step, State),
       append(State, [Step], Updated).
    
    member(X,[X|_]).
    member(X,[Y|Z]):-member(X,Z).
    
    move(X,Y,_):-X=:=2,Y=:=0,write('done'),!.
    move(X,Y,Z):-X<4,\+member((4,Y),Z),write("fill 4 jug"),nl,move(4,Y,[(4,Y)|Z]).
    move(X,Y,Z):-Y<3,\+member((X,3),Z),write("fill 3 jug"),nl,move(X,3,[(X,3)|z]).
    move(X,Y,Z):-X>0,\+member((0,Y),Z),write("pour 4 jug"),nl,move(0,Y,[(0,Y)|Z]).
    move(X,Y,Z):-Y>0,\+member((X,0),Z),write("pour 3 jug"),nl,move(X,0,[(X,0)|Z]).
    move(X,Y,Z):-P is X+Y,P>=4,Y>0,K is 4-X,M is Y-K,\+member((4,M),Z),write("pour from 3jug to 4jug"),nl,move(4,M,[(4,M)|Z]).
    move(X,Y,Z):-P is X+Y,P>=3,X>0,K is 3-Y,M is X-K,\+member((M,3),Z),write("pour from 4jug to 3jug"),nl,move(M,3,[(M,3)|Z]).
    move(X,Y,Z):-K is X+Y,K<4,Y>0,\+member((K,0),Z),write("pour from 3jug to 4jug"),nl,move(K,0,[(K,0)|Z]).
    move(X,Y,Z):-K is X+Y,K<3,X>0,\+member((0,K),Z),write("pour from 4jug to 3jug"),nl,move(0,K,[(0,K)|Z]).
    
    move(0,0,[(0,0)]).
    
    fill 4 jug
    fill 3 jug
    pour 4 jug
    pour 3 jug
    fill 4 jug
    pour from 4jug to 3jug
    pour 3 jug
    pour from 4jug to 3jug
    fill 4 jug
    pour from 4jug to 3jug
    pour 3 jug
    done