Prolog 序言-水壶的广度优先搜索
我在研究Prolog中状态空间的搜索策略,我在看下面的程序,是著名的水壶问题,为了简单起见,你有两个水壶,4升和3升,你可以填充,清空,然后把水转移到另一个水壶,直到第一个水壶空了或者第二个水壶满了。我们的目标是有2升的水壶没有任何测量。 这种实现应该是广度优先的Prolog 序言-水壶的广度优先搜索,prolog,shortest-path,water-jug-problem,Prolog,Shortest Path,Water Jug Problem,我在研究Prolog中状态空间的搜索策略,我在看下面的程序,是著名的水壶问题,为了简单起见,你有两个水壶,4升和3升,你可以填充,清空,然后把水转移到另一个水壶,直到第一个水壶空了或者第二个水壶满了。我们的目标是有2升的水壶没有任何测量。 这种实现应该是广度优先的 go:-solution(S). solution(ActionList):-init(I),nl,write(init),tab(4),write(I), nl,solution(I,[
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).
显然这不是最短路径,操作2和4是不必要的
其他详细信息:我尝试使用跟踪执行,但似乎不是BF,因为从state0,0开始,唯一可直接访问的状态是state4,0和state0,3,然后在BFS中,这3个节点将被访问,但查看跟踪,它们不是,在state4,0之后,它将访问state4,3。现在你能确认我走对了路,这不是BFS吗?但是试图遵循Bratko实现我有一个问题:我应该列举每个节点及其后续节点,我认为这对于水壶问题是不可行的。有什么提示吗?根据BFS的Bratko实现和提供的状态表示找到了解决方案。这是我的最终代码,我验证了这是一个BFS跟踪
go:-start(Start),solve(Start,Solution),reverse(Solution,L),print(L).
solve( Start, Solution) :-
breadthfirst( [ [Start] ], Solution).
% breadthfirst( [ Path1, Path2, ...], Solution):
% Solution is an extension to a goal of one of paths
breadthfirst( [ [Node | Path] | _], [Node | Path]) :-
goal( Node).
breadthfirst( [Path | Paths], Solution) :-
extend( Path, NewPaths),
append( Paths, NewPaths, Paths1),
breadthfirst( Paths1, Solution).
extend( [Node | Path], NewPaths) :-
bagof( [NewNode, Node | Path],
( next_state( Node, NewNode), \+member( NewNode, [Node | Path] ) ),
NewPaths),
!.
extend( Path, [] ). % bagof failed: Node has no successor
% states are represented by the compound term (4-gallon jug, 3-gallon jug);
% in the initial state both jugs are empty:
start((0, 0)).
% the goal state is to measure 2 gallons of water:
goal((2, _)).
goal((_, 2)).
% fill up the 4-gallon jug if it is not already filled:
next_state((X, Y), (4, Y)) :- X < 4.
% fill up the 3-gallon jug if it is not already filled:
next_state((X, Y), (X, 3)) :- Y < 3.
% if there is water in the 3-gallon jug Y > 0) and there is room in the 4-gallon jug (X < 4) THEN use it to fill up
% the 4-gallon jug until it is full (4-gallon jug = 4 in the new state) and leave the rest in the 3-gallon jug:
next_state((X, Y), (4, Z)) :- Y > 0, X < 4,
Aux is X + Y, Aux >= 4,
Z is Y - (4 - X).
% if there is water in the 4-gallon jug (X > 0) and there is room in the 3-gallon jug (Y < 3) THEN use it to fill up
% the 3-gallon jug until it is full (3-gallon jug = 3 in the new state) and leave the rest in the 4-gallon jug:
next_state((X, Y), (Z, 3)) :- X > 0, Y < 3,
Aux is X + Y, Aux >= 3,
Z is X - (3 - Y).
% there is something in the 3-gallon jug (Y > 0) and together with the amount in the 4-gallon jug it fits in the
% 4-gallon jug (Aux is X + Y, Aux =< 4) THEN fill it all (Y is 0 in the new state) into the 4-gallon jug (Z is Y + X):
next_state((X, Y),(Z, 0)) :- Y > 0,
Aux is X + Y, Aux =< 4,
Z is Y + X.
% there is something in the 4-gallon jug (X > 0) and together with the amount in the 3-gallon jug it fits in the
% 3-gallon jug (Aux is X + Y, Aux =< 3) THEN fill it all (X is 0 in the new state) into the 3-gallon jug (Z is Y + X):
next_state((X, Y),(0, Z)) :- X > 0,
Aux is X + Y, Aux =< 3,
Z is Y + X.
% empty the 4-gallon jug IF it is not already empty (X > 0):
next_state((X, Y), (0, Y)) :- X > 0.
% empty the 3-gallon jug IF it is not already empty (Y > 0):
next_state((X, Y), (X, 0)) :- Y > 0.
print([]).
print([H|T]):-write(H),nl,print(T).
并重新定义了打印谓词:
print([],_).
print([H|T],0):-write(start),tab(4),write(H),nl,print(T,H).
print([H|T],Prev):-action(Prev,H,X),write(X),tab(4),write(H),nl,print(T,H).
action((_,Y),(4,Y),fill1).
action((X,_),(X,3),fill2).
action((_,Y),(4,Z),put(2,1)):-Y\=Z.
action((X,_),(Z,3),put(1,2)):-X\=Z.
action((X,_),(Z,0),put(2,1)):-X\=Z.
action((_,Y),(0,Z),put(2,1)):-Y\=Z.
action((_,Y),(0,Y),empty1).
action((X,_),(X,0),empty2).
print([],_).
print([H|T],0):-write(start),tab(4),write(H),nl,print(T,H).
print([H|T],Prev):-action(Prev,H,X),write(X),tab(4),write(H),nl,print(T,H).