diff --git a/images/blocks_world.png b/images/blocks_world.png new file mode 100644 index 000000000..cc772ae36 Binary files /dev/null and b/images/blocks_world.png differ diff --git a/learning.ipynb b/learning.ipynb index 78ff4f0e3..32a8c64ca 100644 --- a/learning.ipynb +++ b/learning.ipynb @@ -1168,7 +1168,7 @@ "cell_type": "code", "execution_count": 13, "metadata": { - "collapsed": false, + "collapsed": true, "deletable": true, "editable": true }, @@ -1518,7 +1518,7 @@ "language_info": { "codemirror_mode": { "name": "ipython", - "version": 3 + "version": 3.0 }, "file_extension": ".py", "mimetype": "text/x-python", @@ -1529,5 +1529,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 -} + "nbformat_minor": 0 +} \ No newline at end of file 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/logic.py b/logic.py index 68d996c14..ff5e6f09b 100644 --- a/logic.py +++ b/logic.py @@ -847,20 +847,22 @@ def subst(s, x): def fol_fc_ask(KB, alpha): """A simple forward-chaining algorithm. [Figure 9.3]""" - while new is not None: + while True: new = [] - for rule in KB: + for rule in KB.clauses: p, q = parse_definite_clause(standardize_variables(rule)) - for p_ in random.KB.clauses: + for p_ in KB.clauses: if p != p_: for theta in (subst(theta, p) == subst(theta, p_)): q_ = subst(theta, q) - if not unify(q_,KB.sentence in KB) or not unify(q_, new): + if not unify(q_,KB.sentence in KB) or not unify(q_, new): new.append(q_) phi = unify(q_,alpha) if phi is not None: return phi KB.tell(new) + if new is None: + break return None diff --git a/planning.ipynb b/planning.ipynb index d5a5eb25d..091a1c916 100644 --- a/planning.ipynb +++ b/planning.ipynb @@ -1,24 +1,504 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## PLANNING" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook describes the planning.py module, which covers Classical Planning from Chapter 10 & Planning & Acting in Real World Chapter 11." + ] + }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [], "source": [ - "import planning" + "from planning import *\n", + "from utils import expr" + ] + }, + { + "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", + "The `PDDL class` include:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#ACTIONS\n", + "Actions are described by a set of action schemas that implicitly define the class Actions:\n", + "Actions consists of a precondition(positive and negative) and effect(positive and negative). It consists of following " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# AIR CARGO PROBLEM from Figure 10.1\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" + ] + }, + { + "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" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following code defines the goal_test() function which tests if the solution achieves goal or not. 'required' states the goal:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "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)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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": [ + "\n", + "`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" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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_." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`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." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, the function returns the defined problem using PDLL." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`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" + ] + }, + { + "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": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# SPARE TIRE PROBLEM from Figure 10.2:\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": "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": [ + "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": [ + "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.\n", + "\n", + "![pL plot](images/blocks_world.png)" ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], - "source": [] + "source": [ + "" + ] } ], "metadata": { @@ -30,7 +510,7 @@ "language_info": { "codemirror_mode": { "name": "ipython", - "version": 3 + "version": 3.0 }, "file_extension": ".py", "mimetype": "text/x-python", @@ -42,4 +522,4 @@ }, "nbformat": 4, "nbformat_minor": 0 -} +} \ No newline at end of file diff --git a/planning.py b/planning.py index b92cb6eaa..5c0215cc5 100644 --- a/planning.py +++ b/planning.py @@ -557,12 +557,11 @@ def goal_test(kb): return False return True - # Actions - - # Hit - precond_pos = [expr("Approaching(Ball,loc)"), expr("At(actor,loc)")] - precond_neg = [] - effect_add = [expr("Returned(Ball)")] + ##actions + #hit + precond_pos=[expr("Approaching(Ball, loc)"), expr("At(actor, loc)")] + precond_neg=[] + effect_add=[expr("Returned(Ball)")] effect_rem = [] hit = Action(expr("Hit(actor, Ball)"), [precond_pos, precond_neg], [effect_add, effect_rem]) @@ -573,4 +572,4 @@ def goal_test(kb): effect_rem = [expr("At(actor, loc)")] go = Action(expr("Go(actor, to)"), [precond_pos, precond_neg], [effect_add, effect_rem]) - return PDLL(init, [hit, go], goal_test) + return PDLL(init, [hit, go], goal_test) \ No newline at end of file