% Figure 17.5 A simple means-ends planner. :- op( 900, fy, not). % not Goal): negation as failure; % Note: This is often available as a built-in predicate, % often written as prefix operator "\+", e.g. \+ likes(mary,snakes) not Goal :- Goal, !, fail ; true. % A simple means-ends planner % plan( State, Goals, Plan, FinalState) plan( State, Goals, [], State) :- % Plan is empty satisfied( State, Goals). % Goals true in State % The way plan is decomposed into stages by conc, the % precondition plan (PrePlan) is found in breadth-first % fashion. However, the length of the rest of plan is not % restricted and goals are achieved in depth-first style. plan( State, Goals, Plan, FinalState) :- conc( PrePlan, [Action | PostPlan], Plan), % Divide plan select( State, Goals, Goal), % Select a goal achieves( Action, Goal), % Relevant action can( Action, Condition), plan( State, Condition, PrePlan, MidState1), % Enable Action apply( MidState1, Action, MidState2), % Apply Action plan( MidState2, Goals, PostPlan, FinalState). % Achieve remaining goals % satisfied( State, Goals): Goals are true in State satisfied( State, []). satisfied( State, [Goal | Goals]) :- member( Goal, State), satisfied( State, Goals). select( State, Goals, Goal) :- member( Goal, Goals), not member( Goal, State). % Goal not satisfied already % achieves( Action, Goal): Goal is add-list of Action achieves( Action, Goal) :- adds( Action, Goals), member( Goal, Goals). % apply( State, Action, NewState): Action executed in State produces NewState apply( State, Action, NewState) :- deletes( Action, DelList), delete_all( State, DelList, State1), !, adds( Action, AddList), conc( AddList, State1, NewState). % delete_all( L1, L2, Diff) if Diff is set-difference of L1 and L2 delete_all( [], _, []). delete_all( [X | L1], L2, Diff) :- member( X, L2), !, delete_all( L1, L2, Diff). delete_all( [X | L1], L2, [X | Diff]) :- delete_all( L1, L2, Diff).