University of Wisconsin - MadisonCS 540 Lecture NotesC. R. Dyer
Partial-Order Planning (Chapter 11)

Partial-Order Planning

Plan-Space Planning

Example

Interleaving vs. Non-Interleaving of Sub-Plan Steps

Given a conjunctive goal, G1 ^ G2, if the steps that solve G1 must either all come before or all come after the steps that solve G2, then the planner is called a non-interleaving planner. Otherwise, the planner allows interleaving of sub-plan steps. This constraint is different from the issue of partial-order vs. total-order planners. STRIPS is a non-interleaving planner because of its use of a stack to order goals to be achieved.

While a pure non-interleaving planner cannot solve the Sussman Anomaly, an interleaving planner can solve it by interleaving the steps associated with solving the two goals, on(A,B) and on(B,C). For example, the following plan solves this problem: unstack(C,A), Pickup(B), Stack(B,C), Stack(A,B). Notice that the first and last steps of this plan were created as part of the sub-plan to solve on(A,B), and the middle two steps are used to solve on(B,C).

Partial-Order Planner (POP) Algorithm

function pop(initial-state, conjunctive-goal, operators)
  // non-deterministic algorithm
  plan = make-initial-plan(initial-state, conjunctive-goal);
  loop:
    begin
      if solution?(plan) then return plan;
      (S-need, c) = select-subgoal(plan) ; // choose an unsolved goal
      choose-operator(plan, operators, S-need, c);
          // select an operator to solve that goal and revise plan
      resolve-threats(plan);  // fix any threats created
    end
end

function solution?(plan)
  if causal-links-establishing-all-preconditions-of-all-steps(plan)
     and all-threats-resolved(plan)
     and all-temporal-ordering-constraints-consistent(plan)
     and all-variable-bindings-consistent(plan)
  then return true;
  else return false;
end

function select-subgoal(plan)
  pick a plan step S-need from steps(plan) with a precondition c
     that has not been achieved;
  return (S-need, c);
end

procedure choose-operator(plan, operators, S-need, c)
  // solve "open precondition" of some step
  choose a step S-add by either
    Step Addition: adding a new step from operators that
       has c in its Add-list
    or Simple Establishment: picking an existing step in Steps(plan)
       that has c in its Add-list;
  if no such step then return fail;
  add causal link "S-add --->c S-need" to Links(plan);
  add temporal ordering constraint "S-add < S-need" to Orderings(plan);
  if S-add is a newly added step then
    begin
    add S-add to Steps(plan);
    add "Start < S-add" and "S-add < Finish" to Orderings(plan);
    end
end

procedure resolve-threats(plan)
  foreach S-threat that threatens link "Si --->c Sj" in Links(plan)
   begin     // "declobber" threat
     choose either
       Demotion: add "S-threat < Si" to Orderings(plan)
       or Promotion: add "Sj < S-threat" to Orderings(plan);
     if not(consistent(plan)) then return fail;
   end
end

Plan Modification Operations

The above algorithm uses four basic plan modification operations to revise a plan, two for solving a goal and two for fixing a threat: Example -- Solving the Sussman Anomaly using the POP Algorithm
In the following plans, links shown as -----> are causal links and are labeled with the open precondition that is solved by this link. Links shown as ++++++> are temporal links, though most of these are not shown in order to keep the figures neater. Of course, for each causal link there should also be a temporal link connecting the same two nodes, but this is not shown.

 

  1. Create initial-plan:
  2. Start +++++++++++++> Finish
    P: none              P: on(A,B)
    E: on(C,A)              on(B,C)
       handempty
       ontable(A)
       ontable(B)
       clear(B)
       clear(C)
  3. Solve open precondition on(A,B) in step Finish by Step Addition using Stack(A,B).

  4. Notes:
    1. Stack is the only operator that can be used to solve this open precondition.
    2. The figure below should include a temporal link from the new step to Finish, but it is not included in order to keep the figure more readable. Also, the temporal link connecting Start to Finish has been omitted for the same reason.
                                         on(A,B)
    Start +++++++++++++> Stack(A,B) ------------> Finish
    P: none              P: holding(A)            P: on(A,B)
    E: on(C,A)              clear(B)                 on(B,C)
       handempty         E: on(A,B)
       ontable(A)           clear(A)
       ontable(B)           handempty
       clear(B)             ~holding(A)
       clear(C)             ~clear(B)
  5. Solve open precondition on(B,C) in step Finish by Step Addition using Stack(B,C).

  6. Notes:
    1. Stack is the only operator applicable here.
    2. The figure below should include temporal links from Start to the new step, as well as from the new step to Finish, but these are not explicitly shown in order to keep the figure more readable.
                                      on(A,B)
    Start +++++++++++++> Stack(A,B) ------------> Finish
    P: none              P: holding(A)          ^ P: on(A,B)
    E: on(C,A)              clear(B)            |    on(B,C)
       handempty         E: on(A,B)             |
       ontable(A)           clear(A)            |
       ontable(B)           handempty           |
       clear(B)             ~holding(A)         |
       clear(C)             ~clear(B)           |
                                                |
                                      on(B,C)   |
                         Stack(B,C) ------------|
                         P: holding(B)
                            clear(C)
                         E: on(B,C)
                            clear(B)
                            handempty
                            ~holding(B)
                            ~clear(C)
  7. Solve open precondition holding(B) in step Stack(B,C) by Step Addition using Pickup(B).

  8. Notes:
    1. There are two possible operators (Pickup and Unstack) that could be used to solve this open precondition, so this is a choice point for the algorithm.
    2. The figure below should include temporal links from Start to the new step, as well as from the new step to Stack(B,C), but these are not explicitly shown in order to keep the figure more readable.
                                      on(A,B)
    Start +++++++++++++> Stack(A,B) ------------> Finish
    P: none              P: holding(A)          ^ P: on(A,B)
    E: on(C,A)              clear(B)            |    on(B,C)
       handempty         E: on(A,B)             |
       ontable(A)           clear(A)            |
       ontable(B)           handempty           |
       clear(B)             ~holding(A)         |on(B,C)
       clear(C)             ~clear(B)           |
                                                |
                                    holding(B)  |
                         Pickup(B) -----------> Stack(B,C)
                         P: ontable(B)          P: holding(B)
                            clear(B)               clear(C)
                            handempty           E: on(B,C)
                         E: holding(B)             clear(B)
                            ~ontable(B)            handempty
                            ~clear(B)              ~holding(B)
                            handempty              ~clear(C)
  9. Solve open precondition holding(A) in step Stack(A,B) by Step Addition using Pickup(A).

  10. Notes:
    1. There are two possible operators (Pickup and Unstack) for solving this open precondition, so this is a choice point for the algorithm.
    2. The figure below should include temporal links from Start to the new step, as well as from the new step to Stack(A,B), but these are not explicitly shown in order to keep the figure more readable.
                              holding(A)             on(A,B)
    Start ++++++++> Pickup(A) ----------> Stack(A,B) --------> Finish
    P: none         P: ontable(A)         P: holding(A)      ^ P: on(A,B)
    E: on(C,A)         clear(A)              clear(B)        |    on(B,C)
       handempty       handempty          E: on(A,B)         |
       ontable(A)   E: holding(A)            clear(A)        |
       ontable(B)      ~clear(A)             handempty       |
       clear(B)        ~ontable(A)           ~holding(A)     |on(B,C)
       clear(C)        ~handempty            ~clear(B)       |
                                                             |
                                                   |---------|
                                   holding(B)      |
                         Pickup(B) -----------> Stack(B,C)
                         P: ontable(B)          P: holding(B)
                            clear(B)               clear(C)
                            handempty           E: on(B,C)
                         E: holding(B)             clear(B)
                            ~ontable(B)            handempty
                            ~clear(B)              ~holding(B)
                            handempty              ~clear(C)
  11. Solve open precondition clear(A) in step Pickup(A) using Step Addition with Unstack(C,A):
  12. Start
    P: none
    E: on(C,A)
       handempty
       ontable(A)
       ontable(B)
       clear(B)
       clear(C)
    
               clear(A)          holding(A)             on(A,B)
    Unstack(C,A) ----> Pickup(A) ----------> Stack(A,B) -------> Finish
    P: clear(C)        P: ontable(A)         P: holding(A)     ^ P: on(A,B)
       on(C,A)            clear(A)              clear(B)       |    on(B,C)
       handempty          handempty          E: on(A,B)        |
    E: holding(C)      E: holding(A)            clear(A)       |
       clear(A)           ~clear(A)             handempty      |
       ~clear(C)          ~ontable(A)           ~holding(A)    |on(B,C)
       ~on(C,A)           ~handempty            ~clear(B)      |
       ~handempty                                              |
                                                   |-----------|
                                   holding(B)      |
                         Pickup(B) -----------> Stack(B,C)
                         P: ontable(B)          P: holding(B)
                            clear(B)               clear(C)
                            handempty           E: on(B,C)
                         E: holding(B)             clear(B)
                            ~ontable(B)            handempty
                            ~clear(B)              ~holding(B)
                            handempty              ~clear(C)
  13. Solve open precondition handempty in Pickup(B) using Step Addition with Putdown(C):
  14. Start
    P: none
    E: on(C,A)
       handempty
       ontable(A)
       ontable(B)
       clear(B)
       clear(C)
    
               clear(A)          holding(A)             on(A,B)
    Unstack(C,A) ----> Pickup(A) ----------> Stack(A,B) -------> Finish
    P: clear(C)        P: ontable(A)         P: holding(A)     ^ P: on(A,B)
       on(C,A)            clear(A)              clear(B)       |    on(B,C)
       handempty          handempty          E: on(A,B)        |
    E: holding(C)      E: holding(A)            clear(A)       |
       clear(A)           ~clear(A)             handempty      |
       ~clear(C)          ~ontable(A)           ~holding(A)    |on(B,C)
       ~on(C,A)           ~handempty            ~clear(B)      |
       ~handempty                                              |
                                                   |-----------|
              handempty            holding(B)      |
    Putdown(C) --------> Pickup(B) -----------> Stack(B,C)
    P: holding(C)        P: ontable(B)          P: holding(B)
    E: ontable(C)           clear(B)               clear(C)
       clear(C)             handempty           E: on(B,C)
       handempty         E: holding(B)             clear(B)
       ~holding(C)          ~ontable(B)            handempty
                            ~clear(B)              ~holding(B)
                            handempty              ~clear(C)
  15. Solve open preconditions using Simple Establishment for each of the following:
  16.  

    Open Precond in Step Solved by Step
    clear(C) Unstack(C,A) Start
    on(C,A) Unstack(C,A) Start
    handempty Unstack(C,A) Start
    For each of the above, add a causal link from Start to Unstack(C,A).
  17. Detect threat ~clear(C) in step Stack(B,C) to causal link from Start to Unstack(C,A). Fix by Promotion: add temporal link from Unstack(C,A) to Stack(B,C) so that Stack(B,C) forced to come after Unstack(C,A).
  18. Start ----------
    P: none        |
    E: on(C,A)     |
       handempty   |clear(C)
       ontable(A)  |on(C,A)
       ontable(B)  |handempty
       clear(B)    |
       clear(C)    |
                   |
        |----------|
        |
        V      clear(A)          holding(A)             on(A,B)
    Unstack(C,A) ----> Pickup(A) ----------> Stack(A,B) -------> Finish
    P: clear(C)  +     P: ontable(A)         P: holding(A)     ^ P: on(A,B)
       on(C,A)    +       clear(A)              clear(B)       |    on(B,C)
       handempty  +       handempty          E: on(A,B)        |
    E: holding(C) +    E: holding(A)            clear(A)       |
       clear(A)   +       ~clear(A)             handempty      |
       ~clear(C)  +       ~ontable(A)           ~holding(A)    |on(B,C)
       ~on(C,A)    ++++   ~handempty            ~clear(B)      |
       ~handempty      ++++++++++++++++++++++++++              |
                                                +  |-----------|
              handempty            holding(B)   v  |
    Putdown(C) --------> Pickup(B) -----------> Stack(B,C)
    P: holding(C)        P: ontable(B)          P: holding(B)
    E: ontable(C)           clear(B)               clear(C)
       clear(C)             handempty           E: on(B,C)
       handempty         E: holding(B)             clear(B)
       ~holding(C)          ~ontable(B)            handempty
                            ~clear(B)              ~holding(B)
                            handempty              ~clear(C)
  19. Solve open preconditions using Simple Establishment for each of the following:
  20.  

    Open Precond in Step Solved by Step
    Holding(C) Putdown(C) Unstack(C,A)
    ontable(B) Pickup(B) Start
    clear(B) Pickup(B) Start
    handempty Pickup(B) Putdown(C)
    For each of the above, add a causal link.
  21. Detect threat ~handempty at step Pickup(A) to causal link from Putdown(C) to Pickup(B). Fix by Promotion: add temporal link from Pickup(B) to Pickup(A).
  22.  Note: This fix means there is no threat at step Stack(A,B) to causal link from Start to Pickup(B) because now Stack(A,B) is after Pickup(A) which is after Pickup(B), so Stack(A,B) must occur after Pickup(B).

    Start ----------
    P: none        |
    E: on(C,A)     |
       handempty   |clear(C)
       ontable(A)  |on(C,A)
       ontable(B)  |handempty
       clear(B)    |
       clear(C)    |
                   |
        |----------|
        |
        V      clear(A)          holding(A)             on(A,B)
    Unstack(C,A) ----> Pickup(A) ----------> Stack(A,B) -------> Finish
    | P:clear(C)  +   ^ P: ontable(A)         P: holding(A)     ^ P: on(A,B)
    |   on(C,A)    +  +    clear(A)              clear(B)       |    on(B,C)
    |   handempty  +  +    handempty          E: on(A,B)        |
    | E:holding(C) +  + E: holding(A)            clear(A)       |
    |   clear(A)   +  +    ~clear(A)             handempty      |
    |   ~clear(C)  +  +    ~ontable(A)           ~holding(A)    |on(B,C)
    |   ~on(C,A)    ++++   ~handempty            ~clear(B)      |
    |   ~handempty    + +++++++++++++++++++++++++               |
    |                 +                         +               |
    |holding(C)       ++++                      +  |------------|
    |                    +                      +  |
    v         handempty  +         holding(B)   v  |
    Putdown(C) --------> Pickup(B) -----------> Stack(B,C)
    P: holding(C)        P: ontable(B)          P: holding(B)
    E: ontable(C)           clear(B)               clear(C)
       clear(C)             handempty           E: on(B,C)
       handempty         E: holding(B)             clear(B)
       ~holding(C)          ~ontable(B)            handempty
                            ~clear(B)              ~holding(B)
                            handempty              ~clear(C)
  23. Solve open preconditions using Simple Establishment for each of the following:
  24.  

    Open Precond in Step Solved by Step
    clear(C) Stack(B,C) Putdown(C)
    ontable(A) Pickup(A) Start
    handempty Pickup(A) Stack(B,C)
    clear(B) Stack(A,B) Stack(B,C)
    For each of the above, add a causal link.
    Start ----------------------
    P: none        |           |
    E: on(C,A)     |           |
       handempty   |clear(C)   |ontable(A)
       ontable(A)  |on(C,A)    |
       ontable(B)  |handempty  |
       clear(B)    |           |
       clear(C)    |           |
                   |    |------|
        |----------|    |
        |               |
        V      clear(A) v        holding(A)             on(A,B)
    Unstack(C,A) ----> Pickup(A) ----------> Stack(A,B) -------> Finish
    | P:clear(C)  +  ^ ^P: ontable(A)       ^ P: holding(A)     ^ P: on(A,B)
    |   on(C,A)    + + |   clear(A)         |    clear(B)       |    on(B,C)
    |   handempty  + + |   handempty        | E: on(A,B)        |
    | E:holding(C) + + |E: holding(A)       |    clear(A)       |
    |   clear(A)   + + |   ~clear(A)        |    handempty      |
    |   ~clear(C)  + + |   ~ontable(A)      |    ~holding(A)    |on(B,C)
    |   ~on(C,A)   + + |   ~handempty       |    ~clear(B)      |
    |   ~handempty + + |------|             |--------|          |
    |              + +        |  handempty           |          |
    |              +++++++++  |--------------------| |          |
    |                +     +                       | |clear(B)  |
    |holding(C)      +++++ ++++++++++++++++++++++  | |          |
    |                    +                      +  | | |--------|
    v         handempty  +         holding(B)   v  | | |
    Putdown(C) --------> Pickup(B) -----------> Stack(B,C)
    P: holding(C) \      P: ontable(B)        ^ P: holding(B)
    E: ontable(C)  \        clear(B)          |    clear(C)
       clear(C)     \       handempty         | E: on(B,C)
       handempty     \   E: holding(B)        |    clear(B)
       ~holding(C)    \     ~ontable(B)       |    handempty
                      |     ~clear(B)         |    ~holding(B)
                      |     handempty         |    ~clear(C)
                      |                       |
                      |         clear(C)      |
                      |------------------------
  25. No open preconditions and no threats, so halt. The only consistent total ordering that is implied from the final complete partial-order plan is: Unstack(C,A), Putdown(C), Pickup(B), Stack(B,C), Pickup(A), Stack(A,B). Notice that this interleaves the steps in the solutions to the two original goals, on(A,B) and on(B,C).

POP Summary


Copyright © 1996-2003 by Charles R. Dyer. All rights reserved.