? users online
  • Logout
    • Open hangout
    • Open chat for current file
<div class="notebook">

<div class="nb-cell markdown" name="md1">
# STRIPS
This notebook explores [*STRIPS*](https://en.wikipedia.org/wiki/Stanford_Research_Institute_Problem_Solver); Stanford Research Institute Problem Solver.

STRIPS is 

&gt; an automated planner developed by Richard Fikes and Nils Nilsson
</div>

<div class="nb-cell markdown" name="md2">
## Blocks World
We will make plans in [blocks world](https://en.wikipedia.org/wiki/Blocks_world). Blocks world is

&gt; one of the most famous planning domains in artificial intelligence. A set of wooden blocks of various shapes and colors sitting on a table. The goal is to build one or more vertical stacks of blocks. Only one block may be moved at a time: it may either be placed on the table or placed atop another block. Because of this, any blocks that are, at a given time, under another block cannot be moved. Moreover, some kinds of blocks cannot have other blocks stacked on top of them. 
</div>

<div class="nb-cell html" name="htm1">
<svg width="480" height="480" viewBox="0 0 5 5" xmlns="http://www.w3.org/2000/svg">
  <style>
    .label { font-weight: normal; font-size: 0.8px; }
  </style>
  <g transform="scale(1 -1) translate(0 -5)" stroke="black" stroke-width="0.1" fill="none">
    <g transform="translate(0, 1.5)">
      <line x1="0" y1="0" x2="5" y2="0"></line>
      <g name="b" transform="translate(0.5, 0)">
        <rect x="0" y="0" width="1" height="1"></rect>
        <text x="0.5" y="-0.5" transform="scale(1 -1) translate(-0.2, 0.3)" fill="black" class="label">b</text>
      </g>
      <g name="a" transform="translate(0.5, 1)">
        <rect x="0" y="0" width="1" height="1"></rect>
        <text x="0.5" y="-0.5" transform="scale(1 -1) translate(-0.2, 0.3)" fill="black" class="label">a</text>
      </g>
      <g name="c" transform="translate(3.5, 0)">
        <rect x="0" y="0" width="1" height="1"></rect>
        <text x="0.5" y="-0.5" transform="scale(1 -1) translate(-0.2, 0.3)" fill="black" class="label">c</text>
      </g>
      <g name="p" transform="translate(0.5, -1)">
        <text x="0.5" y="-0.5" transform="scale(1 -1) translate(-0.2, 0.3)" fill="black" class="label">p</text>
      </g>
      <g name="q" transform="translate(2, -1)">
        <text x="0.5" y="-0.5" transform="scale(1 -1) translate(-0.2, 0.3)" fill="black" class="label">q</text>
      </g>
      <g name="r" transform="translate(3.5, -1)">
        <text x="0.5" y="-0.5" transform="scale(1 -1) translate(-0.2, 0.3)" fill="black" class="label">r</text>
      </g>
    </g>
  </g>
</svg>
</div>

<div class="nb-cell markdown" name="md8">
Our world has three blocks: a, b, c, and three places on the table: p, q, r.
</div>

<div class="nb-cell program" data-background="true" name="p3">
block(a). 
block(b). 
block(c).

place(p). 
place(q). 
place(r).
</div>

<div class="nb-cell query" name="q2">
block(Block).
</div>

<div class="nb-cell query" name="q3">
place(Place).
</div>

<div class="nb-cell markdown" name="md3">
## State Representation
We will represent a state in the blocks world as a list of terms `on(X, Y)`. `X` can be a block, e.g. "a", "b", "c", and `Y` can either be a block or a place on the table, e.g. "p", "q", "r".

As an example the state above is represented as

```prolog
[on(a, b), on(b, p), on(c, r)].
```
</div>

<div class="nb-cell markdown" name="md4">
## `solve`
We will introduce a top-level term that allows us to come up with a plan to go from an `Initial` state to a `Final` state.

We delegate the actual solving to our implementation of STRIPS.
</div>

<div class="nb-cell program" data-background="true" name="p1">
solve(Initial, Final, Plan) :- strips(Initial, Final, Plan).
</div>

<div class="nb-cell query" name="q10">
solve([on(a, b), on(b, p), on(c, r)], [on(a, b), on(b, c), on(c,q)], Plan).
</div>

<div class="nb-cell markdown" name="md5">
## `strips`
The `strips/3` clause does the heavy lifting of coming up with a plan. There are two cases to consider.

1. We already reached the `Final` state. In this case our plan can be empty.
2. We haven't reached the `Final` state. In that case we perform any legal action to an intermediate state and try to reach the `Final` state from there.

### Optimalisation
#### Visited States
With the above considerations it is not garantueed that Prolog can find a solution. The reason for this is that Prolog would happily move a to b, and back again ad infinitum. In order to prevent the revisiting intermediate states, we keep track of the visited intermediate states.

#### Shorter Plan
In general we will favor shorter plans over longer plans. Since Prolog out of the box does a depth first search, we are not guaranteed to find the shortest plan first.

One way to remedy this is use [iterative deepening](https://en.wikipedia.org/wiki/Iterative_deepening_depth-first_search).
</div>

<div class="nb-cell program" data-background="true" name="p2">
strips(Initial, Final, Plan) :- strips(Initial, Final, [Initial], Plan).

strips(Initial, Final, Visited, Plan) :- 
    deepening_strips(1, Initial, Final, Visited, Plan).

deepening_strips(Bound, Initial, Final, Visited, Plan) :-
    bounded_strips(Bound, Initial, Final, Visited, Plan).
deepening_strips(Bound, Initial, Final, Visited, Plan) :-
	succ(Bound, Successor),
    deepening_strips(Successor, Initial, Final, Visited, Plan).

bounded_strips(_, Final, Final, _, []).
bounded_strips(Bound, Initial, Final, Visited, [Action|Actions]) :-
    succ(Predecessor, Bound),
    action(Initial, Action),
    perform(Initial, Action, Intermediate),
    \+ member(Intermediate, Visited),
    bounded_strips(Predecessor, Intermediate, Final, [Intermediate|Visited], Actions).
</div>

<div class="nb-cell markdown" name="md6">
## Definition
the `strips/4` clause is defined in terms of `action/2` and `perform/3`. In this section we will take a look at the definition of these clauses.
</div>

<div class="nb-cell markdown" name="md7">
### `action`
This clause is responsible for determining the legal actions in a state. All actions are of the form `move(Block, Destination)`.

A action `move(Block, Destination)` is legal if

1. `Block` is a block.
2. `Block` is not the `Destination`.
3. `Block` is free to move in this state. I.e. nothing is on `Block`.
4. `Destination` is free to move to in this state. I.e. nothing in on `Destination`.
</div>

<div class="nb-cell program" data-background="true" name="p4">
action(State, move(Block, Destination)) :-
    block(Block),
    \+ Block == Destination,
    free(State, Block),
    free(State, Destination).
       
free(State, Thing) :-
    thing(Thing),
    \+ member(on(_, Thing), State).

thing(Block) :- block(Block).
thing(Place) :- place(Place).
</div>

<div class="nb-cell query" name="q1">
free([on(a, b)], a).
</div>

<div class="nb-cell query" name="q4">
\+ free([on(a, b)], b).
</div>

<div class="nb-cell query" name="q5">
action([on(a, b), on(b, p), on(c, r)], move(a, q)).
</div>

<div class="nb-cell query" name="q11">
\+ action([on(a, b), on(b, p), on(c, r)], move(a, a)).
</div>

<div class="nb-cell query" name="q6">
action([on(a, b), on(b, p), on(c, r)], Action).
</div>

<div class="nb-cell markdown" name="md9">
### `perform`
This clause is responsible for changing the `Source` state into the `Target` state by performing an `Action`.
</div>

<div class="nb-cell program" data-background="true" name="p5">
perform(Source, move(Block, Destination), Target) :-
    substitute(on(Block, _), Source, on(Block, Destination), Target).
</div>

<div class="nb-cell query" name="q7">
perform([on(a, b), on(b, p), on(c, r)], 
        move(a, c),
        [on(a, c), on(b, p), on(c, r)]).
</div>

<div class="nb-cell markdown" name="md10">
## `substitute`
Given two lists `As` and `Bs`, `substitute/4` will substitute every term `A` in `As` with `B` to produce `Bs`.
</div>

<div class="nb-cell program" data-background="true" name="p6">
substitute(_, [], _, []).
substitute(A, [A|As], B, [B|Bs]) :-
    substitute(A, As, B, Bs), !.
substitute(A, [X|As], B, [X|Bs]) :-
    substitute(A, As, B, Bs).
</div>

<div class="nb-cell query" name="q8">
substitute(a, [a, b, c], x, [x, b, c]).
</div>

<div class="nb-cell query" name="q9">
substitute(X, [a, b, c], x, [a, x, c]).
</div>

</div>