Prolog计划员只生成一个计划

时间:2013-06-17 20:41:53

标签: prolog artificial-intelligence planning

我有一个prolog规划器,它正确地解决了当时只生成一个计划的一个主要问题。该计划是正确的,但对于我的申请,我真的需要有所有可能的计划。

plan(State, Goal, _, Moves) :-  subsetB(Goal,State),
                            write('moves are'), nl,
                            reverse_print_stack(Moves).
plan(State, Goal, Been_list, Moves) :-
                            effects(Name, [Preconditions, Add,Delete]),  //a list of of rules governing the domain
                            conditions_met(Preconditions, State),       //checks if all preconditions are present in the state
                            change_state(State, Add,Delete, Child_state), //add predicates from Add list, removes predicates in the Delete list and stores result in Child_state
                            \+(member_state(Child_state, Been_list)),     //checks if Child_state hasn't been previously visited
                            stack(Child_state, Been_list, New_been_list),
                            stack(Name, Moves, New_moves),
                    plan(Child_state, Goal, New_been_list, New_moves).


change_state(S, [],[], S).
change_state(S, [], Delete, S_new) :-   change_state(S, [],[], S2),
                                    apply_del(Delete, S2, S_new).
change_state(S, Add,Delete, S_new) :-   change_state(S, [], Delete, S2),
                                    apply_add(Add, S2, S_new).


apply_add([],State,State).
apply_add([activate(App)|Rest],State,InterimState) :-apply_add(Rest,State,S2),find_stones(App,State,StonesToBeActivated), make_active(StonesToBeActivated,S2, InterimState).
apply_add([First|Rest],State,InterimState) :- apply_add(Rest,State,S2),add_element(First, S2, InterimState).


apply_del([],InterimState,InterimState).
apply_del([First|Rest],InterimState,NewState) :- apply_del(Rest, InterimState,S2),del_element(First, S2, NewState).



subsetB([],_).
subsetB([F|R],S) :- member(F,S),subsetB(R,S).



%dropping a stone inside app1 
 effects(drop(X,app1),                     %action
   [[stone(X),active(X)],                  %preconditions
    [in(app1,X)],                          %postconditions : add list
    [active(X)]]).                         %postconditions : delete list

go(S,G,AllPlans):- findall(Moves, plan(S,G,[S],Moves),AllMoves).

conditions_met(P, S) :- subsetB(P, S).

示例通话    go([in(app1,s1),stone(s2),active(s2),stone(s3),active(s3)],[in(app1,s1),in(app1,s3)in(app1, S2)],AllPlans)。

答案:

降(S2,APP1) drop(s3,app1)//正确 _2368 _2366 碱性食物 五里坡景观民宿 _2360 _2358 心灵励志 _2354 _2352 _2350 _2348 中文之美 _2344 _2342 _2340 _2338 多媒体设计 等......无限地

1 个答案:

答案 0 :(得分:2)

要查找目标的所有解决方案,请查看bagof or findall。或者我错过了什么?

像这样:

?- findall(Moves, plan(State, Goal, _, Moves), AllMoves).

这些谓词的全部思想是,您要说明要收集哪些参数,并获取该谓词下所有可能实例化的列表。从这个意义上讲,您通常会有一个“返回”值(一个可以用结果实例化的参数),然后您可以查看或打印它,而不是在找到解决方案的谓词中明确打印它。

一个简单的例子:

foo(1). foo(2). foo(3). foo(4). foo(5). foo(6).
bar(R) :- foo(A), A mod 2 =:= 0.

findall(R, bar(R), Even).

现在递归:它是如何工作的?您不能在同一谓词的不同子句之间共享变量。例如,这是错误的:

baz(0, B).
baz(X, B) :- X0 is X - 1, B1 is B + 1, baz(X0, B1).

因为B是baz的第一个子句中的单例变量。相反,你可以这样做:

baz(0, B, B).
baz(X, B, Result) :- X0 is X - 1, B1 is B + 1, baz(X0, B1, Result).

您现在可以致电:

?- baz(10, 2, Result).
Result = 12

但在第一次回答后你仍会遇到问题。

您获得单个正确的计划可能是,因为plan的第一个子句不符合subsetB的要求,您将进入第二个子句。在那里,你创建了一个 Moves ,它的尾部有一个自由变量,但这还不是问题。但问题是,当您找到第一个解决方案(全部在第二个plan子句中,递归)时, Moves 现在绑定到一个操作列表,而不是开始寻找新的解决方案,你再次进入第二个子句通过回溯,已经填充了 Moves ,这可能会混淆算法的其余部分。

为了使其正确,您可能需要确保在plan回溯时,它开始寻找新的解决方案,并使用干净的 Moves 。您可以首先将 Moves 实例化为空列表并在累加器中收集结果,如上面简单的baz谓词所示。