我有一个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 多媒体设计 等......无限地
答案 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
谓词所示。