Add FAIKR1 hierarchical and reactive planners

This commit is contained in:
2023-11-24 15:17:17 +01:00
parent 2ef29c7cb0
commit 869030639a
5 changed files with 820 additions and 568 deletions

View File

@ -0,0 +1,91 @@
<mxfile host="app.diagrams.net" modified="2023-11-24T13:45:44.355Z" agent="Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/119.0" etag="MzZ1NGvJcRhNqOrj3_1h" version="22.1.3" type="device">
<diagram name="Pagina-1" id="dSRs-kC2vbCNl_D_IkwA">
<mxGraphModel dx="989" dy="500" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="zVF-ozqo9N9PJf_awi-E-1" value="START" style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;fontFamily=Times New Roman;" vertex="1" parent="1">
<mxGeometry x="376" y="170" width="76" height="30" as="geometry" />
</mxCell>
<mxCell id="zVF-ozqo9N9PJf_awi-E-2" value="&lt;font style=&quot;font-size: 16px;&quot;&gt;on(tire1, hub1), flat(tire1), inflated(spare), off(spare), tire(tire1)&lt;br style=&quot;font-size: 16px;&quot;&gt;&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=16;fontFamily=Times New Roman;" vertex="1" parent="1">
<mxGeometry x="134" y="200" width="560" height="20" as="geometry" />
</mxCell>
<mxCell id="zVF-ozqo9N9PJf_awi-E-3" value="STOP" style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;fontFamily=Times New Roman;" vertex="1" parent="1">
<mxGeometry x="248" y="430" width="76" height="30" as="geometry" />
</mxCell>
<mxCell id="zVF-ozqo9N9PJf_awi-E-4" value="on(tire1, hub1), inflated(X)" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=16;fontFamily=Times New Roman;" vertex="1" parent="1">
<mxGeometry x="158" y="410" width="256" height="20" as="geometry" />
</mxCell>
<mxCell id="zVF-ozqo9N9PJf_awi-E-5" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;strokeWidth=2;entryX=0.323;entryY=-0.119;entryDx=0;entryDy=0;entryPerimeter=0;fontFamily=Times New Roman;" edge="1" parent="1" source="zVF-ozqo9N9PJf_awi-E-2" target="zVF-ozqo9N9PJf_awi-E-4">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="380" y="320" as="sourcePoint" />
<mxPoint x="375" y="372" as="targetPoint" />
<Array as="points">
<mxPoint x="414" y="240" />
<mxPoint x="240" y="240" />
<mxPoint x="240" y="350" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="zVF-ozqo9N9PJf_awi-E-6" value="STOP" style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;fontFamily=Times New Roman;" vertex="1" parent="1">
<mxGeometry x="504" y="430" width="76" height="30" as="geometry" />
</mxCell>
<mxCell id="zVF-ozqo9N9PJf_awi-E-7" value="inflated(X), on(tire1, hub1)" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=16;fontFamily=Times New Roman;" vertex="1" parent="1">
<mxGeometry x="414" y="410" width="256" height="20" as="geometry" />
</mxCell>
<mxCell id="zVF-ozqo9N9PJf_awi-E-10" value="CHECK(tire1)" style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;fontFamily=Times New Roman;" vertex="1" parent="1">
<mxGeometry x="340" y="290" width="149" height="30" as="geometry" />
</mxCell>
<mxCell id="zVF-ozqo9N9PJf_awi-E-11" value="tire(tire1)" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=16;fontFamily=Times New Roman;" vertex="1" parent="1">
<mxGeometry x="351.5" y="270" width="125" height="20" as="geometry" />
</mxCell>
<mxCell id="zVF-ozqo9N9PJf_awi-E-12" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;strokeWidth=2;fontFamily=Times New Roman;" edge="1" parent="1" source="zVF-ozqo9N9PJf_awi-E-2">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="410" y="230" as="sourcePoint" />
<mxPoint x="414" y="268" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="zVF-ozqo9N9PJf_awi-E-13" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;dashed=1;fontFamily=Times New Roman;" edge="1" parent="1" source="zVF-ozqo9N9PJf_awi-E-10">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="380" y="440" as="sourcePoint" />
<mxPoint x="350" y="350" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="zVF-ozqo9N9PJf_awi-E-14" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;dashed=1;fontFamily=Times New Roman;" edge="1" parent="1" source="zVF-ozqo9N9PJf_awi-E-10">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="424" y="330" as="sourcePoint" />
<mxPoint x="480" y="350" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="zVF-ozqo9N9PJf_awi-E-16" value="intact(tire1)" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=16;fontFamily=Times New Roman;" vertex="1" parent="1">
<mxGeometry x="276" y="322" width="125" height="20" as="geometry" />
</mxCell>
<mxCell id="zVF-ozqo9N9PJf_awi-E-17" value="¬intact(tire1)" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=16;fontFamily=Times New Roman;" vertex="1" parent="1">
<mxGeometry x="440" y="322" width="125" height="20" as="geometry" />
</mxCell>
<mxCell id="zVF-ozqo9N9PJf_awi-E-20" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.659;entryY=-0.114;entryDx=0;entryDy=0;entryPerimeter=0;strokeWidth=2;fontFamily=Times New Roman;" edge="1" parent="1" source="zVF-ozqo9N9PJf_awi-E-2" target="zVF-ozqo9N9PJf_awi-E-7">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="380" y="390" as="sourcePoint" />
<mxPoint x="430" y="340" as="targetPoint" />
<Array as="points">
<mxPoint x="414" y="240" />
<mxPoint x="583" y="240" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="zVF-ozqo9N9PJf_awi-E-22" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;fontFamily=Times New Roman;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="340" y="370" as="sourcePoint" />
<mxPoint x="360" y="370" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="zVF-ozqo9N9PJf_awi-E-23" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;fontFamily=Times New Roman;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="476.5" y="370" as="sourcePoint" />
<mxPoint x="496.5" y="370" as="targetPoint" />
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@ -13,6 +13,5 @@
\input{sections/_swarm_intelligence.tex} \input{sections/_swarm_intelligence.tex}
\input{sections/_games.tex} \input{sections/_games.tex}
\input{sections/_planning.tex} \input{sections/_planning.tex}
\input{sections/_generative_planning.tex}
\end{document} \end{document}

View File

@ -1,566 +0,0 @@
\chapter{Generative planning}
\begin{description}
\item[Generative planning] \marginnote{Generative planning}
Offline planning that creates the entire plan before execution based on
a snapshot of the current state of the world.
It relies on the following assumptions:
\begin{descriptionlist}
\item[Atomic time]
Actions cannot be interrupted.
\item[Determinism]
Actions are deterministic.
\item[Closed world]
The initial state is fully known,
what is not in the initial state is considered false (which is different from unknown).
\item[No interference] Only the execution of the plan changes the state of the world.
\end{descriptionlist}
\end{description}
\section{Linear planning}
\marginnote{Linear planning}
Formulates the planning problem as a search problem where:
\begin{itemize}
\item Nodes contain the state of the world.
\item Edges represent possible actions.
\end{itemize}
Produces a totally ordered list of actions.
The direction of the search can be:
\begin{descriptionlist}
\item[Forward] \marginnote{Forward search}
Starting from the initial state, the search terminates when a state containing a superset of the goal is reached.
\item[Backward] \marginnote{Backward search}
Starting from the goal, the search terminates when a state containing a subset of the initial state is reached.
Goal regression is used to reduce the goal into sub-goals.
Given a (sub-)goal $G$ and a rule (action) $R$ with delete-list (states that are false after the action) \texttt{d\_list}
and add-list (states that are true after the action) \texttt{a\_list}, regression of $G$ through $R$ is define as:
\[
\begin{split}
\texttt{regr[$G$, $R$]} &= \texttt{true} \text{ if } G \in \texttt{a\_list} \text{ (i.e. regression possible)} \\
\texttt{regr[$G$, $R$]} &= \texttt{false} \text{ if } G \in \texttt{d\_list} \text{ (i.e. regression not possible)} \\
\texttt{regr[$G$, $R$]} &= G \text{ otherwise} \text{ (i.e. $R$ does not influence $G$)} \\
\end{split}
\]
\begin{example}[Moving blocks]
Given the action \texttt{unstack(X, Y)} with:
\[
\begin{split}
\texttt{d\_list} &= \{ \texttt{handempty}, \texttt{on(X, Y)}, \texttt{clear(X)} \} \\
\texttt{a\_list} &= \{ \texttt{holding(X)}, \texttt{clear(Y)} \}
\end{split}
\]
We have that:
\[
\begin{split}
\texttt{regr[holding(b), unstack(b, Y)]} &= \texttt{true} \\
\texttt{regr[handempty, unstack(X, Y)]} &= \texttt{false} \\
\texttt{regr[ontable(c), unstack(X, Y)]} &= \texttt{ontable(c)} \\
\texttt{regr[clear(c), unstack(X, Y)]} &= \begin{cases}
\texttt{true} & \text{if \texttt{Y}=\texttt{c}} \\
\texttt{clear(c)} & \text{otherwise}
\end{cases}
\end{split}
\]
\end{example}
\end{descriptionlist}
\subsection{Deductive planning}
\marginnote{Deductive planning}
Formulates the planning problem using first order logic to represent states, goals and actions.
Plans are generated as theorem proofs.
\subsubsection{Green's formulation}
\marginnote{Green's formulation}
Green's formulation is based on \textbf{situation calculus}.
To find a plan, the goal is negated and it is proven that it leads to an inconsistency.
The main concepts are:
\begin{descriptionlist}
\item[Situation]
Properties (fluents) that hold in a given state \texttt{s}.
\begin{example}[Moving blocks]
To denote that \texttt{ontable(c)} holds in a state \texttt{s}, we use the axiom:
\[ \texttt{ontable(c, s)} \]
\end{example}
The operator \texttt{do} allows to evolve the state such that:
\[ \texttt{do(A, S)} = \texttt{S'} \]
\texttt{S'} is the new state obtained by applying the action \texttt{A} in the state \texttt{S}.
\item[Actions]
Define the pre-condition and post-condition fluents of an action in the form:
\[ \texttt{pre-conditions} \rightarrow \texttt{post-conditions} \]
Applying the equivalence $A \rightarrow B \equiv \lnot A \vee B$, actions can be described by means of disjunctions.
\begin{example}[Moving blocks]
The action \texttt{stack(X, Y)} has pre-conditions \texttt{holding(X)} and \texttt{clear(Y)}, and
post-conditions \texttt{on(X, Y)}, \texttt{clear(X)} and \texttt{handfree}.
Its representation in Green's formulation is:
\[
\begin{split}
\texttt{holding(X, S)} \land \texttt{clear(Y, S)} &\rightarrow \\
&\texttt{on(X, Y, do(stack(X, Y), s))} \land \\
&\texttt{clear(X, do(stack(X, Y), s))} \land \\
&\texttt{handfree(do(stack(X, Y), s))} \\
\end{split}
\]
\end{example}
\item[Frame axioms]
Besides the effects of actions, each state also have to define for all non-changing fluents their frame axioms.
If the problem is complex, the number of frame axioms becomes unreasonable.
\begin{example}[Moving blocks]
\[ \texttt{on(U, V, S)}, \texttt{diff(U, X)} \rightarrow \texttt{on(U, V, do(move(X, Y, Z), S))} \]
\end{example}
\end{descriptionlist}
\begin{example}[Moving blocks]
The initial state is described by the following axioms:\\[0.5em]
\begin{minipage}{.3\linewidth}
\centering
\texttt{on(a, d, s0)} \\
\texttt{on(b, e, s0)} \\
\texttt{on(c, f, s0)} \\
\texttt{clear(a, s0)} \\
\texttt{clear(b, s0)} \\
\end{minipage}
\begin{minipage}{.3\linewidth}
\centering
\texttt{clear(c, s0)} \\
\texttt{clear(g, s0)} \\
\texttt{diff(a, b)} \\
\texttt{diff(a, c)} \\
\texttt{diff(a, d)} \dots \\
\end{minipage}
\begin{minipage}{.3\linewidth}
\centering
\includegraphics[width=\linewidth]{img/_moving_block_example_green.pdf}
\end{minipage}\\[0.5em]
For simplicity, we only consider the action \texttt{move(X, Y, Z)} that moves \texttt{X} from \texttt{Y} to \texttt{Z}.
It is defined as:
\[
\begin{split}
\texttt{clear(X, S)}&, \texttt{clear(Z, S)}, \texttt{on(X, Y, S)}, \texttt{diff(X, Z)} \rightarrow \\
&\texttt{clear(Y, do(move(X, Y, Z), S))}, \texttt{on(X, Z, do(move(X, Y, Z), S))}
\end{split}
\]
This action can be translated into the following effect axioms:
\[
\begin{split}
\lnot\texttt{clear(X, S)} &\vee \lnot\texttt{clear(Z, S)} \vee \lnot\texttt{on(X, Y, S)} \vee \lnot\texttt{diff(X, Z)} \vee \\
&\texttt{clear(Y, do(move(X, Y, Z), S))}
\end{split}
\]
\[
\begin{split}
\lnot\texttt{clear(X, S)} &\vee \lnot\texttt{clear(Z, S)} \vee \lnot\texttt{on(X, Y, S)} \vee \lnot\texttt{diff(X, Z)} \vee \\
&\texttt{on(X, Z, do(move(X, Y, Z), S))}
\end{split}
\]
\end{example}
Given the goal \texttt{on(a, b, s1)}, we prove that $\lnot\texttt{on(a, b, s1)}$ leads to an inconsistency.
We decide to make the following substitutions:
\[ \{ \texttt{X}/\texttt{a}, \texttt{Z}/\texttt{b}, \texttt{s1}/\texttt{do(move(a, Y, b), S)} \} \]
The premise of \texttt{move} leads to an inconsistency (when applying \texttt{move} its premise is false):
\begin{center}
\begin{tabular}{c|c|c|c}
$\lnot\texttt{clear(a, S)}$ & $\lnot\texttt{clear(b, S)}$ & $\lnot\texttt{on(a, Y, S)}$ & $\lnot\texttt{diff(a, b)}$ \\
False with $\{ \texttt{S}/\texttt{s0} \}$ & False with $\{ \texttt{S}/\texttt{s0} \}$
& False with $\{ \texttt{S}/\texttt{s0}, \texttt{Y}/\texttt{d} \}$ & False
\end{tabular}
\end{center}
Therefore, the substitution $\{ \texttt{s1}/\texttt{do(move(a, Y, b), S)} \}$ defines the plan to reach the goal \texttt{on(a, b, s1)}.
\subsubsection{Kowalsky's formulation}
\marginnote{Kowalsky's formulation}
Kowalsky's formulation avoids the frame axioms problem by using a set of fixed predicates:
\begin{descriptionlist}
\item[\texttt{holds(rel, s/a)}]
Describes the relations \texttt{rel} that are true in a state \texttt{s} or after the execution of an action \texttt{a}.
\item[\texttt{poss(s)}]
Indicates if a state \texttt{s} is possible.
\item[\texttt{pact(a, s)}]
Indicates if an action \texttt{a} can be executed in a state \texttt{s}.
\end{descriptionlist}
Actions can be described as:
\[ \texttt{poss(S)} \land \texttt{pact(A, S)} \rightarrow \texttt{poss(do(A, S))} \]
In the Kowalsky's formulation, each action requires a frame assertion (in Green's formulation, each state requires frame axioms).
\begin{example}[Moving blocks]
An initial state can be described by the following axioms:\\[0.5em]
\begin{minipage}{.35\linewidth}
\centering
\texttt{holds(on(a, b), s0)} \\
\texttt{holds(ontable(b), s0)} \\
\texttt{holds(ontable(c), s0)} \\
\end{minipage}
\begin{minipage}{.35\linewidth}
\centering
\texttt{holds(clear(a), s0)} \\
\texttt{holds(clear(c), s0)} \\
\texttt{holds(handempty, s0)} \\
\texttt{poss(s0)} \\
\end{minipage}
\begin{minipage}{.2\linewidth}
\centering
\includegraphics[width=0.6\linewidth]{img/_moving_block_example_kowalsky.pdf}
\end{minipage}\\[0.5em]
\end{example}
\begin{example}[Moving blocks]
The action \texttt{unstack(X, Y)} has:
\begin{descriptionlist}
\item[Pre-conditions] \texttt{on(X, Y)}, \texttt{clear(X)} and \texttt{handempty}
\item[Effects] \phantom{}
\begin{description}
\item[Add-list] \texttt{holding(X)} and \texttt{clear(Y)}
\item[Delete-list] \texttt{on(X, Y)}, \texttt{clear(X)} and \texttt{handempty}
\end{description}
\end{descriptionlist}
Its description in Kowalsky's formulation is:
\begin{descriptionlist}
\item[Pre-conditions]
\[
\begin{split}
\texttt{holds(on(X, Y), S)}&, \texttt{holds(clear(X), S)}, \texttt{holds(handempty, S)} \rightarrow \\
&\texttt{pact(unstack(X, Y), S)}
\end{split}
\]
\item[Effects] (use add-list)
\[ \texttt{holds(holding(X), do(unstack(X, Y), S))} \]
\[ \texttt{holds(clear(Y), do(unstack(X, Y), S))} \]
\item[Frame condition] (uses delete-list)
\[
\begin{split}
\texttt{holds(V, S)}&, \texttt{V} \neq \texttt{on(X, Y)}, \texttt{V} \neq \texttt{clear(X)}, \texttt{V} \neq \texttt{handempty}
\rightarrow \\
& \texttt{holds(V, do(unstack(X, Y), S))}
\end{split}
\]
\end{descriptionlist}
\end{example}
\subsection{STRIPS}
\marginnote{STRIPS}
STRIPS (Stanford Research Institute Problem Solver) is an ad-hoc algorithm
for linear planning resolution.
The elements of the problem are represented as:
\begin{descriptionlist}
\item[State] represented with its true fluents.
\item[Goal] represented with its true fluents.
\item[Action] represented using three lists:
\begin{descriptionlist}
\item[Preconditions] Fluents that are required to be true in order to apply the action.
\item[Delete-list] Fluents that become false after the action.
\item[Add-list] Fluents that become true after the action.
\end{descriptionlist}
Add-list and delete-list can be combined in an effect list with positive (add-list) and negative (delete-list) axioms.
\begin{description}
\item[STRIPS assumption] Everything that is not in the add-list or delete-list is unchanged in the next state.
\end{description}
\end{descriptionlist}
STRIPS uses two data structures:
\begin{descriptionlist}
\item[Goal stack] Does a backward search to reach the initial state.
\item[Current state] Represents the forward application of the actions found using the goal stack.
\end{descriptionlist}
\begin{algorithm}
\caption{STRIPS}
\begin{lstlisting}[mathescape=true]
def strips(problem):
goal_stack = Stack()
current_state = State(problem.initial_state)
goal_stack.push(problem.goal)
plan = []
while not goal_stack.empty():
if (goal_stack.top() is a single/conjunction of goals and
there is a substitution $\theta$ that makes it $\subseteq$ current_state):
A = goal_stack.pop()
$\theta$ = find_substitution(A, current_state)
goal_stack.apply_substitution($\theta$)
elif goal_stack.top() is a single goal:
R = rule with a $\in$ R.add_list
_ = goal_stack.pop() # Pop goal
goal_stack.push(R)
goal_stack.push(R.preconditions)
elif goal_stack.top() is a conjunction of goals:
for g in permutation(goal_stack.top()):
goal_stack.push(g)
# Note that there is no pop
elif goal_stack.top() is an action:
action = goal_stack.pop()
current_state.apply(action)
plan.append(action)
return plan
\end{lstlisting}
\end{algorithm}
\begin{example}[Moving blocks]
\begin{center}
\includegraphics[trim={0 32.2cm 0 0}, clip, width=0.85\textwidth]{img/_strips_example.pdf}
\end{center}
\begin{center}
\includegraphics[trim={0 0 0 17.5cm}, clip, width=0.85\textwidth]{img/_strips_example.pdf}
\end{center}
\end{example}
Since there are non-deterministic choices, the search space may become very large.
Heuristics may be used to avoid this.
Conjunction of goals are solved separately, but this could lead to the \marginnote{Sussman anomaly} \textbf{Sussman anomaly}
where a sub-goal destroys what another sub-goal has done.
For this reason, when a conjunction is encountered, it is not immediately popped from the goal stack
and is left as a final check.
\section{Non-linear planning}
\marginnote{Non-linear planning}
Non-linear planning finds a plan as a search problem in the space of plans (instead of states as in linear planning).
Each node of the search tree is a partial plan. Edges represent plan refinement operations.
A non-linear plan is represented by:
\begin{descriptionlist}
\item[Actions{\normalfont.}] \marginnote{Actions set}
\item[Orderings] \marginnote{Orderings set}
between actions.
\item[Causal links] \marginnote{Causal links}
triplet $\langle S_i, S_j, c \rangle$ where $S_i$ and $S_j$ are actions and $c$ is a sub-goal.
$c$ should be the effect of $S_i$ and precondition of $S_j$.
Causal links represent causal relations between actions (i.e. interaction between sub-goals):
to execute $S_j$, the effect $c$ of $S_i$ is required first.
\end{descriptionlist}
The initial plan is an empty plan with two fake actions \texttt{start} and \texttt{stop}
with ordering $\texttt{start} < \texttt{stop}$:
\begin{descriptionlist}
\item[\texttt{start}] has no preconditions and the effects match the initial state.
\item[\texttt{stop}] has no effects and the preconditions match the goal.
\end{descriptionlist}
At each step, one of the following refinement operations can be applied until the goal is reached:
\begin{itemize}
\item Add an action to the set of actions.
\item Add an ordering to the set of orderings.
\item Add a causal link to the set of causal links.
\end{itemize}
\begin{figure}[h]
\centering
\includegraphics[width=0.45\textwidth]{img/_nonlinear_plan_example.pdf}
\caption{Example of search tree in non-linear planning}
\end{figure}
\begin{description}
\item[Least commitment planning] \marginnote{Least commitment planning}
Only strictly necessary restrictions (e.g. ordering) are imposed.
Non-linear planning is a least commitment planning.
\item[Linearization] \marginnote{Linearization}
At the end, the partially ordered actions should be linearized,
respecting the ordering constraints, to obtain the final plan.
\end{description}
\begin{description}
\item[Threat] \marginnote{Threat}
An action $S_k$ is a threat to a causal link $\langle S_i, S_j, c \rangle$
if its effects cancel $c$.
$S_k$ should not be executed in between $S_i$ and $S_j$.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/_threat_example.pdf}
\caption{Example of threat. Causal links are represented using thick arrows.}
\end{figure}
Possible solutions to a threat $S_k$ to $\langle S_i, S_j, c \rangle$ are:
\begin{descriptionlist}
\item[Demotion] \marginnote{Demotion}
Add the ordering constraint $S_k < S_i$ (i.e. threat executed before).
\item[Promotion] \marginnote{Promotion}
Add the ordering constraint $S_k > S_i$ (i.e. threat executed after).
\end{descriptionlist}
\end{description}
\begin{algorithm}
\caption{Partial order planning (POP)}
\begin{lstlisting}[mathescape=true]
def pop(initial_state, goal, actions):
plan = init_empty_plan(initial_state, goal)
while not plan.isSolution():
try:
sn, c = selectSubgoal(plan)
chooseOperator(plan, actions, sn, c)
resolveThreats(plan)
except PlanFailError:
plan.backtrack()
return plan
def selectSubgoal(plan):
sn, c = random([sn, c in plan.steps if c in sn.unsolved_preconditions])
return sn, c
def chooseOperator(plan, actions, sn, c):
s = random([s in (actions + plan.steps) if c in s.effects])
if s is None: raise(PlanFailError)
plan.addCausalLink($\langle$s, sn, c$\rangle$)
plan.addOrdering(s < sn)
if s not in plan.steps:
plan.addAction(s)
plan.addOrdering(start < s < stop)
def resolveThreats(plan):
for s_k, s_i, s_j in plan.threats():
resolution = random([ DEMOTION, PROMOTION ])
if resolution == DEMOTION:
plan.addOrdering(s_k < s_i)
elif resolution == PROMOTION:
plan.addOrdering(s_k > s_j)
if plan.isNotConsistent(): raise(PlanFailError)
\end{lstlisting}
\end{algorithm}
\begin{example}[Purchasing schedule]
The initial state is:
\[ \texttt{at(home)}, \texttt{sells(hws, drill)}, \texttt{sells(sm, milk)}, \texttt{sells(sm, banana)} \]
where $\texttt{hws}$ means "hardware store" and $\texttt{sm}$ means "supermarket".
The goal is:
\[ \texttt{at(home)}, \texttt{have(drill)}, \texttt{have(milk)}, \texttt{have(banana)} \]
The possible actions are:\\[0.5em]
\begin{minipage}{.5\linewidth}
\begin{descriptionlist}
\item[\texttt{GO(X, Y)}] \phantom{}
\begin{description}
\item[Preconditions] $\texttt{at(X)}$
\item[Effects] $\texttt{at(Y)}$, $\lnot \texttt{at(X)}$
\end{description}
\end{descriptionlist}
\end{minipage}
\begin{minipage}{.5\linewidth}
\begin{descriptionlist}
\item[\texttt{BUY(S, Y)}] \phantom{}
\begin{description}
\item[Preconditions] $\texttt{at(S)}$, $\texttt{sells(S, Y)}$
\item[Effects] $\texttt{have(Y)}$
\end{description}
\end{descriptionlist}
\end{minipage}\\[0.5em]
Partial order planning steps are:
\begin{enumerate}
\item Define the initial plan:
\begin{center}
\includegraphics[width=0.7\textwidth]{img/_pop_example1.pdf}
\end{center}
\item The loop of POP is:
\begin{itemize}
\item Choose an action $a_i$ and one of its unsolved preconditions $c$.
\item Select an action $a_j$ with the precondition $c$ in its effects.
\item Add the ordering constraint $\texttt{start} < a_j < \texttt{stop}$.
\item Add the causal link $\langle a_j, a_i, c \rangle$ (and ordering $a_j < a_i$).
\item Solve threats.
\end{itemize}
We choose the action $a_i = \texttt{stop}$ and the precondition $c = \texttt{have(drill)}$.
We choose as action with $c$ in its effects $a_j = \texttt{BUY(X, drill)}$.
We therefore add to the plan the ordering $\texttt{start} < \texttt{BUY(X, drill)} < \texttt{stop}$ and
the causal link $\langle \texttt{BUY(X, drill)}, \texttt{stop}, \texttt{have(drill)} \rangle$:
\begin{center}
\includegraphics[width=0.7\textwidth]{img/_pop_example2.pdf}
\end{center}
\item Repeat the previous point for the preconditions $\texttt{have(milk)}$ and $\texttt{have(banana)}$:
\begin{center}
\includegraphics[width=0.7\textwidth]{img/_pop_example3.pdf}
\end{center}
\item Now, we choose as action $\texttt{BUY(X, drill)}$ and as unsolved precondition $\texttt{sells(X, drill)}$.
This can be solved from the action $\texttt{start}$ with effect $\texttt{sells(hws, drill)}$.
We make the substitution $\texttt{X}/\texttt{drill}$ and
add $\langle \texttt{start}, \texttt{BUY(hws, drill)}, \texttt{sells(hws, drill)} \rangle$ to the causal links.
The same process can be repeated for $\texttt{BUY(X, milk)}$ and $\texttt{BUY(X, banana)}$:
\begin{center}
\includegraphics[width=0.7\textwidth]{img/_pop_example4.pdf}
\end{center}
\item Now, we choose as action $\texttt{BUY(hws, drill)}$ and as unsolved precondition $\texttt{at(hws)}$.
This can be solved using the action $\texttt{GO(X, hws)}$.
We add $\langle \texttt{GO(X, hws)}, \texttt{BUY(hws, drill)}, \texttt{at(hws)} \rangle$ to the causal links.
We continue by choosing as action $\texttt{GO(X, hws)}$ and as unsolved precondition $\texttt{at(X)}$.
This can be solved from $\texttt{start}$ with effect $\texttt{at(home)}$.
We therefore make the substitution $\texttt{X}/\texttt{home}$ and
add $\langle \texttt{start}, \texttt{GO(home, hws)}, \texttt{at(home)} \rangle$ to the causal links.
The same process can be repeated for the $\texttt{milk}$ and $\texttt{banana}$ branch:
\begin{center}
\includegraphics[width=0.7\textwidth]{img/_pop_example5.pdf}
\end{center}
\item We have a threat between $\texttt{GO(home, hws)}$ and $\texttt{GO(home, sm)}$ as they both
require the precondition $\texttt{at(home)}$ and both have as effect $\lnot\texttt{at(home)}$.
It can be easily seen that neither promotion nor demotion solves the conflict.
We are therefore forced to backtrack.
We backtrack at the previous point, where we chose as action $\texttt{GO(X, sm)}$ and as precondition $\texttt{at(X)}$
(this step has been implicitly done in the previous point).
\begin{itemize}
\item Instead of choosing the action $\texttt{start}$, we choose $\texttt{GO(home, hws)}$ with the effect $\texttt{at(hws)}$.
We therefore make the substitution $\texttt{X}/\texttt{hws}$ and update the causal links.
\item We also resolve the threat $\texttt{GO(hws, sm)}$ to $\texttt{BUY(hws, drill)}$
(it removes the precondition $\texttt{at(hws)}$)
by promoting $\texttt{GO(hws, sm)}$
and adding the ordering constraint $\texttt{BUY(hws, drill)} < \texttt{GO(hws, sm)}$:
\end{itemize}
\begin{center}
\includegraphics[width=0.7\textwidth]{img/_pop_example6.pdf}
\end{center}
\item Now, we choose as action $\texttt{stop}$ and as precondition $\texttt{at(home)}$.
We choose as action $\texttt{GO(sm, home)}$ and update the causal links.
Finally, we solve the threat $\texttt{GO(sm, home)}$ to
both $\texttt{BUY(sm, milk)}$ and $\texttt{BUY(sm, banana)}$ (it removes the required precondition $\texttt{at(sm)}$)
by promoting $\texttt{GO(sm, home)}$.
The newly added ordering constraints are
$\texttt{BUY(sm, milk)} < \texttt{GO(sm, home)}$ and
$\texttt{BUY(sm, banana)} < \texttt{GO(sm, home)}$.
The final plan is:
\begin{center}
\includegraphics[width=0.7\textwidth]{img/_pop_example7.pdf}
\end{center}
By considering the ordering constraints, a linearization could be:
\[
\begin{split}
\texttt{GO(home, hws)} &\rightarrow
\texttt{BUY(hws, drill)} \rightarrow
\texttt{GO(hws, sm)} \rightarrow\\
&\texttt{BUY(sm, milk)} \rightarrow
\texttt{BUY(sm, banana)} \rightarrow
\texttt{GO(sm, home)}
\end{split}
\]
\end{enumerate}
\end{example}

View File

@ -1,4 +1,7 @@
\chapter{Automated planning definitions} \chapter{Automated planning}
\section{Definitions}
\begin{description} \begin{description}
\item[Automated planning] \marginnote{Automated planning} \item[Automated planning] \marginnote{Automated planning}
@ -49,4 +52,729 @@
\item[Non deterministic] \item[Non deterministic]
An action applied to the real world may have unexpected effects due to uncertainty. An action applied to the real world may have unexpected effects due to uncertainty.
\end{descriptionlist} \end{descriptionlist}
\item[Generative planning] \marginnote{Generative planning}
Offline planning that creates the entire plan before execution based on
a snapshot of the current state of the world.
It relies on the following assumptions:
\begin{descriptionlist}
\item[Atomic time]
Actions cannot be interrupted.
\item[Determinism]
Actions are deterministic.
\item[Closed world]
The initial state is fully known,
what is not in the initial state is considered false (which is different from unknown).
\item[No interference] Only the execution of the plan changes the state of the world.
\end{descriptionlist}
\end{description} \end{description}
\section{Linear planning}
\marginnote{Linear planning}
Formulates the planning problem as a search problem where:
\begin{itemize}
\item Nodes contain the state of the world.
\item Edges represent possible actions.
\end{itemize}
Produces a totally ordered list of actions.
The direction of the search can be:
\begin{descriptionlist}
\item[Forward] \marginnote{Forward search}
Starting from the initial state, the search terminates when a state containing a superset of the goal is reached.
\item[Backward] \marginnote{Backward search}
Starting from the goal, the search terminates when a state containing a subset of the initial state is reached.
Goal regression is used to reduce the goal into sub-goals.
Given a (sub-)goal $G$ and a rule (action) $R$ with delete-list (states that are false after the action) \texttt{d\_list}
and add-list (states that are true after the action) \texttt{a\_list}, regression of $G$ through $R$ is define as:
\[
\begin{split}
\texttt{regr[$G$, $R$]} &= \texttt{true} \text{ if } G \in \texttt{a\_list} \text{ (i.e. regression possible)} \\
\texttt{regr[$G$, $R$]} &= \texttt{false} \text{ if } G \in \texttt{d\_list} \text{ (i.e. regression not possible)} \\
\texttt{regr[$G$, $R$]} &= G \text{ otherwise} \text{ (i.e. $R$ does not influence $G$)} \\
\end{split}
\]
\begin{example}[Moving blocks]
Given the action \texttt{unstack(X, Y)} with:
\[
\begin{split}
\texttt{d\_list} &= \{ \texttt{handempty}, \texttt{on(X, Y)}, \texttt{clear(X)} \} \\
\texttt{a\_list} &= \{ \texttt{holding(X)}, \texttt{clear(Y)} \}
\end{split}
\]
We have that:
\[
\begin{split}
\texttt{regr[holding(b), unstack(b, Y)]} &= \texttt{true} \\
\texttt{regr[handempty, unstack(X, Y)]} &= \texttt{false} \\
\texttt{regr[ontable(c), unstack(X, Y)]} &= \texttt{ontable(c)} \\
\texttt{regr[clear(c), unstack(X, Y)]} &= \begin{cases}
\texttt{true} & \text{if \texttt{Y}=\texttt{c}} \\
\texttt{clear(c)} & \text{otherwise}
\end{cases}
\end{split}
\]
\end{example}
\end{descriptionlist}
\subsection{Deductive planning}
\marginnote{Deductive planning}
Formulates the planning problem using first order logic to represent states, goals and actions.
Plans are generated as theorem proofs.
\subsubsection{Green's formulation}
\marginnote{Green's formulation}
Green's formulation is based on \textbf{situation calculus}.
To find a plan, the goal is negated and it is proven that it leads to an inconsistency.
The main concepts are:
\begin{descriptionlist}
\item[Situation]
Properties (fluents) that hold in a given state \texttt{s}.
\begin{example}[Moving blocks]
To denote that \texttt{ontable(c)} holds in a state \texttt{s}, we use the axiom:
\[ \texttt{ontable(c, s)} \]
\end{example}
The operator \texttt{do} allows to evolve the state such that:
\[ \texttt{do(A, S)} = \texttt{S'} \]
\texttt{S'} is the new state obtained by applying the action \texttt{A} in the state \texttt{S}.
\item[Actions]
Define the pre-condition and post-condition fluents of an action in the form:
\[ \texttt{pre-conditions} \rightarrow \texttt{post-conditions} \]
Applying the equivalence $A \rightarrow B \equiv \lnot A \vee B$, actions can be described by means of disjunctions.
\begin{example}[Moving blocks]
The action \texttt{stack(X, Y)} has pre-conditions \texttt{holding(X)} and \texttt{clear(Y)}, and
post-conditions \texttt{on(X, Y)}, \texttt{clear(X)} and \texttt{handfree}.
Its representation in Green's formulation is:
\[
\begin{split}
\texttt{holding(X, S)} \land \texttt{clear(Y, S)} &\rightarrow \\
&\texttt{on(X, Y, do(stack(X, Y), s))} \land \\
&\texttt{clear(X, do(stack(X, Y), s))} \land \\
&\texttt{handfree(do(stack(X, Y), s))} \\
\end{split}
\]
\end{example}
\item[Frame axioms]
Besides the effects of actions, each state also have to define for all non-changing fluents their frame axioms.
If the problem is complex, the number of frame axioms becomes unreasonable.
\begin{example}[Moving blocks]
\[ \texttt{on(U, V, S)}, \texttt{diff(U, X)} \rightarrow \texttt{on(U, V, do(move(X, Y, Z), S))} \]
\end{example}
\end{descriptionlist}
\begin{example}[Moving blocks]
The initial state is described by the following axioms:\\[0.5em]
\begin{minipage}{.3\linewidth}
\centering
\texttt{on(a, d, s0)} \\
\texttt{on(b, e, s0)} \\
\texttt{on(c, f, s0)} \\
\texttt{clear(a, s0)} \\
\texttt{clear(b, s0)} \\
\end{minipage}
\begin{minipage}{.3\linewidth}
\centering
\texttt{clear(c, s0)} \\
\texttt{clear(g, s0)} \\
\texttt{diff(a, b)} \\
\texttt{diff(a, c)} \\
\texttt{diff(a, d)} \dots \\
\end{minipage}
\begin{minipage}{.3\linewidth}
\centering
\includegraphics[width=\linewidth]{img/_moving_block_example_green.pdf}
\end{minipage}\\[0.5em]
For simplicity, we only consider the action \texttt{move(X, Y, Z)} that moves \texttt{X} from \texttt{Y} to \texttt{Z}.
It is defined as:
\[
\begin{split}
\texttt{clear(X, S)}&, \texttt{clear(Z, S)}, \texttt{on(X, Y, S)}, \texttt{diff(X, Z)} \rightarrow \\
&\texttt{clear(Y, do(move(X, Y, Z), S))}, \texttt{on(X, Z, do(move(X, Y, Z), S))}
\end{split}
\]
This action can be translated into the following effect axioms:
\[
\begin{split}
\lnot\texttt{clear(X, S)} &\vee \lnot\texttt{clear(Z, S)} \vee \lnot\texttt{on(X, Y, S)} \vee \lnot\texttt{diff(X, Z)} \vee \\
&\texttt{clear(Y, do(move(X, Y, Z), S))}
\end{split}
\]
\[
\begin{split}
\lnot\texttt{clear(X, S)} &\vee \lnot\texttt{clear(Z, S)} \vee \lnot\texttt{on(X, Y, S)} \vee \lnot\texttt{diff(X, Z)} \vee \\
&\texttt{on(X, Z, do(move(X, Y, Z), S))}
\end{split}
\]
\end{example}
Given the goal \texttt{on(a, b, s1)}, we prove that $\lnot\texttt{on(a, b, s1)}$ leads to an inconsistency.
We decide to make the following substitutions:
\[ \{ \texttt{X}/\texttt{a}, \texttt{Z}/\texttt{b}, \texttt{s1}/\texttt{do(move(a, Y, b), S)} \} \]
The premise of \texttt{move} leads to an inconsistency (when applying \texttt{move} its premise is false):
\begin{center}
\begin{tabular}{c|c|c|c}
$\lnot\texttt{clear(a, S)}$ & $\lnot\texttt{clear(b, S)}$ & $\lnot\texttt{on(a, Y, S)}$ & $\lnot\texttt{diff(a, b)}$ \\
False with $\{ \texttt{S}/\texttt{s0} \}$ & False with $\{ \texttt{S}/\texttt{s0} \}$
& False with $\{ \texttt{S}/\texttt{s0}, \texttt{Y}/\texttt{d} \}$ & False
\end{tabular}
\end{center}
Therefore, the substitution $\{ \texttt{s1}/\texttt{do(move(a, Y, b), S)} \}$ defines the plan to reach the goal \texttt{on(a, b, s1)}.
\subsubsection{Kowalsky's formulation}
\marginnote{Kowalsky's formulation}
Kowalsky's formulation avoids the frame axioms problem by using a set of fixed predicates:
\begin{descriptionlist}
\item[\texttt{holds(rel, s/a)}]
Describes the relations \texttt{rel} that are true in a state \texttt{s} or after the execution of an action \texttt{a}.
\item[\texttt{poss(s)}]
Indicates if a state \texttt{s} is possible.
\item[\texttt{pact(a, s)}]
Indicates if an action \texttt{a} can be executed in a state \texttt{s}.
\end{descriptionlist}
Actions can be described as:
\[ \texttt{poss(S)} \land \texttt{pact(A, S)} \rightarrow \texttt{poss(do(A, S))} \]
In the Kowalsky's formulation, each action requires a frame assertion (in Green's formulation, each state requires frame axioms).
\begin{example}[Moving blocks]
An initial state can be described by the following axioms:\\[0.5em]
\begin{minipage}{.35\linewidth}
\centering
\texttt{holds(on(a, b), s0)} \\
\texttt{holds(ontable(b), s0)} \\
\texttt{holds(ontable(c), s0)} \\
\end{minipage}
\begin{minipage}{.35\linewidth}
\centering
\texttt{holds(clear(a), s0)} \\
\texttt{holds(clear(c), s0)} \\
\texttt{holds(handempty, s0)} \\
\texttt{poss(s0)} \\
\end{minipage}
\begin{minipage}{.2\linewidth}
\centering
\includegraphics[width=0.6\linewidth]{img/_moving_block_example_kowalsky.pdf}
\end{minipage}\\[0.5em]
\end{example}
\begin{example}[Moving blocks]
The action \texttt{unstack(X, Y)} has:
\begin{descriptionlist}
\item[Pre-conditions] \texttt{on(X, Y)}, \texttt{clear(X)} and \texttt{handempty}
\item[Effects] \phantom{}
\begin{description}
\item[Add-list] \texttt{holding(X)} and \texttt{clear(Y)}
\item[Delete-list] \texttt{on(X, Y)}, \texttt{clear(X)} and \texttt{handempty}
\end{description}
\end{descriptionlist}
Its description in Kowalsky's formulation is:
\begin{descriptionlist}
\item[Pre-conditions]
\[
\begin{split}
\texttt{holds(on(X, Y), S)}&, \texttt{holds(clear(X), S)}, \texttt{holds(handempty, S)} \rightarrow \\
&\texttt{pact(unstack(X, Y), S)}
\end{split}
\]
\item[Effects] (use add-list)
\[ \texttt{holds(holding(X), do(unstack(X, Y), S))} \]
\[ \texttt{holds(clear(Y), do(unstack(X, Y), S))} \]
\item[Frame condition] (uses delete-list)
\[
\begin{split}
\texttt{holds(V, S)}&, \texttt{V} \neq \texttt{on(X, Y)}, \texttt{V} \neq \texttt{clear(X)}, \texttt{V} \neq \texttt{handempty}
\rightarrow \\
& \texttt{holds(V, do(unstack(X, Y), S))}
\end{split}
\]
\end{descriptionlist}
\end{example}
\subsection{STRIPS}
\marginnote{STRIPS}
STRIPS (Stanford Research Institute Problem Solver) is an ad-hoc algorithm
for linear planning resolution.
The elements of the problem are represented as:
\begin{descriptionlist}
\item[State] represented with its true fluents.
\item[Goal] represented with its true fluents.
\item[Action] represented using three lists:
\begin{descriptionlist}
\item[Preconditions] Fluents that are required to be true in order to apply the action.
\item[Delete-list] Fluents that become false after the action.
\item[Add-list] Fluents that become true after the action.
\end{descriptionlist}
Add-list and delete-list can be combined in an effect list with positive (add-list) and negative (delete-list) axioms.
\begin{description}
\item[STRIPS assumption] Everything that is not in the add-list or delete-list is unchanged in the next state.
\end{description}
\end{descriptionlist}
STRIPS uses two data structures:
\begin{descriptionlist}
\item[Goal stack] Does a backward search to reach the initial state.
\item[Current state] Represents the forward application of the actions found using the goal stack.
\end{descriptionlist}
\begin{algorithm}
\caption{STRIPS}
\begin{lstlisting}[mathescape=true]
def strips(problem):
goal_stack = Stack()
current_state = State(problem.initial_state)
goal_stack.push(problem.goal)
plan = []
while not goal_stack.empty():
if (goal_stack.top() is a single/conjunction of goals and
there is a substitution $\theta$ that makes it $\subseteq$ current_state):
A = goal_stack.pop()
$\theta$ = find_substitution(A, current_state)
goal_stack.apply_substitution($\theta$)
elif goal_stack.top() is a single goal:
R = rule with a $\in$ R.add_list
_ = goal_stack.pop() # Pop goal
goal_stack.push(R)
goal_stack.push(R.preconditions)
elif goal_stack.top() is a conjunction of goals:
for g in permutation(goal_stack.top()):
goal_stack.push(g)
# Note that there is no pop
elif goal_stack.top() is an action:
action = goal_stack.pop()
current_state.apply(action)
plan.append(action)
return plan
\end{lstlisting}
\end{algorithm}
\begin{example}[Moving blocks]
\begin{center}
\includegraphics[trim={0 16cm 0 0}, clip, width=0.85\textwidth]{img/_strips_example.pdf}
\end{center}
\begin{center}
\includegraphics[trim={0 0 0 33.8cm}, clip, width=0.85\textwidth]{img/_strips_example.pdf}
\end{center}
\end{example}
Since there are non-deterministic choices, the search space may become very large.
Heuristics may be used to avoid this.
Conjunction of goals are solved separately, but this could lead to the \marginnote{Sussman anomaly} \textbf{Sussman anomaly}
where a sub-goal destroys what another sub-goal has done.
For this reason, when a conjunction is encountered, it is not immediately popped from the goal stack
and is left as a final check.
\section{Non-linear planning}
\marginnote{Non-linear planning}
\subsection{Partial order planning}
Non-linear planning finds a plan as a search problem in the space of plans (instead of states as in linear planning).
Each node of the search tree is a partial plan. Edges represent plan refinement operations.
A non-linear plan is represented by:
\begin{descriptionlist}
\item[Actions{\normalfont.}] \marginnote{Actions set}
\item[Orderings] \marginnote{Orderings set}
between actions.
\item[Causal links] \marginnote{Causal links}
triplet $\langle S_i, S_j, c \rangle$ where $S_i$ and $S_j$ are actions and $c$ is a sub-goal.
$c$ should be the effect of $S_i$ and precondition of $S_j$.
Causal links represent causal relations between actions (i.e. interaction between sub-goals):
to execute $S_j$, the effect $c$ of $S_i$ is required first.
\end{descriptionlist}
The initial plan is an empty plan with two fake actions \texttt{start} and \texttt{stop}
with ordering $\texttt{start} < \texttt{stop}$:
\begin{descriptionlist}
\item[\texttt{start}] has no preconditions and the effects match the initial state.
\item[\texttt{stop}] has no effects and the preconditions match the goal.
\end{descriptionlist}
At each step, one of the following refinement operations can be applied until the goal is reached:
\begin{itemize}
\item Add an action to the set of actions.
\item Add an ordering to the set of orderings.
\item Add a causal link to the set of causal links.
\end{itemize}
\begin{figure}[h]
\centering
\includegraphics[width=0.45\textwidth]{img/_nonlinear_plan_example.pdf}
\caption{Example of search tree in non-linear planning}
\end{figure}
\begin{description}
\item[Least commitment planning] \marginnote{Least commitment planning}
Only strictly necessary restrictions (e.g. ordering) are imposed.
Non-linear planning is a least commitment planning.
\item[Linearization] \marginnote{Linearization}
At the end, the partially ordered actions should be linearized,
respecting the ordering constraints, to obtain the final plan.
\end{description}
\begin{description}
\item[Threat] \marginnote{Threat}
An action $S_k$ is a threat to a causal link $\langle S_i, S_j, c \rangle$
if its effects cancel $c$.
$S_k$ should not be executed in between $S_i$ and $S_j$.
\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{img/_threat_example.pdf}
\caption{Example of threat. Causal links are represented using thick arrows.}
\end{figure}
Possible solutions to a threat $S_k$ to $\langle S_i, S_j, c \rangle$ are:
\begin{descriptionlist}
\item[Demotion] \marginnote{Demotion}
Add the ordering constraint $S_k < S_i$ (i.e. threat executed before).
\item[Promotion] \marginnote{Promotion}
Add the ordering constraint $S_k > S_j$ (i.e. threat executed after).
\end{descriptionlist}
\end{description}
\begin{algorithm}[H]
\caption{Partial order planning (POP)}
\begin{lstlisting}[mathescape=true]
def pop(initial_state, goal, actions):
plan = init_empty_plan(initial_state, goal)
while not plan.isSolution():
try:
sn, c = selectSubgoal(plan)
chooseOperator(plan, actions, sn, c)
resolveThreats(plan)
except PlanFailError:
plan.backtrack()
return plan
def selectSubgoal(plan):
sn, c = random([sn, c in plan.steps if c in sn.unsolved_preconditions])
return sn, c
def chooseOperator(plan, actions, sn, c):
s = random([s in (actions + plan.steps) if c in s.effects])
if s is None: raise(PlanFailError)
plan.addCausalLink($\langle$s, sn, c$\rangle$)
plan.addOrdering(s < sn)
if s not in plan.steps:
plan.addAction(s)
plan.addOrdering(start < s < stop)
def resolveThreats(plan):
for s_k, s_i, s_j in plan.threats():
resolution = random([ DEMOTION, PROMOTION ])
if resolution == DEMOTION:
plan.addOrdering(s_k < s_i)
elif resolution == PROMOTION:
plan.addOrdering(s_k > s_j)
if plan.isNotConsistent(): raise(PlanFailError)
\end{lstlisting}
\end{algorithm}
\begin{example}[Purchasing schedule]
The initial state is:
\[ \texttt{at(home)}, \texttt{sells(hws, drill)}, \texttt{sells(sm, milk)}, \texttt{sells(sm, banana)} \]
where $\texttt{hws}$ means "hardware store" and $\texttt{sm}$ means "supermarket".
The goal is:
\[ \texttt{at(home)}, \texttt{have(drill)}, \texttt{have(milk)}, \texttt{have(banana)} \]
The possible actions are:\\[0.5em]
\begin{minipage}{.5\linewidth}
\begin{descriptionlist}
\item[\texttt{GO(X, Y)}] \phantom{}
\begin{description}
\item[Preconditions] $\texttt{at(X)}$
\item[Effects] $\texttt{at(Y)}$, $\lnot \texttt{at(X)}$
\end{description}
\end{descriptionlist}
\end{minipage}
\begin{minipage}{.5\linewidth}
\begin{descriptionlist}
\item[\texttt{BUY(S, Y)}] \phantom{}
\begin{description}
\item[Preconditions] $\texttt{at(S)}$, $\texttt{sells(S, Y)}$
\item[Effects] $\texttt{have(Y)}$
\end{description}
\end{descriptionlist}
\end{minipage}\\[0.5em]
Partial order planning steps are:
\begin{enumerate}
\item Define the initial plan:
\begin{center}
\includegraphics[width=0.7\textwidth]{img/_pop_example1.pdf}
\end{center}
\item The loop of POP is:
\begin{itemize}
\item Choose an action $a_i$ and one of its unsolved preconditions $c$.
\item Select an action $a_j$ with the precondition $c$ in its effects.
\item Add the ordering constraint $\texttt{start} < a_j < \texttt{stop}$.
\item Add the causal link $\langle a_j, a_i, c \rangle$ (and ordering $a_j < a_i$).
\item Solve threats.
\end{itemize}
We choose the action $a_i = \texttt{stop}$ and the precondition $c = \texttt{have(drill)}$.
We choose as action with $c$ in its effects $a_j = \texttt{BUY(X, drill)}$.
We therefore add to the plan the ordering $\texttt{start} < \texttt{BUY(X, drill)} < \texttt{stop}$ and
the causal link $\langle \texttt{BUY(X, drill)}, \texttt{stop}, \texttt{have(drill)} \rangle$:
\begin{center}
\includegraphics[width=0.7\textwidth]{img/_pop_example2.pdf}
\end{center}
\item Repeat the previous point for the preconditions $\texttt{have(milk)}$ and $\texttt{have(banana)}$:
\begin{center}
\includegraphics[width=0.7\textwidth]{img/_pop_example3.pdf}
\end{center}
\item Now, we choose as action $\texttt{BUY(X, drill)}$ and as unsolved precondition $\texttt{sells(X, drill)}$.
This can be solved from the action $\texttt{start}$ with effect $\texttt{sells(hws, drill)}$.
We make the substitution $\texttt{X}/\texttt{drill}$ and
add $\langle \texttt{start}, \texttt{BUY(hws, drill)}, \texttt{sells(hws, drill)} \rangle$ to the causal links.
The same process can be repeated for $\texttt{BUY(X, milk)}$ and $\texttt{BUY(X, banana)}$:
\begin{center}
\includegraphics[width=0.7\textwidth]{img/_pop_example4.pdf}
\end{center}
\item Now, we choose as action $\texttt{BUY(hws, drill)}$ and as unsolved precondition $\texttt{at(hws)}$.
This can be solved using the action $\texttt{GO(X, hws)}$.
We add $\langle \texttt{GO(X, hws)}, \texttt{BUY(hws, drill)}, \texttt{at(hws)} \rangle$ to the causal links.
We continue by choosing as action $\texttt{GO(X, hws)}$ and as unsolved precondition $\texttt{at(X)}$.
This can be solved from $\texttt{start}$ with effect $\texttt{at(home)}$.
We therefore make the substitution $\texttt{X}/\texttt{home}$ and
add $\langle \texttt{start}, \texttt{GO(home, hws)}, \texttt{at(home)} \rangle$ to the causal links.
The same process can be repeated for the $\texttt{milk}$ and $\texttt{banana}$ branch:
\begin{center}
\includegraphics[width=0.7\textwidth]{img/_pop_example5.pdf}
\end{center}
\item We have a threat between $\texttt{GO(home, hws)}$ and $\texttt{GO(home, sm)}$ as they both
require the precondition $\texttt{at(home)}$ and both have as effect $\lnot\texttt{at(home)}$.
It can be easily seen that neither promotion nor demotion solves the conflict.
We are therefore forced to backtrack.
We backtrack at the previous point, where we chose as action $\texttt{GO(X, sm)}$ and as precondition $\texttt{at(X)}$
(this step has been implicitly done in the previous point).
\begin{itemize}
\item Instead of choosing the action $\texttt{start}$, we choose $\texttt{GO(home, hws)}$ with the effect $\texttt{at(hws)}$.
We therefore make the substitution $\texttt{X}/\texttt{hws}$ and update the causal links.
\item We also resolve the threat $\texttt{GO(hws, sm)}$ to $\texttt{BUY(hws, drill)}$
(it removes the precondition $\texttt{at(hws)}$)
by promoting $\texttt{GO(hws, sm)}$
and adding the ordering constraint $\texttt{BUY(hws, drill)} < \texttt{GO(hws, sm)}$:
\end{itemize}
\begin{center}
\includegraphics[width=0.7\textwidth]{img/_pop_example6.pdf}
\end{center}
\item Now, we choose as action $\texttt{stop}$ and as precondition $\texttt{at(home)}$.
We choose as action $\texttt{GO(sm, home)}$ and update the causal links.
Finally, we solve the threat $\texttt{GO(sm, home)}$ to
both $\texttt{BUY(sm, milk)}$ and $\texttt{BUY(sm, banana)}$ (it removes the required precondition $\texttt{at(sm)}$)
by promoting $\texttt{GO(sm, home)}$.
The newly added ordering constraints are
$\texttt{BUY(sm, milk)} < \texttt{GO(sm, home)}$ and
$\texttt{BUY(sm, banana)} < \texttt{GO(sm, home)}$.
The final plan is:
\begin{center}
\includegraphics[width=0.7\textwidth]{img/_pop_example7.pdf}
\end{center}
By considering the ordering constraints, a linearization could be:
\[
\begin{split}
\texttt{GO(home, hws)} &\rightarrow
\texttt{BUY(hws, drill)} \rightarrow
\texttt{GO(hws, sm)} \rightarrow\\
&\texttt{BUY(sm, milk)} \rightarrow
\texttt{BUY(sm, banana)} \rightarrow
\texttt{GO(sm, home)}
\end{split}
\]
\end{enumerate}
\end{example}
\subsection{Modal truth criterion}
\marginnote{Modal truth criterion}
Modal truth criterion uses five plan refinement methods that
ensures the completeness of the planner (POP is not complete).
MTC refinement methods are:
\begin{descriptionlist}
\item[Establishment] \marginnote{Establishment}
The same standard operations of POP:
\begin{enumerate}
\item Insert a new action in the plan.
\item Add an ordering constraint.
\item Do a variable assignement.
\end{enumerate}
\item[Promotion] \marginnote{Promotion}
As in POP.
\item[Demotion] \marginnote{Demotion}
As in POP.
\item[White knight] \marginnote{White knight}
Insert an operator $S_n$ between $S_k$ and $S_j$, where $S_k$ threatens $S_j$,
in such way that $S_n$ re-establishes the preconditions of $S_j$.
\item[Separation] \marginnote{Separation}
Add a constraint to a variable to avoid that it unifies with an unwanted value.
\end{descriptionlist}
\section{Hierarchical planning}
\marginnote{Hierarchical planning}
Hierarchical planning allows to create a complex plan at different levels of abstraction.
Different meta-level searches are executed to generate meta-level plans that are progressively refined.
\subsection{ABSTRIPS}
\marginnote{ABSTRIPS}
In ABSTRIPS, a criticality value is assigned to each precondition based on the complexity of its achievement.
At each level, a plan is found assuming that the preconditions corresponding to lower levels of criticality are true.
At the next level, the previously found plan and its preconditions are used as starting point in the goal stack.
\begin{algorithm}
\caption{ABSTRIPS}
\begin{lstlisting}[mathescape=true]
def abstrips(problem, start_threshold, threshold_step):
threshold = start_threshold
plan = None
while $\text{there is a precondition still not considered}$:
true_preconds = problem.preconds[criticality < threshold]
plan = strips(problem, true_preconds, starting_plan=plan)
threshold -= threshold_step
return plan
\end{lstlisting}
\end{algorithm}
\subsection{Macro-operators}
\marginnote{Macro-operators}
In macro-operators, two types of operators are defined:
\begin{descriptionlist}
\item[Atomic] Elementary operations that can be executed by an agent.
\item[Macro] Set of atomic operators. Before execution, this type of operator has to be decomposed.
\begin{description}
\item[Precompiled decomposition]
The decomposition is known and described along side the preconditions and effects of the operator.
\item[Planned decomposition]
The planner has to synthesize the atomic operators that compose a macro operator.
\end{description}
Constraints are needed for a safe decomposition.
Let $A$ be a macro with effect $X$ and $P$ its decomposition:
\begin{itemize}
\item $X$ must be the effect of at least an atomic action in $P$ and should be protected until the end of $P$.
\item Each precondition of the actions in $P$ must be guaranteed by previous actions or be a precondition of $A$.
\item $P$ must not threat any causal link.
\end{itemize}
Moreover, when a macro action $A$ is replaced with its decomposition $P$:
\begin{itemize}
\item For each $B$ such that $B < A$, impose the ordering $B < \texttt{First($P$)}$.
\item For each $B$ such that $A < B$, impose the ordering $\texttt{Last($P$)} < B$.
\item Each causal link $\langle S, A, c \rangle$ is replaced with $\langle S, S_i, c \rangle$,
where $S_i$ are actions in $P$ with precondition $c$ and do not have other atomic operators of the macro before.
\item Each causal link $\langle A, S, c \rangle$ is replaced with $\langle S_i, A, c \rangle$,
where $S_i$ are actions in $P$ with effect $c$ and do not have other atomic operators of the macro after.
\end{itemize}
\end{descriptionlist}
\begin{algorithm}
\caption{Hierarchical decomposition POP}
\begin{lstlisting}[mathescape=true]
def hdpop(initial_state, goal, actions, decomposition_methods):
plan = init_empty_plan(initial_state, goal)
while not plan.isSolution():
try:
if choice() == ESTABLISHMENT:
sn, c = selectSubgoal(plan)
chooseOperator(plan, actions, sn, c)
else:
macro = selectMacroStep(plan)
chooseDecomposition(macro, decomposition_methods, plan)
resolveThreats(plan)
except PlanFailError:
plan.backtrack()
return plan
\end{lstlisting}
\end{algorithm}
\section{Conditional planning}
\marginnote{Conditional planning}
Conditional planning is based on the open world assumption where what is not in the initial state is unknown.
It generates a different plan for each source of uncertainty and therefore has exponential complexity.
\begin{description}
\item[Sensing action]
Action with pre-conditions and post-conditions that allows to obtain unknown information.
\end{description}
\begin{example}[Inflate tire]
\phantom{}\\
\begin{center}
\includegraphics[width=0.65\textwidth]{img/_conditional_planning.pdf}
\end{center}
When executing a sensing action, a copy of the goal is generated for each possible scenario.
\end{example}
\section{Reactive planning}
Reactive planners are on-line algorithms able to interact with the dynamicity the world.
\subsection{Pure reactive systems}
\marginnote{Pure reactive systems}
Pure reactive planners have a knowledge base that describes the conditions for which an action has to be executed.
The choice of the action is predictable. Therefore, this approach is not suited for domains that require reasoning.
\subsection{Hybrid systems}
\marginnote{Hybrid systems}
Hybrid planners integrate the generative and reactive approach.
The steps the algorithm does are:
\begin{itemize}
\item Generates a plan to achieve the goal.
\item Checks the pre-conditions and post-conditions of the action it is going to execute.
\item Backtracks the effects of an action in case of a failure.
\item Corrects the plan if external events occur.
\end{itemize}