prolog中多个目标的fluent

prolog中多个目标的fluent,prolog,Prolog,这是一个区块世界的问题,它将把区块移动到我们想要的地方。 位于上的predict根据fluent告诉我们块的位置。goal_state是我们想要块的位置 位于上的的第三个参数是情境(fluents),表示动作历史 fluent从空列表开始,表示尚未执行任何操作。在每个动作之后,我们将动作添加到第三个参数fluent中 例如,如果我们把a移到b,然后把b移到c,然后把c移到d,那么流畅的语言将是[移动(c,d),移动(b,c),移动(a,b)]。我们可以根据fluents(它们的动作历史)知道每个

这是一个区块世界的问题,它将把区块移动到我们想要的地方。 位于上的predict
根据fluent告诉我们块的位置。
goal_state
是我们想要块的位置

位于
上的
的第三个参数是情境(fluents),表示动作历史

fluent空列表开始,表示尚未执行任何操作。在每个动作之后,我们将动作添加到第三个参数fluent中

例如,如果我们把a移到b,然后把b移到c,然后把c移到d,那么流畅的语言将是
[移动(c,d),移动(b,c),移动(a,b)]
。我们可以根据fluents(它们的动作历史)知道每个块在哪里

%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\u state:-位于(a,b,S)
,我可以得到所有可能的fluents:

?- 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] 
但是当我有多个目标时,比如说
目标状态:-位于(a,b,S),位于(d,区域2,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).
我将
计划(L):-初始状态(I)、目标状态(G)、可到达状态(I、L、G)替换为
计划(L):-初始状态(I)、可到达状态(I、L、G)、目标状态(G)。

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

以下是序言中的答案:

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

在这个公式中,您无法完全摆脱无限递归,因为将块在新状态之间来回移动会在图中创建一个循环,对应于无限列表

您可以先将解决方案与任意列表统一起来,执行迭代深化搜索:

:- length(S,_), goal_state(S).
首先,用一个长度为0的列表统一S,在该列表上尝试目标状态。尝试所有长度为an的列表后,长度与长度为1的列表一致,以此类推


编辑:感谢mat确定了正确的搜索策略

在这个公式中,您无法完全摆脱无限递归,因为将块在新状态之间来回移动会在图中创建一个循环,对应于无限列表

您可以先将解决方案与任意列表统一起来,执行迭代深化搜索:

:- length(S,_), goal_state(S).
首先,用一个长度为0的列表统一S,在该列表上尝试目标状态。尝试所有长度为an的列表后,长度与长度为1的列表一致,以此类推


编辑:感谢mat确定了正确的搜索策略

你能详细解释一下第三个参数吗?我想这是一个列表,但它包含什么?我已经重新编辑了这个问题。谢谢。如果S包含移动(a,b),你问(a,b,S)上的位置,你期望什么?我只是想知道可能导致b上a的所有可能性。你能解释更多关于第三个参数的信息吗?我想这是一个列表,但它包含什么?我已经重新编辑了这个问题。谢谢。如果S包含移动(a,b),你问(a,b,S)的位置,你期待什么?我只是想知道所有可能导致b+1上a的可能性,但这不是广度优先搜索(BFS):它是深度优先迭代深化,在相当一般的假设下,这是一种时间和空间上的渐近最优搜索方法。谢谢!我找到了另一种解决问题的方法,首先统一S,然后使用预测目标状态。+1,但这不是广度优先搜索(BFS):它是深度优先迭代深化,这是一种在相当普遍的假设下在时间和空间上渐近最优的搜索方法。谢谢!我找到了另一种解决问题的方法,首先统一S,然后使用预测目标状态。