我正在 Prolog 的状态空间中研究搜索策略,我正在查看以下程序,这是著名的水壶问题,为简单起见,您有 2 个水壶(4 升和 3 升),您可以装满、倒空和将水转移到另一个水壶中,直到第一个是空的或第二个是满的。目标是有 2 升(水罐没有任何测量值)。这个实现应该是广度优先。
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).
我不清楚的是如何理解这是 beadthfirst 而不是 depth first 例如,查看代码。我正在“人工智能的Prolog编程”(I.Bratko)一书中查看BF的实现,这对我来说似乎不同,因为它保留了所有备选候选者(在我的情况下为节点或状态)与他们的路径(如理论上应该)。另一个问题:BF 应该首先找到最短路径,但这是我的程序的响应:
init state(0,0)
fillA state(4,0)
fillB state(4,3)
emptyA state(0,3)
emptyBinA state(3,0)
fillB state(3,3)
fillAwithB state(4,2)
emptyA state(0,2)
emptyBinA state(2,0)
显然这不是最短路径,操作 2 和 4 是不必要的。
其他详细信息:我尝试使用跟踪执行,但似乎不是明确的 BF,因为从“state(0,0)”开始,唯一可直接到达的状态是“state(4,0)”和“state(0, 3)",然后在 BFS 中访问这 3 个节点,但是查看跟踪,它们不是,在 state(4,0) 之后它访问 state(4,3)。现在你能确认我走的是正确的路而且这不是 BFS 吗?但是尝试遵循 Bratko 实现我有一个问题:我应该枚举每个节点及其后继节点,我认为这对于水壶问题是不可行的。有什么提示吗?