diff --git a/images/blocks_world.png b/images/blocks_world.png new file mode 100644 index 000000000..26f3e2977 Binary files /dev/null and b/images/blocks_world.png differ diff --git a/images/dwr_state_transition.png b/images/dwr_state_transition.png new file mode 100644 index 000000000..ecc8ec004 Binary files /dev/null and b/images/dwr_state_transition.png differ diff --git a/images/factored_state_representation.png b/images/factored_state_representation.png new file mode 100644 index 000000000..d128f5f05 Binary files /dev/null and b/images/factored_state_representation.png differ diff --git a/logic.ipynb b/logic.ipynb index 079f1170b..7c12d7c66 100644 --- a/logic.ipynb +++ b/logic.ipynb @@ -306,11 +306,11 @@ "|--------------------------|----------------------|-------------------------|---|---|\n", "| Negation | ¬ P | `~P` | `~P` | `Expr('~', P)`\n", "| And | P ∧ Q | `P & Q` | `P & Q` | `Expr('&', P, Q)`\n", - "| Or | P ∨ Q | `P` | `Q`| `P` | `Q` | `Expr('`|`', P, Q)`\n", + "| Or | P ∨ Q | `P` | `Q`| `P` | `Q` | `Expr('`|`', P, Q)\n", "| Inequality (Xor) | P ≠ Q | `P ^ Q` | `P ^ Q` | `Expr('^', P, Q)`\n", "| Implication | P → Q | `P` |`'==>'`| `Q` | `P ==> Q` | `Expr('==>', P, Q)`\n", "| Reverse Implication | Q ← P | `Q` |`'<=='`| `P` |`Q <== P` | `Expr('<==', Q, P)`\n", - "| Equivalence | P ↔ Q | `P` |`'<=>'`| `Q` |`P <=> Q` | `Expr('<=>', P, Q)`\n", + "| Equivalence | P ↔ Q | `P` |`'<=>'`| `Q` |`P ==> Q` | `Expr('==>', P, Q)`\n", "\n", "Here's an example of defining a sentence with an implication arrow:" ] @@ -412,6 +412,7 @@ "\n", "The class `PropKB` can be used to represent a knowledge base of propositional logic sentences.\n", "\n", + "\n", "We see that the class `KB` has four methods, apart from `__init__`. A point to note here: the `ask` method simply calls the `ask_generator` method. Thus, this one has already been implemented and what you'll have to actually implement when you create your own knowledge base class (if you want to, though I doubt you'll ever need to; just use the ones we've created for you), will be the `ask_generator` function and not the `ask` function itself.\n", "\n", "The class `PropKB` now.\n", @@ -425,67 +426,367 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# TODO: More on KBs, plus what was promised in Intro Section\n", + "The following gives an idea how the python code works in logic.py:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "KB = PropKB()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "creates an empty knowledge base" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "KB.tell(A & C)\n", + "KB.ask(A) == KB.ask(C) == {}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "adds sentence and checks if KB entails the query." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "KB.ask(E)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{}" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "KB.tell(E)\n", + "KB.ask(E)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "KB.retract(C)\n", + "KB.ask(C)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "removes all clauses of 'C' from the sentence." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ "\n", - "TODO: fill in here ..." + "# The truth table enumeration algorithm from Figure 7.10:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "def tt_entails(kb, alpha):\n", + " \n", + " assert not variables(alpha)\n", + " return tt_check_all(kb, alpha, prop_symbols(kb & alpha), {})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Appendix: The Implementation of `|'==>'|`\n", + "Example:" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tt_entails(expr('P & Q'), expr('Q'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The tt_entail algorithm makes use of the tt_check_all() function, which gives results in the following manner. " + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tt_check_all(expr('P & Q'), expr('Q'), prop_symbols(expr('Q')), {})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "prop_symbols() is used to give the function argument in the form of symbols." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Example of the DPLL algorithm from Figure 7.17:" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{B: True, A: True}\n{P: True}\n{P: True}\n{P: False}\n" + ] + } + ], + "source": [ + "print (dpll_satisfiable(expr('A & B')))\n", "\n", - "Consider the `Expr` formed by this syntax:" + "print (dpll_satisfiable(expr('P | Q')))\n", + "\n", + "print (dpll_satisfiable(expr('P | ~Q')))\n", + "\n", + "print (dpll_satisfiable(expr('~P | Q')))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Example of the WalkSAT algorithm from Figure 7.18:" ] }, { "cell_type": "code", - "execution_count": 15, - "metadata": { - "collapsed": false - }, + "execution_count": 24, + "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(P ==> ~Q)" + "{C: True, B: True, A: True}" ] }, - "execution_count": 15, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "P |'==>'| ~Q" + "WalkSAT([A & B, A & C], 0.5, 100 )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "What is the funny `|'==>'|` syntax? The trick is that \"`|`\" is just the regular Python or-operator, and so is exactly equivalent to this: " + "# Example of the SATplan algorithm from Figure 7.22:" ] }, { "cell_type": "code", - "execution_count": 16, - "metadata": { - "collapsed": false - }, + "execution_count": 25, + "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(P ==> ~Q)" + "['Left', 'Left']" ] }, - "execution_count": 16, + "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], + "source": [ + "transition = {'A': {'Left': 'A', 'Right': 'B'},\n", + " 'B': {'Left': 'A', 'Right': 'C'},\n", + " 'C': {'Left': 'B', 'Right': 'C'}}\n", + "\n", + "SAT_plan('C', transition, 'A', 3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# unify() algorithm from Figure 9.1:\n", + "\n", + " Returns a substitution to make the first 2 arguments identical, and the third argument is the substitution built up so far." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{x: 2}\n" + ] + } + ], + "source": [ + "print(unify(x, 2, {}))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# TODO: More on KBs, plus what was promised in Intro Section\n", + "\n", + "TODO: fill in here ..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Appendix: The Implementation of `|'==>'|`\n", + "\n", + "Consider the `Expr` formed by this syntax:" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "P |'==>'| ~Q" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What is the funny `|'==>'|` syntax? The trick is that \"`|`\" is just the regular Python or-operator, and so is exactly equivalent to this: " + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": false + }, + "outputs": [], "source": [ "(P | '==>') | ~Q" ] @@ -499,7 +800,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 29, "metadata": { "collapsed": false }, @@ -510,7 +811,7 @@ "PartialExpr('==>', P)" ] }, - "execution_count": 17, + "execution_count": 29, "metadata": {}, "output_type": "execute_result" } @@ -530,7 +831,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 30, "metadata": { "collapsed": false }, @@ -541,7 +842,7 @@ "(P ==> ~Q)" ] }, - "execution_count": 18, + "execution_count": 30, "metadata": {}, "output_type": "execute_result" } @@ -571,7 +872,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 31, "metadata": { "collapsed": false }, @@ -582,7 +883,7 @@ "(~(P & Q) ==> (~P | ~Q))" ] }, - "execution_count": 19, + "execution_count": 31, "metadata": {}, "output_type": "execute_result" } @@ -600,7 +901,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 32, "metadata": { "collapsed": false }, @@ -611,7 +912,7 @@ "(~(P & Q) ==> (~P | ~Q))" ] }, - "execution_count": 20, + "execution_count": 32, "metadata": {}, "output_type": "execute_result" } @@ -630,7 +931,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 33, "metadata": { "collapsed": false }, @@ -641,7 +942,7 @@ "(((P & Q) ==> P) | Q)" ] }, - "execution_count": 21, + "execution_count": 33, "metadata": {}, "output_type": "execute_result" } @@ -659,7 +960,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 34, "metadata": { "collapsed": false }, @@ -670,7 +971,7 @@ "((P & Q) ==> (P | Q))" ] }, - "execution_count": 22, + "execution_count": 34, "metadata": {}, "output_type": "execute_result" } @@ -701,16 +1002,16 @@ "language_info": { "codemirror_mode": { "name": "ipython", - "version": 3 + "version": 3.0 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.4.3" + "version": "3.5.1" } }, "nbformat": 4, "nbformat_minor": 0 -} +} \ No newline at end of file diff --git a/planning.ipynb b/planning.ipynb index 37461ee9b..d84dab483 100644 --- a/planning.ipynb +++ b/planning.ipynb @@ -2,27 +2,37 @@ "cells": [ { "cell_type": "markdown", - "metadata": { - "collapsed": true - }, + + "metadata": {}, + "source": [ + "# PLANNING" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, "source": [ - "# Planning: planning.py; chapters 10-11" + "This notebook describes the planning.py module, which covers Classical Planning from Chapter 10 & Planning & Acting in Real World Chapter 11." + ] }, { "cell_type": "markdown", "metadata": {}, "source": [ + "This notebook describes the [planning.py](https://github.com/aimacode/aima-python/blob/master/planning.py) module, which covers Chapters 10 (Classical Planning) and 11 (Planning and Acting in the Real World) of *[Artificial Intelligence: A Modern Approach](http://aima.cs.berkeley.edu)*. See the [intro notebook](https://github.com/aimacode/aima-python/blob/master/intro.ipynb) for instructions.\n", "\n", "We'll start by looking at `PDDL` and `Action` data types for defining problems and actions. Then, we will see how to use them by trying to plan a trip from *Sibiu* to *Bucharest* across the familiar map of Romania, from [search.ipynb](https://github.com/aimacode/aima-python/blob/master/search.ipynb). Finally, we will look at the implementation of the GraphPlan algorithm.\n", "\n", "The first step is to load the code:" + ] }, { "cell_type": "code", "execution_count": 1, + "metadata": { "collapsed": false }, @@ -51,12 +61,244 @@ { "cell_type": "code", "execution_count": 2, + "metadata": { "collapsed": false }, "outputs": [], "source": [ + + "from planning import *\n", + "from utils import expr" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **The Planning Problem** \n", + "> To find an executable sequence of actions that achieves a given goal when performed starting in a given state.\n", + "\n", + "Motivation of the planning process is to reason about possible course of actions that will change the environment in order to reach the goal (task)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Planning v/s Scheduling\n", + "\n", + "We need to understand the difference between the terms:\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "**Scheduling** - assigns in time resources to separate processes.\n", + "\n", + "Given: _resources, actions and constraints._\n", + "\n", + " Form an appropriate schedule that meets the constraints\n", + "\n", + " Arrange the actions, assign resources and satisfy the constrains.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Planning** - considers possible interaction among components of plan.\n", + "\n", + "Given: _the initial state, goal state, operators._\n", + "\n", + " Find a sequence of operators that will reach the goal state from the initial state\n", + "\n", + " Select appropriate actions, arrange the actions and consider the causalities" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Assumptions in Classical Planning\n", + "\n", + "Classical planners make at least the following assumptions:\n", + "\n", + "- the agent's actions are deterministic; that is, the agent can predict the consequences of its actions.\n", + "- there are no external events beyond the control of the agent that change the state of the world.\n", + "- the world is fully observable; thus, the agent can observe the current state of the world.\n", + "- time progresses discretely from one state to the next.\n", + "- goals are predicates of states that must be achieved or maintained.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Representations For Planning:\n", + "\n", + "1. **STRIPS** \n", + "The simplest language used for formalizing actions is the STRIPS language. In STRIPS, the state variables have the domain {0,1} (equivalently {FALSE, TRUE}), and an action consists of three sets of state variables, the PRECONDITION, the ADD={a1,a2,...,an} list, and the DELETE={d1,d2,...,dm} list (it is assumed that ADD and DELETE don't intersect.) \n", + "\n", + "2. **ADL**\n", + "Action description language (ADL) is an automated planning and scheduling system in particular for robots. It is considered an advancement of STRIPS. We won't go ino its details here.\n", + "\n", + "3. **PDDL**\n", + "(\"Planning Domain Definition Language\") is a recent atempt to standardize planning domain and problem description languages. It was developed mainly to make the 1998/2000 International Planning Competitions possible. \n", + "\n", + "The differences of PDDL in comparison to STRIPS are:\n", + "\n", + " - The PRECONDITION may be an arbitrary Boolean combination of atomic facts about the state variables. Atomic facts say something about one state variable, for example a=0 or b=1. A precondition could for example be (a=1)∨¬(b=1∧c=0).\n", + " - Instead of the unconditional assignments represented by ADD and DELETE, the effects may be conditional. This means that the effects are of the form, IF condition THEN a := v where the condition is a Boolean combination of facts. STRIPS corresponds to PDDL with trivial conditions that are always true (the condition is the constant TRUE).\n", + " - Goals may be Boolean combinations of atomic facts (formulas). \n", + "\n", + "We will be using **PDDL** consistent with the book." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#PDDL \n", + "The PDDL (Planning Domain Definition Language) allows us to express all actions with one action schema.\n", + "\n", + "It can be used to define a problem:\n", + "1. initial state\n", + "2. Actions that are available in a state\n", + "3. Result of applying an action\n", + "4. The goal test\n", + "\n", + "\n", + "The `PDDL class` includes:\n", + "\n", + "1. **`init(self, initial_state, actions, goal_test)`**: the constructor creates a knowledge base with initial state, initialises actions and `goal_test_func` function with `goal_test`.\n", + "2. **`goal_test(self)`**: initialises `goal_test` with `kb`.\n", + "3. **`act(self, action)`**: performs the action given as argument, along with checks preformed on pre-conditions.\n", + "\n", + "\n", + "PDDL is a domain definition language. It is used to define the properties of a domain, the predicates which are used and the action definition. A predicate defines the property of an object which can be true or false, e.g. yellow t-shirt. Yellow is the property and t-shirt is the object. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#ACTIONS\n", + "Actions are described by a set of action schemas that implicitly define the `class Actions`.\n", + "The schema consists of a action name, a list of variables used in the schema, a precondition (positive and negative) and effect (positive and negative). \n", + "\n", + "The **precondition** of an action specifies when the action can be carried out. The precondition of an action is a proposition that must be true before the action can be carried out. In terms of constraints, the robot is constrained to only be able to choose an action for which the precondition is true. \n", + "For example, in the block problem move(x,y) has preconditions clear(x) and clear(y). The action move(x,table) is always possible.\n", + "\n", + "The **effect** of an action specifies the resulting state.\n", + "Each problem described in chapter 10 has:\n", + "- an initial state\n", + "- a goal\n", + "- actions with preconditions and effects (these action are split into _pos (positive conditions) and _neg (negative conditions))\n", + "Each problem thus requires a solution which is satisfied by some initial conditions and solved using actions which meet the preconditions and effects.\n", + " \n", + "We say that action `a` is **applicable** in state s if the preconditions are satisfied by s.\n", + "\n", + "Now that we have a sense of the representations let's go through some examples." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Factored Representation:\n", + "\n", + "In contrast to atomic representation where state is a single indivisible entity (figure on the left), in factored representation state is a collection of variables (figure on the right below).\n", + "\n", + " The problems we see ahead are in factored state representation.","\n","Now that we have a sense of the representations let's see some examples." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# AIR CARGO PROBLEM\n", + "\n", + "The problem is to transport cargo via plane to & from airports.\n", + "\n", + "###Real Life Cargo Transportaion by Planes instance:\n", + "- 10 airports\n", + "- 50 aircrafts\n", + "- 200 pieces of cargo\n", + "- no. of states 1050 x (50 + 10)200 $\\approx$ 10405\n", + "- minimum number of actions 50 x 9 =450 (all cargo located on airport with no planes)\n", + "- maximum number of actions 50200 x 9 $\\approx$ 10340 (all cargo and aircrafts in one airport)\n", + "\n", + "Practically: The number of particles in the universe is about **_1087_**.\n", + "\n", + "That is where automated planning research comes in to solve such problems using classical planning (or other algorithms)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#####For now we will stick to the example from the book from Fig. 10.1:\n", + "\n", + "\n", + "To define a problem we have to define an initial state (predicates which are true at the beginning of the problem) and a goal state (predicates which are true at the end of the problem). \n", + "\n", + "\n", + "The following code defines the initial state for the problem\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "def air_cargo():\n", + " init = [expr('At(C1, SFO)'), \n", + " expr('At(C2, JFK)'),\n", + " expr('At(P1, SFO)'),\n", + " expr('At(P2, JFK)'),\n", + " expr('Cargo(C1)'),\n", + " expr('Cargo(C2)'),\n", + " expr('Plane(P1)'),\n", + " expr('Plane(P2)'),\n", + " expr('Airport(JFK)'),\n", + " expr('Airport(SFO)')]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`init` defines the initial state of the problem.\n", + "\n", + "**`expr('At(C1, SF0)')`** represents the predicate **Cargo 1 at San Fransisco**\n", + "\n", + "**`expr('At(P1, SF0)')`** represents the predicate **Plane 1 at San Fransisco** ... and so on.\n", + "\n", + "\n", + "\n", + "The following code defines the goal_test() function which tests if the solution achieves goal or not. 'required' states the goal:" + "%psource Action" + ] }, { @@ -322,12 +564,424 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, + "execution_count": 3, + "metadata": {}, "outputs": [], - "source": [] + "source": [ + "def goal_test(kb):\n", + " required = [expr('At(C1 , JFK)'), expr('At(C2 ,SFO)')]\n", + " for q in required:\n", + " if kb.ask(q) is False:\n", + " return False\n", + " return True" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this problem the Goal is **`(At(C1 , JFK ) ∧ At(C2 , SFO))`** i.e., **Cargo 1 ar JFK and Cargo 2 at San Fransisco** which is written as:\n", + "\n", + "`required = [expr('At(C1 , JFK)'), expr('At(C2 ,SFO)')]`\n", + "\n", + "The function `goal_test(kb)` takes a knowledge base as argument, and for every predicate in `required` (goal), it checks the `ask` function from `KB class`. The `ask` function returns value `True` or `False` accordingly if predicate in `required` meets preconditions or not (defined ahead).\n", + "\n", + "\n", + "Actions such as 'load', 'unload' and fly are defined with preconditions and effects accompanying them." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "# Actions\n", + "# Load\n", + "precond_pos = [expr(\"At(c, a)\"), expr(\"At(p, a)\"), expr(\"Cargo(c)\"), expr(\"Plane(p)\"), expr(\"Airport(a)\")]\n", + "precond_neg = []\n", + "effect_add = [expr(\"In(c, p)\")]\n", + "effect_rem = [expr(\"At(c, a)\")]\n", + "load = Action(expr(\"Load(c, p, a)\"), [precond_pos, precond_neg], [effect_add, effect_rem])\n", + "\n", + "# Unload\n", + "precond_pos = [expr(\"In(c, p)\"), expr(\"At(p, a)\"), expr(\"Cargo(c)\"), expr(\"Plane(p)\"), expr(\"Airport(a)\")]\n", + "precond_neg = []\n", + "effect_add = [expr(\"At(c, a)\")]\n", + "effect_rem = [expr(\"In(c, p)\")]\n", + "unload = Action(expr(\"Unload(c, p, a)\"), [precond_pos, precond_neg], [effect_add, effect_rem])\n", + "\n", + "# Fly\n", + "# Used 'f' instead of 'from' because 'from' is a python keyword and expr uses eval() function\n", + "precond_pos = [expr(\"At(p, f)\"), expr(\"Plane(p)\"), expr(\"Airport(f)\"), expr(\"Airport(to)\")]\n", + "precond_neg = []\n", + "effect_add = [expr(\"At(p, to)\")]\n", + "effect_rem = [expr(\"At(p, f)\")]\n", + "fly = Action(expr(\"Fly(p, f, to)\"), [precond_pos, precond_neg], [effect_add, effect_rem])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`precond_` is used to denote predicates which must be True **before** the action.\n", + "eg: \n", + "\n", + "`effect_` is used to denote predicates which must be True **after** the action.\n", + "\n", + "`precon_pos` & `effect_add` are used to denote predicates which must be **True**.\n", + "\n", + "`precon_neg` & `effect_rem` are used to denote predicates which must be **False**.\n", + "\n", + "\n", + "Eg: in Action `load`\n", + "\n", + "`precond_pos = [expr(\"At(c, a)\"), expr(\"At(p, a)\"), expr(\"Cargo(c)\"), expr(\"Plane(p)\"), expr(\"Airport(a)\")]` is a precondition which must be **True** denoting predicate _Cargo c at Airport a & Plane p at Airport a_.\n", + "\n", + "`precond_neg = []` is a precondition which must be **False**. \t\t\t\n", + "\n", + "`effect_add = [expr(\"In(c, p)\")]` is an effect which must be **True** denoting the predicate _Cargo c in Plane p_.\n", + "\n", + "`effect_rem = [expr(\"At(c, a)\")]`is an effect which must be **False** denoting the predicate _Cargo c at Airport a_.\n", + "\n", + "`load = Action(expr(\"Load(c, p, a)\"), [precond_pos, precond_neg], [effect_add, effect_rem])` thus define the action **`Load(c, p, a)** with the preconditions it must follow and the effects it leads to.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Finally, the function returns the defined problem using PDLL.\n", + "\n", + "`return(PDLL(init, [load, unload, fly], goal_test)`\n", + "\n", + " which defines the problem as a whole with its initial state (`init`), the actions possible(` [load, unload, fly]`) and the goal(`goal_test`)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A solution to the air_cargo problem is as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "solution = [expr(\"Load(C1 , P1, SFO)\"),\n", + " expr(\"Fly(P1, SFO, JFK)\"),\n", + " expr(\"Unload(C1, P1, JFK)\"),\n", + " expr(\"Load(C2, P2, JFK)\"),\n", + " expr(\"Fly(P2, JFK, SFO)\"),\n", + " expr(\"Unload (C2, P2, SFO)\")]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where `expr(\"Load(C1 , P1, SFO)\")` means _load the Cargo C1 in Plane P1 at San Fransico_. In order for this action to take place the preconditions we specified while defining the action `Load` must be met. The effects from this action are then carried forward i.e., they now are an existing state and it should be sought that these effects do **not** clash with preconditions of actions ahead, otherwise the action can't be completed. \n", + "\n", + "Following lines describe the _plan_ of the above solution:\n", + "\n", + "`expr(\"Load(C1 , P1, SFO)\") ` --> _Load Cargo C1 in Plane P1 at San Fransico_\n", + "\n", + "`expr(\"Fly(P1, SFO, JFK)\")` --> _Fly Plane P1 from San Fransisco to JFK_\n", + "\n", + "`expr(\"Unload(C1, P1, JFK)\")` --> _Unload Cargo C1 from Plane P1 at JFK_\n", + "\n", + "`expr(\"Load(C2, P2, JFK)\")` --> _Load Cargo C2 in Plane P2 at JFK_\n", + "\n", + "`expr(\"Fly(P2, JFK, SFO)\")` --> _Fly Plane P2 from JFK to San Fransisco_\n", + "\n", + "`expr(\"Unload (C2, P2, SFO)\")` --> _Unload Cargo C2 from Plane P2 at San Fransisco_\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We then execute the action on the state's kb." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "a = air_cargo()\n", + "\n", + "for action in solution:\n", + " a.act(action)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where each action is acted upon leading to a state which is tested below to be the goal state or not." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.goal_test()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Yes, the solution is correct. You may try any other solution to check if it achieves the goal or not." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Another related example - The Dock-Worker Robots (DWR) Domain\n", + "\n", + "It is specifically an example of automated planning, with the following scenario:\n", + "- harbour with several locations (docs)\n", + "- docked ships\n", + "- storage area for containers\n", + "- parking area for trains, trucks\n", + "\n", + "- Goal: \n", + " \t1. cranes to load and unload ships\n", + " \t2. robot carts to move around containers\n", + "\n", + "Like the air cargo transport problem, the actions can be sought to be **put, take, load, unload, move**.\n", + "\n", + "The following figure depicts a simple instance of the problem where the initial state is S0 (robot at location 2 and container on pallet in location 1) and the goal state is S5 (container on robot at location 2). The state transitions are accompanied by the following actions:\n", + "\n", + "- S0 (robot at location 2 and container on pallet in location 1) -- **initial state**; `At(robot, location2), At(container, location1), At(container, pallet)`\n", + "- S1 (robot at location 2 and container on crane in location 1) -- action `take(crane, container)` \n", + "- S2 (robot at location 1 and container on pallet in location 1) -- action `move(location2, location1), put(container, pallet)`\n", + "- S3 (robot at location 1 and container on crane in location 1) -- action `take(crane, container)`\n", + "- S4 (robot at location 1 and container on robot in location 1) -- action `load(robot, container)`\n", + "- S5 (robot at location 2 and container on robot in location 2) -- action `move(location1, location2)` ; **goal state**\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# SPARE TIRE PROBLEM from Figure 10.2:\n", + "\n", + "The Spare Tire problem is to replace a flat tire on axle with a spare one. \n", + "\n", + "The problem follows the same structure of function as before, only the predicates are changed.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "init = [expr('Tire(Flat)'),\n", + " expr('Tire(Spare)'),\n", + " expr('At(Flat, Axle)'),\n", + " expr('At(Spare, Trunk)')]\n", + "\n", + "\n", + "required = [expr('At(Spare, Axle)'), expr('At(Flat, Ground)')]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`init ` states the initial state:\n", + "\n", + "`expr('Tire(Flat)')` --> _Flat Tire_\n", + "\n", + "`expr('Tire(Spare)')` --> _Spare Tire_\n", + "\n", + "`expr('At(Flat, Axle)')` --> _Flat Tire on Axle_\n", + "\n", + "`expr('At(Spare, Trunk)')` --> _Spare Tire in Trunk_\n", + "\n", + "\n", + "`required = [expr('At(Spare, Axle)'), expr('At(Flat, Ground)')]` states the goal i.e., _Spare tire must be on Axle, and Flat tire on Ground_\n", + "\n", + "Just a sidenote, the action `At()` means same as _on, in, at_ in the problem reference." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "# Actions\n", + "\n", + "# Remove\n", + "precond_pos = [expr(\"At(obj, loc)\")]\n", + "precond_neg = []\n", + "effect_add = [expr(\"At(obj, Ground)\")]\n", + "effect_rem = [expr(\"At(obj, loc)\")]\n", + "remove = Action(expr(\"Remove(obj, loc)\"), [precond_pos, precond_neg], [effect_add, effect_rem])\n", + "\n", + "# PutOn\n", + "precond_pos = [expr(\"Tire(t)\"), expr(\"At(t, Ground)\")]\n", + "precond_neg = [expr(\"At(Flat, Axle)\")]\n", + "effect_add = [expr(\"At(t, Axle)\")]\n", + "effect_rem = [expr(\"At(t, Ground)\")]\n", + "put_on = Action(expr(\"PutOn(t, Axle)\"), [precond_pos, precond_neg], [effect_add, effect_rem])\n", + "\n", + "# LeaveOvernight\n", + "precond_pos = []\n", + "precond_neg = []\n", + "effect_add = []\n", + "effect_rem = [expr(\"At(Spare, Ground)\"), expr(\"At(Spare, Axle)\"), expr(\"At(Spare, Trunk)\"),\n", + " expr(\"At(Flat, Ground)\"), expr(\"At(Flat, Axle)\"), expr(\"At(Flat, Trunk)\")]\n", + "leave_overnight = Action(expr(\"LeaveOvernight\"), [precond_pos, precond_neg],\n", + " [effect_add, effect_rem])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The problem involves 3 actions:\n", + "\n", + "1. `Remove(obj, loc)` --> Remove object _obj_ from location _loc_.\n", + "2. `PutOn(t, Axle)` --> Put tire_t_ on _Axle_\n", + "3. `Leaveovernight` --> Leave tire overnight _(we assume the neighbourhood is good and we find the tire at the same place the next day)_" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "solution to the spare tire problem from the book is as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "solution = [expr(\"Remove(Flat, Axle)\"),\n", + " expr(\"Remove(Spare, Trunk)\"),\n", + " expr(\"PutOn(Spare, Axle)\")]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Following lines describe the _plan_ of the above solution:\n", + "\n", + "`expr(\"Remove(Flat, Axle)\")` --> _Remove Flat tire from Axle_\n", + "\n", + "`expr(\"Remove(Spare, Trunk)\")` --> _Remove Spare tire from Trunk_\n", + "\n", + "`expr(\"PutOn(Spare, Axle)\")` --> _Put Spare tire on Axle_\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "let's test it in the same way as before :" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s = spare_tire()\n", + "\n", + "for action in solution:\n", + " s.act(action)\n", + "\n", + "s.goal_test()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The solution achieves the goal." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# THE BLOCKS WORLD from Figure 10.3 :" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " The above image below shows the transitions between different states which are possible for 3 blocks. Watch how the rightmost transition is what we follow in the book. " + ] } ], "metadata": { @@ -339,7 +993,7 @@ "language_info": { "codemirror_mode": { "name": "ipython", - "version": 3 + "version": 3.0 }, "file_extension": ".py", "mimetype": "text/x-python", pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy