/graphplan.pl

http://github.com/Mortimerp9/Prolog-Graphplan · Perl · 328 lines · 240 code · 88 blank · 0 comment · 3 complexity · dd3ea5ae5b04972884c10fb9ac926538 MD5 · raw file

  1. % This file is part of the Prolog Graplan project.
  2. %
  3. % The Prolog Graplan project is free software: you can redistribute it and/or modify
  4. % it under the terms of the GNU General Public License as published by
  5. % the Free Software Foundation, either version 3 of the License, or
  6. % (at your option) any later version.
  7. %
  8. % The Prolog Graplan project is distributed in the hope that it will be useful,
  9. % but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. % GNU General Public License for more details.
  12. %
  13. % You should have received a copy of the GNU General Public License
  14. % along with the Prolog Graplan project. If not, see <http://www.gnu.org/licenses/>.
  15. % (C) 2011 Suresh Manandhar, Pierre Andrews
  16. % Graphplan Planner based on Blum & Furst 1997. Journal of AI, 90:281-300.
  17. % Pierre Andrews and Suresh Manandhar Nov 2006
  18. %
  19. :- dynamic no_op_count/1.
  20. :- dynamic mutex_action/3.
  21. :- dynamic mutex_condition/3.
  22. :- dynamic plan_graph_del/3.
  23. :- dynamic plan_graph_add/3.
  24. :- dynamic plan_graph_pre/3.
  25. plan(InitialState, FinalState, Domain, Plan):-
  26. retractall(no_op_count(_)),
  27. retractall(mutex_action(_, _, _)),
  28. retractall(mutex_condition(_, _, _)),
  29. retractall(plan_graph_del(_, _, _)),
  30. retractall(plan_graph_add(_, _, _)),
  31. retractall(plan_graph_pre(_, _, _)),
  32. assert(no_op_count(0)),
  33. add_initial_conditions(InitialState),
  34. generate_graph_nodes(1, FinalState, FinalLevel, Domain),
  35. find_plan(FinalLevel, FinalState, InitialState, [], PlanT),
  36. remove_no_ops(PlanT, Plan),
  37. nl, nl, write_plan(Plan), nl.
  38. find_plan(0, CurrentState, InitialState, Plan, Plan):-
  39. subset(CurrentState, InitialState).
  40. find_plan(N, CurrentState, InitialState, PrevActions, Plan):-
  41. N > 0,
  42. find_current_level_actions(N, CurrentState, [], CurLevelNActions, []),
  43. findall(Cond,(member(Action,CurLevelNActions), plan_graph(N, pre, Cond, Action)), PreConds),
  44. list_to_set(PreConds, MidState),
  45. % nl, write(' Level '), write(N),
  46. % nl, write('Actions : '), nl, write(CurLevelNActions),
  47. % nl, write('State : '), nl, write(CurrentState), nl,nl,
  48. N1 is N-1,
  49. find_plan(N1, MidState, InitialState, [CurLevelNActions|PrevActions], Plan).
  50. find_current_level_actions(_, [], Actions, Actions, _).
  51. find_current_level_actions(N, CurrentState, CurActions, Actions, CurAdds):-
  52. member(Pred, CurrentState),
  53. choose_action_to_achieve_pred(N, Pred, Action),
  54. not( (member(OtherAction,CurActions), mutex_action(N, Action, OtherAction)) ),
  55. findall(Cond, plan_graph(N, add, Cond, Action), AddCondsL),
  56. list_to_set(AddCondsL, AddConds),
  57. %% Plan minimality (as described in the paper) is equivalent to redundancy check
  58. %% There is no other action which has the same effect i.e. same add conditions
  59. not( (member(OtherAdds,CurAdds), subset(AddConds,OtherAdds), subset(OtherAdds,AddConds)) ),
  60. subtract(CurrentState, AddConds, CurrentStateMod),
  61. find_current_level_actions(N, CurrentStateMod, [Action|CurActions], Actions, [AddConds|CurAdds]).
  62. choose_action_to_achieve_pred(N, Pred, no_op(X)):- %% Generate shorter plans using the following strategy
  63. plan_graph(N, add, Pred, no_op(X)). %% Be lazy: prefer no ops
  64. choose_action_to_achieve_pred(N, Pred, OtherAction):- %% Choose real actions only if no ops fail
  65. plan_graph(N, add, Pred, OtherAction),
  66. OtherAction \= no_op(_).
  67. add_initial_conditions([]).
  68. add_initial_conditions([Pred|Conditions]):-
  69. add_plan_graph(0, add, Pred, start),
  70. add_initial_conditions(Conditions).
  71. generate_graph_nodes( N, _, _, _Domain):-
  72. N > 30, %% The program is probably too slow beyond this point
  73. !,
  74. nl, nl, write('Bound reached'),
  75. nl, write('Terminating.....'),
  76. fail.
  77. generate_graph_nodes( N, FinalState, N1, _Domain):-
  78. N1 is N-1,
  79. %% Check if FinalState Conditions have been satisfied
  80. %% and no mutual exclusion conditions have been violated
  81. get_nonmutex_addconds(FinalState, N1, []),
  82. nl, write('Feasible Plan found at level '), write(N1),
  83. !.
  84. generate_graph_nodes(N, _, _, _Domain):-
  85. % Add no-ops
  86. add_no_op_nodes(N),
  87. fail.
  88. generate_graph_nodes(N, _, _, Domain):-
  89. can(Action, PreConditions, Domain),
  90. NPrev is N-1,
  91. get_nonmutex_addconds(PreConditions, NPrev, []),
  92. deletes(Action, DelPreConditions, Domain),
  93. %% Instantiation Check
  94. ( ground(DelPreConditions)
  95. -> true
  96. ; (
  97. nl,
  98. write('Action not fully instantiated '), write(Action),
  99. nl,
  100. write('Del Conditions: '), write(DelPreConditions), nl
  101. )
  102. ),
  103. adds(Action, AddConditions, _, Domain),
  104. %% Instantiation Check
  105. ( ground(AddConditions)
  106. -> true
  107. ; (
  108. nl,
  109. write('Action not fully instantiated '), write(Action),
  110. nl,
  111. write('Add Conditions: '), write(AddConditions), nl
  112. )
  113. ),
  114. add_graph_nodes(PreConditions, Action, N, pre),
  115. add_graph_nodes(DelPreConditions, Action, N, del),
  116. add_graph_nodes(AddConditions, Action, N, add),
  117. % nl, write("Added Action: "), write(Action),
  118. % nl,
  119. fail.
  120. generate_graph_nodes(N, FinalState, FinalLevel, Domain):-
  121. % Propagate mutual exclusions
  122. mutex(N),
  123. N1 is N+1,
  124. !,
  125. generate_graph_nodes(N1, FinalState, FinalLevel, Domain),
  126. !.
  127. get_nonmutex_addconds([], _, _).
  128. get_nonmutex_addconds([Pred|Conditions], N, PrePreds):-
  129. plan_graph(N, add, Pred, _),
  130. check_mutex(PrePreds, Pred, N),
  131. get_nonmutex_addconds(Conditions, N, [Pred|PrePreds]).
  132. check_mutex([], _, _).
  133. check_mutex([OtherPred|Others], Pred, N):-
  134. not(mutex_condition(N, Pred, OtherPred)),
  135. check_mutex(Others, Pred, N).
  136. mutex(N):-
  137. mutex_add_del_conflict(N),
  138. mutex_precond_conflict(N),
  139. mutex_add_add_conflict(N).
  140. mutex_add_del_conflict(N):-
  141. plan_graph(N, del, Pred, Action2),
  142. ( plan_graph(N, add, Pred, Action1); plan_graph(N, pre, Pred, Action1) ),
  143. Action1 \= Action2,
  144. insert_action_conflict(N, Action1, Action2),
  145. fail.
  146. mutex_add_del_conflict(_).
  147. insert_action_conflict(N, Action1, Action2):-
  148. add_to_db(mutex_action(N, Action1, Action2)),
  149. add_to_db(mutex_action(N, Action2, Action1)).
  150. mutex_add_add_conflict(N):-
  151. mutex_action(N, Action1, Action2),
  152. plan_graph(N, add, Pred1, Action1),
  153. plan_graph(N, add, Pred2, Action2),
  154. Action1 \= Action2,
  155. Pred1 \= Pred2,
  156. not(mutex_condition(N, Pred1, Pred2)),
  157. not( (
  158. plan_graph(N, add, Pred1, Action11),
  159. plan_graph(N, add, Pred2, Action22),
  160. Action11 \= Action22,
  161. not(mutex_action(N, Action11, Action22))
  162. )
  163. ),
  164. add_to_db(mutex_condition(N, Pred1, Pred2)),
  165. add_to_db(mutex_condition(N, Pred2, Pred1)),
  166. fail.
  167. mutex_add_add_conflict(_).
  168. mutex_precond_conflict(N):-
  169. N1 is N-1,
  170. mutex_condition(N1, Pred1, Pred2),
  171. plan_graph(N, pre, Pred1, Action1),
  172. plan_graph(N, pre, Pred2, Action2),
  173. Action1 \= Action2,
  174. insert_action_conflict(N, Action1, Action2),
  175. fail.
  176. mutex_precond_conflict(_).
  177. plan_graph(N, del, Pred, Action):-
  178. plan_graph_del(N, Pred, Action).
  179. plan_graph(N, pre, Pred, Action):-
  180. plan_graph_pre(N, Pred, Action).
  181. plan_graph(N, add, Pred, Action):-
  182. plan_graph_add(N, Pred, Action).
  183. add_plan_graph(N, del, Pred, Action):-
  184. plan_graph_del(N, Pred, Action),
  185. !.
  186. add_plan_graph(N, del, Pred, Action):-
  187. assert(plan_graph_del(N, Pred, Action)).
  188. add_plan_graph(N, pre, Pred, Action):-
  189. plan_graph_pre(N, Pred, Action),
  190. !.
  191. add_plan_graph(N, pre, Pred, Action):-
  192. assert(plan_graph_pre(N, Pred, Action)).
  193. add_plan_graph(N, add, Pred, Action):-
  194. plan_graph_add(N, Pred, Action),
  195. !.
  196. add_plan_graph(N, add, Pred, Action):-
  197. assert(plan_graph_add(N, Pred, Action)).
  198. add_graph_nodes([], _, _, _).
  199. add_graph_nodes([Pred|Conditions], Action, N, Type):-
  200. add_plan_graph(N, Type, Pred, Action),
  201. add_graph_nodes(Conditions, Action, N, Type).
  202. add_no_op_nodes(N):-
  203. NPrev is N-1,
  204. plan_graph(NPrev, add, Pred, _),
  205. add_no_op_node(Pred, N),
  206. fail.
  207. add_no_op_nodes(_).
  208. add_no_op_node(Pred, N):-
  209. not((plan_graph(N, add, Pred, no_op(C)), plan_graph(N, pre, Pred, no_op(C)))),
  210. new_no_op_count(Count),
  211. add_plan_graph(N, add, Pred, no_op(Count)),
  212. add_plan_graph(N, pre, Pred, no_op(Count)).
  213. new_no_op_count(N):-
  214. retract(no_op_count(N)),
  215. N1 is N+1,
  216. assert(no_op_count(N1)).
  217. add_to_db(Clause):-
  218. call(Clause),
  219. !.
  220. add_to_db(Clause):-
  221. assert(Clause).
  222. write_plan(Plan):- write_plan(Plan,1).
  223. write_plan([], _):- nl.
  224. write_plan([Actions|Rest], N):-
  225. nl, write('Step '), write(N), write(:), nl,
  226. write_list(Actions),
  227. N1 is N+1,
  228. write_plan(Rest, N1).
  229. write_list([]).
  230. write_list([no_op(_)|L]):- !, write_list(L).
  231. write_list([X|L]):- write(' '), write(X), nl, write_list(L).
  232. remove_no_ops([],[]).
  233. remove_no_ops([no_op(_)|L],R):-
  234. !,
  235. remove_no_ops(L,R).
  236. remove_no_ops([X|L],[X1|R]):-
  237. !,
  238. remove_no_ops(X,X1),
  239. remove_no_ops(L,R).
  240. remove_no_ops(X,X).