prolog中不止一个目标的流水

时间:2013-11-17 17:10:26

标签: prolog

这是一个块世界问题,它将移动我们想要的块。  预测located_on根据流量告诉我们块的位置。 goal_state是我们想要块的地方。

located_on的第三个参数是 情境(污水) ,表示 行动历史记录

流畅的 空列表 中启动 ,这意味着尚未执行任何操作。在每个动作之后,我们将动作添加到第三个参数fluent中。

例如,如果我们将a移动到b,然后将b移动到c,然后将c移到d,则流畅度为[move(c,d),move(b,c),move(a,b)]。我们可以根据 流程(他们的行动历史) 了解每个街区的位置。

%Successor states
located_on(A,B,[move(A,B)|_]).
located_on(B,L,[_|S]) :- located_on(B,L,S).

%Goal state
goal_state(S):- located_on(a,b,S),located_on(d,area2,S).

问题在于,当我只有一个目标,比如说goal_state(S):- located_on(a,b,S)时,我可以得到所有可能的污水S:

?- goal_state(X).
X = [] ;
X = [move(a, b)|_G4037] ;
X = [_G4036] ;
X = [_G4036, move(a, b)|_G4040] ;
X = [_G4036, _G4039] ;
X = [_G4036, _G4039, move(a, b)|_G4043] ;
X = [_G4036, _G4039, _G4042] ;
X = [_G4036, _G4039, _G4042, move(a, b)|_G4046] ;
X = [_G4036, _G4039, _G4042, _G4045] ;
X = [_G4036, _G4039, _G4042, _G4045, move(a, b)|_G4049] 

但是当我有多个目标时,比如说goal_state(S):- located_on(a,b,S),located_on(d,area2,S).,我得到的一些问题就陷入了其中一个目标:

?- goal_state(X).
X = [] ;
X = [move(a, b)] ;
X = [move(a, b), move(d, area2)|_G344] ;
X = [move(a, b), _G343] ;
X = [move(a, b), _G343, move(d, area2)|_G347] ;
X = [move(a, b), _G343, _G346] ;
X = [move(a, b), _G343, _G346, move(d, area2)|_G350] ;
X = [move(a, b), _G343, _G346, _G349] ;
X = [move(a, b), _G343, _G346, _G349, move(d, area2)|_G353] ;
X = [move(a, b), _G343, _G346, _G349, _G352] ;
X = [move(a, b), _G343, _G346, _G349, _G352, move(d, area2)|_G356] ;
X = [move(a, b), _G343, _G346, _G349, _G352, _G355] ;
X = [move(a, b), _G343, _G346, _G349, _G352, _G355, move(d, area2)|_G359] 

这里的第一个元素是move(a,b),因为程序在满足move(d, area2)时会得到无限循环。 有什么方法可以帮助我摆脱无限循环

整个计划是这样的:

%Initial states
initial_state([]).
located_on(a,b,[]).
located_on(b,c,[]).
located_on(c,area1,[]).
located_on(d,area2,[]).


%Successor states
located_on(A,B,[move(A,B)|_]).
located_on(B,L,[_|S]) :- located_on(B,L,S).

%Goal state
goal_state(S):- located_on(a,b,S),located_on(d,area2,S),located_on(b,d,S),located_on(c,area1,S).

%Poss
poss(move(A,B),S) :- member(A,[a,b,c,d]),member(B,[a,b,c,d,area1,area2,area3]),
    \+A=B,clear(A,S),clear(B,S).

clear(A,S) :- member(A,[a,b,c,d,area1,area2,area3]), \+located_on(_,A,S).

%Solve problem
legal_move(S,A,[A|S]):-poss(A,S).

plan(L) :- initial_state(I), goal_state(G), reachable(I,L,G).

reachable(S,[],S).
reachable(S1,[M|L],S3) :- legal_move(S1,M,S2), reachable(S2,L,S3).

我将plan(L) :- initial_state(I), goal_state(G), reachable(I,L,G).替换为plan(L) :- initial_state(I), reachable(I,L,G), goal_state(G).

来解决问题

这意味着我们不是生成所有可能的goal_states,而是首先尝试每个可到达的位置,然后检查它们是否是目标状态。通过这种方式,我们在处理goal_state时得到统一的G.

以下是prolog的答案:

24 ?- plan([A,B,C]).
A = move(a, area3),
B = move(b, d),
C = move(a, b)  ;
false.

1 个答案:

答案 0 :(得分:4)

在这个公式中,你不能摆脱无限递归alltogther,因为在一个新状态和后面之间移动一个块会在图形中创建一个循环,它对应于一个无限列表。

您可以做的是通过首先使用任意列表解决方案来执行迭代深化搜索:

:- length(S,_), goal_state(S).

首先,S与一个长度为0的列表统一,在其上尝试了goal_state。在尝试了所有长度为a的列表之后,长度与长度为1的列表结合等等。

编辑:感谢mat用于识别正确的搜索策略!