logic.ipynb 193 ko
Newer Older
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n",
       "   \"http://www.w3.org/TR/html4/strict.dtd\">\n",
       "\n",
       "<html>\n",
       "<head>\n",
       "  <title></title>\n",
       "  <meta http-equiv=\"content-type\" content=\"text/html; charset=None\">\n",
       "  <style type=\"text/css\">\n",
       "td.linenos { background-color: #f0f0f0; padding-right: 10px; }\n",
       "span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }\n",
       "pre { line-height: 125%; }\n",
       "body .hll { background-color: #ffffcc }\n",
       "body  { background: #f8f8f8; }\n",
       "body .c { color: #408080; font-style: italic } /* Comment */\n",
       "body .err { border: 1px solid #FF0000 } /* Error */\n",
       "body .k { color: #008000; font-weight: bold } /* Keyword */\n",
       "body .o { color: #666666 } /* Operator */\n",
       "body .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       "body .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       "body .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       "body .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       "body .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       "body .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       "body .gd { color: #A00000 } /* Generic.Deleted */\n",
       "body .ge { font-style: italic } /* Generic.Emph */\n",
       "body .gr { color: #FF0000 } /* Generic.Error */\n",
       "body .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       "body .gi { color: #00A000 } /* Generic.Inserted */\n",
       "body .go { color: #888888 } /* Generic.Output */\n",
       "body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       "body .gs { font-weight: bold } /* Generic.Strong */\n",
       "body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       "body .gt { color: #0044DD } /* Generic.Traceback */\n",
       "body .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       "body .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       "body .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       "body .kp { color: #008000 } /* Keyword.Pseudo */\n",
       "body .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       "body .kt { color: #B00040 } /* Keyword.Type */\n",
       "body .m { color: #666666 } /* Literal.Number */\n",
       "body .s { color: #BA2121 } /* Literal.String */\n",
       "body .na { color: #7D9029 } /* Name.Attribute */\n",
       "body .nb { color: #008000 } /* Name.Builtin */\n",
       "body .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       "body .no { color: #880000 } /* Name.Constant */\n",
       "body .nd { color: #AA22FF } /* Name.Decorator */\n",
       "body .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       "body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       "body .nf { color: #0000FF } /* Name.Function */\n",
       "body .nl { color: #A0A000 } /* Name.Label */\n",
       "body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       "body .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       "body .nv { color: #19177C } /* Name.Variable */\n",
       "body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       "body .w { color: #bbbbbb } /* Text.Whitespace */\n",
       "body .mb { color: #666666 } /* Literal.Number.Bin */\n",
       "body .mf { color: #666666 } /* Literal.Number.Float */\n",
       "body .mh { color: #666666 } /* Literal.Number.Hex */\n",
       "body .mi { color: #666666 } /* Literal.Number.Integer */\n",
       "body .mo { color: #666666 } /* Literal.Number.Oct */\n",
       "body .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       "body .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       "body .sc { color: #BA2121 } /* Literal.String.Char */\n",
       "body .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       "body .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       "body .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       "body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       "body .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       "body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       "body .sx { color: #008000 } /* Literal.String.Other */\n",
       "body .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       "body .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       "body .ss { color: #19177C } /* Literal.String.Symbol */\n",
       "body .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       "body .fm { color: #0000FF } /* Name.Function.Magic */\n",
       "body .vc { color: #19177C } /* Name.Variable.Class */\n",
       "body .vg { color: #19177C } /* Name.Variable.Global */\n",
       "body .vi { color: #19177C } /* Name.Variable.Instance */\n",
       "body .vm { color: #19177C } /* Name.Variable.Magic */\n",
       "body .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "\n",
       "  </style>\n",
       "</head>\n",
       "<body>\n",
       "<h2></h2>\n",
       "\n",
       "<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">dpll</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">,</span> <span class=\"n\">symbols</span><span class=\"p\">,</span> <span class=\"n\">model</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;See if the clauses are true in a partial model.&quot;&quot;&quot;</span>\n",
       "    <span class=\"n\">unknown_clauses</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>  <span class=\"c1\"># clauses with an unknown truth value</span>\n",
       "    <span class=\"k\">for</span> <span class=\"n\">c</span> <span class=\"ow\">in</span> <span class=\"n\">clauses</span><span class=\"p\">:</span>\n",
       "        <span class=\"n\">val</span> <span class=\"o\">=</span> <span class=\"n\">pl_true</span><span class=\"p\">(</span><span class=\"n\">c</span><span class=\"p\">,</span> <span class=\"n\">model</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">if</span> <span class=\"n\">val</span> <span class=\"ow\">is</span> <span class=\"bp\">False</span><span class=\"p\">:</span>\n",
       "            <span class=\"k\">return</span> <span class=\"bp\">False</span>\n",
       "        <span class=\"k\">if</span> <span class=\"n\">val</span> <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"bp\">True</span><span class=\"p\">:</span>\n",
       "            <span class=\"n\">unknown_clauses</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">c</span><span class=\"p\">)</span>\n",
       "    <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"n\">unknown_clauses</span><span class=\"p\">:</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">model</span>\n",
       "    <span class=\"n\">P</span><span class=\"p\">,</span> <span class=\"n\">value</span> <span class=\"o\">=</span> <span class=\"n\">find_pure_symbol</span><span class=\"p\">(</span><span class=\"n\">symbols</span><span class=\"p\">,</span> <span class=\"n\">unknown_clauses</span><span class=\"p\">)</span>\n",
       "    <span class=\"k\">if</span> <span class=\"n\">P</span><span class=\"p\">:</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">dpll</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">,</span> <span class=\"n\">removeall</span><span class=\"p\">(</span><span class=\"n\">P</span><span class=\"p\">,</span> <span class=\"n\">symbols</span><span class=\"p\">),</span> <span class=\"n\">extend</span><span class=\"p\">(</span><span class=\"n\">model</span><span class=\"p\">,</span> <span class=\"n\">P</span><span class=\"p\">,</span> <span class=\"n\">value</span><span class=\"p\">))</span>\n",
       "    <span class=\"n\">P</span><span class=\"p\">,</span> <span class=\"n\">value</span> <span class=\"o\">=</span> <span class=\"n\">find_unit_clause</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">,</span> <span class=\"n\">model</span><span class=\"p\">)</span>\n",
       "    <span class=\"k\">if</span> <span class=\"n\">P</span><span class=\"p\">:</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">dpll</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">,</span> <span class=\"n\">removeall</span><span class=\"p\">(</span><span class=\"n\">P</span><span class=\"p\">,</span> <span class=\"n\">symbols</span><span class=\"p\">),</span> <span class=\"n\">extend</span><span class=\"p\">(</span><span class=\"n\">model</span><span class=\"p\">,</span> <span class=\"n\">P</span><span class=\"p\">,</span> <span class=\"n\">value</span><span class=\"p\">))</span>\n",
       "    <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"n\">symbols</span><span class=\"p\">:</span>\n",
       "        <span class=\"k\">raise</span> <span class=\"ne\">TypeError</span><span class=\"p\">(</span><span class=\"s2\">&quot;Argument should be of the type Expr.&quot;</span><span class=\"p\">)</span>\n",
       "    <span class=\"n\">P</span><span class=\"p\">,</span> <span class=\"n\">symbols</span> <span class=\"o\">=</span> <span class=\"n\">symbols</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">],</span> <span class=\"n\">symbols</span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">:]</span>\n",
       "    <span class=\"k\">return</span> <span class=\"p\">(</span><span class=\"n\">dpll</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">,</span> <span class=\"n\">symbols</span><span class=\"p\">,</span> <span class=\"n\">extend</span><span class=\"p\">(</span><span class=\"n\">model</span><span class=\"p\">,</span> <span class=\"n\">P</span><span class=\"p\">,</span> <span class=\"bp\">True</span><span class=\"p\">))</span> <span class=\"ow\">or</span>\n",
       "            <span class=\"n\">dpll</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">,</span> <span class=\"n\">symbols</span><span class=\"p\">,</span> <span class=\"n\">extend</span><span class=\"p\">(</span><span class=\"n\">model</span><span class=\"p\">,</span> <span class=\"n\">P</span><span class=\"p\">,</span> <span class=\"bp\">False</span><span class=\"p\">)))</span>\n",
       "</pre></div>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "psource(dpll)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The algorithm uses the ideas described above to check satisfiability of a sentence in propositional logic.\n",
    "It recursively calls itself, simplifying the problem at each step. It also uses helper functions `find_pure_symbol` and `find_unit_clause` to carry out steps 2 and 3 above.\n",
    "<br>\n",
    "The `dpll_satisfiable` helper function converts the input clauses to _conjunctive normal form_ and calls the `dpll` function with the correct parameters."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n",
       "   \"http://www.w3.org/TR/html4/strict.dtd\">\n",
       "\n",
       "<html>\n",
       "<head>\n",
       "  <title></title>\n",
       "  <meta http-equiv=\"content-type\" content=\"text/html; charset=None\">\n",
       "  <style type=\"text/css\">\n",
       "td.linenos { background-color: #f0f0f0; padding-right: 10px; }\n",
       "span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }\n",
       "pre { line-height: 125%; }\n",
       "body .hll { background-color: #ffffcc }\n",
       "body  { background: #f8f8f8; }\n",
       "body .c { color: #408080; font-style: italic } /* Comment */\n",
       "body .err { border: 1px solid #FF0000 } /* Error */\n",
       "body .k { color: #008000; font-weight: bold } /* Keyword */\n",
       "body .o { color: #666666 } /* Operator */\n",
       "body .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       "body .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       "body .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       "body .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       "body .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       "body .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       "body .gd { color: #A00000 } /* Generic.Deleted */\n",
       "body .ge { font-style: italic } /* Generic.Emph */\n",
       "body .gr { color: #FF0000 } /* Generic.Error */\n",
       "body .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       "body .gi { color: #00A000 } /* Generic.Inserted */\n",
       "body .go { color: #888888 } /* Generic.Output */\n",
       "body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       "body .gs { font-weight: bold } /* Generic.Strong */\n",
       "body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       "body .gt { color: #0044DD } /* Generic.Traceback */\n",
       "body .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       "body .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       "body .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       "body .kp { color: #008000 } /* Keyword.Pseudo */\n",
       "body .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       "body .kt { color: #B00040 } /* Keyword.Type */\n",
       "body .m { color: #666666 } /* Literal.Number */\n",
       "body .s { color: #BA2121 } /* Literal.String */\n",
       "body .na { color: #7D9029 } /* Name.Attribute */\n",
       "body .nb { color: #008000 } /* Name.Builtin */\n",
       "body .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       "body .no { color: #880000 } /* Name.Constant */\n",
       "body .nd { color: #AA22FF } /* Name.Decorator */\n",
       "body .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       "body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       "body .nf { color: #0000FF } /* Name.Function */\n",
       "body .nl { color: #A0A000 } /* Name.Label */\n",
       "body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       "body .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       "body .nv { color: #19177C } /* Name.Variable */\n",
       "body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       "body .w { color: #bbbbbb } /* Text.Whitespace */\n",
       "body .mb { color: #666666 } /* Literal.Number.Bin */\n",
       "body .mf { color: #666666 } /* Literal.Number.Float */\n",
       "body .mh { color: #666666 } /* Literal.Number.Hex */\n",
       "body .mi { color: #666666 } /* Literal.Number.Integer */\n",
       "body .mo { color: #666666 } /* Literal.Number.Oct */\n",
       "body .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       "body .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       "body .sc { color: #BA2121 } /* Literal.String.Char */\n",
       "body .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       "body .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       "body .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       "body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       "body .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       "body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       "body .sx { color: #008000 } /* Literal.String.Other */\n",
       "body .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       "body .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       "body .ss { color: #19177C } /* Literal.String.Symbol */\n",
       "body .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       "body .fm { color: #0000FF } /* Name.Function.Magic */\n",
       "body .vc { color: #19177C } /* Name.Variable.Class */\n",
       "body .vg { color: #19177C } /* Name.Variable.Global */\n",
       "body .vi { color: #19177C } /* Name.Variable.Instance */\n",
       "body .vm { color: #19177C } /* Name.Variable.Magic */\n",
       "body .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "\n",
       "  </style>\n",
       "</head>\n",
       "<body>\n",
       "<h2></h2>\n",
       "\n",
       "<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">dpll_satisfiable</span><span class=\"p\">(</span><span class=\"n\">s</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Check satisfiability of a propositional sentence.</span>\n",
       "<span class=\"sd\">    This differs from the book code in two ways: (1) it returns a model</span>\n",
       "<span class=\"sd\">    rather than True when it succeeds; this is more useful. (2) The</span>\n",
       "<span class=\"sd\">    function find_pure_symbol is passed a list of unknown clauses, rather</span>\n",
       "<span class=\"sd\">    than a list of all clauses and the model; this is more efficient.&quot;&quot;&quot;</span>\n",
       "    <span class=\"n\">clauses</span> <span class=\"o\">=</span> <span class=\"n\">conjuncts</span><span class=\"p\">(</span><span class=\"n\">to_cnf</span><span class=\"p\">(</span><span class=\"n\">s</span><span class=\"p\">))</span>\n",
       "    <span class=\"n\">symbols</span> <span class=\"o\">=</span> <span class=\"nb\">list</span><span class=\"p\">(</span><span class=\"n\">prop_symbols</span><span class=\"p\">(</span><span class=\"n\">s</span><span class=\"p\">))</span>\n",
       "    <span class=\"k\">return</span> <span class=\"n\">dpll</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">,</span> <span class=\"n\">symbols</span><span class=\"p\">,</span> <span class=\"p\">{})</span>\n",
       "</pre></div>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "psource(dpll_satisfiable)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's see a few examples of usage."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [],
   "source": [
    "A, B, C, D = expr('A, B, C, D')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{A: True, B: True, C: False, D: True}"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dpll_satisfiable(A & B & ~C & D)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is a simple case to highlight that the algorithm actually works."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{B: True, D: False}"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dpll_satisfiable((A & B) | (C & ~A) | (B & ~D))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If a particular symbol isn't present in the solution, \n",
    "it means that the solution is independent of the value of that symbol.\n",
    "In this case, the solution is independent of A."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{A: True, B: True}"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dpll_satisfiable(A |'<=>'| B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{A: False, B: True, C: True}"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dpll_satisfiable((A |'<=>'| B) |'==>'| (C & ~A))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{B: True, C: True}"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dpll_satisfiable((A | (B & C)) |'<=>'| ((A | B) & (A | C)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. WalkSAT algorithm\n",
    "This algorithm is very similar to Hill climbing.\n",
    "On every iteration, the algorithm picks an unsatisfied clause and flips a symbol in the clause.\n",
    "This is similar to finding a neighboring state in the `hill_climbing` algorithm.\n",
    "<br>\n",
    "The symbol to be flipped is decided by an evaluation function that counts the number of unsatisfied clauses.\n",
    "Sometimes, symbols are also flipped randomly, to avoid local optima. A subtle balance between greediness and randomness is required. Alternatively, some versions of the algorithm restart with a completely new random assignment if no solution has been found for too long, as a way of getting out of local minima of numbers of unsatisfied clauses.\n",
    "<br>\n",
    "<br>\n",
    "Let's have a look at the algorithm."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n",
       "   \"http://www.w3.org/TR/html4/strict.dtd\">\n",
       "\n",
       "<html>\n",
       "<head>\n",
       "  <title></title>\n",
       "  <meta http-equiv=\"content-type\" content=\"text/html; charset=None\">\n",
       "  <style type=\"text/css\">\n",
       "td.linenos { background-color: #f0f0f0; padding-right: 10px; }\n",
       "span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }\n",
       "pre { line-height: 125%; }\n",
       "body .hll { background-color: #ffffcc }\n",
       "body  { background: #f8f8f8; }\n",
       "body .c { color: #408080; font-style: italic } /* Comment */\n",
       "body .err { border: 1px solid #FF0000 } /* Error */\n",
       "body .k { color: #008000; font-weight: bold } /* Keyword */\n",
       "body .o { color: #666666 } /* Operator */\n",
       "body .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       "body .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       "body .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       "body .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       "body .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       "body .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       "body .gd { color: #A00000 } /* Generic.Deleted */\n",
       "body .ge { font-style: italic } /* Generic.Emph */\n",
       "body .gr { color: #FF0000 } /* Generic.Error */\n",
       "body .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       "body .gi { color: #00A000 } /* Generic.Inserted */\n",
       "body .go { color: #888888 } /* Generic.Output */\n",
       "body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       "body .gs { font-weight: bold } /* Generic.Strong */\n",
       "body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       "body .gt { color: #0044DD } /* Generic.Traceback */\n",
       "body .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       "body .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       "body .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       "body .kp { color: #008000 } /* Keyword.Pseudo */\n",
       "body .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       "body .kt { color: #B00040 } /* Keyword.Type */\n",
       "body .m { color: #666666 } /* Literal.Number */\n",
       "body .s { color: #BA2121 } /* Literal.String */\n",
       "body .na { color: #7D9029 } /* Name.Attribute */\n",
       "body .nb { color: #008000 } /* Name.Builtin */\n",
       "body .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       "body .no { color: #880000 } /* Name.Constant */\n",
       "body .nd { color: #AA22FF } /* Name.Decorator */\n",
       "body .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       "body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       "body .nf { color: #0000FF } /* Name.Function */\n",
       "body .nl { color: #A0A000 } /* Name.Label */\n",
       "body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       "body .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       "body .nv { color: #19177C } /* Name.Variable */\n",
       "body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       "body .w { color: #bbbbbb } /* Text.Whitespace */\n",
       "body .mb { color: #666666 } /* Literal.Number.Bin */\n",
       "body .mf { color: #666666 } /* Literal.Number.Float */\n",
       "body .mh { color: #666666 } /* Literal.Number.Hex */\n",
       "body .mi { color: #666666 } /* Literal.Number.Integer */\n",
       "body .mo { color: #666666 } /* Literal.Number.Oct */\n",
       "body .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       "body .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       "body .sc { color: #BA2121 } /* Literal.String.Char */\n",
       "body .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       "body .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       "body .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       "body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       "body .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       "body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       "body .sx { color: #008000 } /* Literal.String.Other */\n",
       "body .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       "body .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       "body .ss { color: #19177C } /* Literal.String.Symbol */\n",
       "body .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       "body .fm { color: #0000FF } /* Name.Function.Magic */\n",
       "body .vc { color: #19177C } /* Name.Variable.Class */\n",
       "body .vg { color: #19177C } /* Name.Variable.Global */\n",
       "body .vi { color: #19177C } /* Name.Variable.Instance */\n",
       "body .vm { color: #19177C } /* Name.Variable.Magic */\n",
       "body .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "\n",
       "  </style>\n",
       "</head>\n",
       "<body>\n",
       "<h2></h2>\n",
       "\n",
       "<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">WalkSAT</span><span class=\"p\">(</span><span class=\"n\">clauses</span><span class=\"p\">,</span> <span class=\"n\">p</span><span class=\"o\">=</span><span class=\"mf\">0.5</span><span class=\"p\">,</span> <span class=\"n\">max_flips</span><span class=\"o\">=</span><span class=\"mi\">10000</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Checks for satisfiability of all clauses by randomly flipping values of variables</span>\n",
       "<span class=\"sd\">    &quot;&quot;&quot;</span>\n",
       "    <span class=\"c1\"># Set of all symbols in all clauses</span>\n",
       "    <span class=\"n\">symbols</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"n\">sym</span> <span class=\"k\">for</span> <span class=\"n\">clause</span> <span class=\"ow\">in</span> <span class=\"n\">clauses</span> <span class=\"k\">for</span> <span class=\"n\">sym</span> <span class=\"ow\">in</span> <span class=\"n\">prop_symbols</span><span class=\"p\">(</span><span class=\"n\">clause</span><span class=\"p\">)}</span>\n",
       "    <span class=\"c1\"># model is a random assignment of true/false to the symbols in clauses</span>\n",
       "    <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"n\">s</span><span class=\"p\">:</span> <span class=\"n\">random</span><span class=\"o\">.</span><span class=\"n\">choice</span><span class=\"p\">([</span><span class=\"bp\">True</span><span class=\"p\">,</span> <span class=\"bp\">False</span><span class=\"p\">])</span> <span class=\"k\">for</span> <span class=\"n\">s</span> <span class=\"ow\">in</span> <span class=\"n\">symbols</span><span class=\"p\">}</span>\n",
       "    <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">max_flips</span><span class=\"p\">):</span>\n",
       "        <span class=\"n\">satisfied</span><span class=\"p\">,</span> <span class=\"n\">unsatisfied</span> <span class=\"o\">=</span> <span class=\"p\">[],</span> <span class=\"p\">[]</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">clause</span> <span class=\"ow\">in</span> <span class=\"n\">clauses</span><span class=\"p\">:</span>\n",
       "            <span class=\"p\">(</span><span class=\"n\">satisfied</span> <span class=\"k\">if</span> <span class=\"n\">pl_true</span><span class=\"p\">(</span><span class=\"n\">clause</span><span class=\"p\">,</span> <span class=\"n\">model</span><span class=\"p\">)</span> <span class=\"k\">else</span> <span class=\"n\">unsatisfied</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">clause</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"n\">unsatisfied</span><span class=\"p\">:</span>  <span class=\"c1\"># if model satisfies all the clauses</span>\n",
       "            <span class=\"k\">return</span> <span class=\"n\">model</span>\n",
       "        <span class=\"n\">clause</span> <span class=\"o\">=</span> <span class=\"n\">random</span><span class=\"o\">.</span><span class=\"n\">choice</span><span class=\"p\">(</span><span class=\"n\">unsatisfied</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">if</span> <span class=\"n\">probability</span><span class=\"p\">(</span><span class=\"n\">p</span><span class=\"p\">):</span>\n",
       "            <span class=\"n\">sym</span> <span class=\"o\">=</span> <span class=\"n\">random</span><span class=\"o\">.</span><span class=\"n\">choice</span><span class=\"p\">(</span><span class=\"nb\">list</span><span class=\"p\">(</span><span class=\"n\">prop_symbols</span><span class=\"p\">(</span><span class=\"n\">clause</span><span class=\"p\">)))</span>\n",
       "        <span class=\"k\">else</span><span class=\"p\">:</span>\n",
       "            <span class=\"c1\"># Flip the symbol in clause that maximizes number of sat. clauses</span>\n",
       "            <span class=\"k\">def</span> <span class=\"nf\">sat_count</span><span class=\"p\">(</span><span class=\"n\">sym</span><span class=\"p\">):</span>\n",
       "                <span class=\"c1\"># Return the the number of clauses satisfied after flipping the symbol.</span>\n",
       "                <span class=\"n\">model</span><span class=\"p\">[</span><span class=\"n\">sym</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"ow\">not</span> <span class=\"n\">model</span><span class=\"p\">[</span><span class=\"n\">sym</span><span class=\"p\">]</span>\n",
       "                <span class=\"n\">count</span> <span class=\"o\">=</span> <span class=\"nb\">len</span><span class=\"p\">([</span><span class=\"n\">clause</span> <span class=\"k\">for</span> <span class=\"n\">clause</span> <span class=\"ow\">in</span> <span class=\"n\">clauses</span> <span class=\"k\">if</span> <span class=\"n\">pl_true</span><span class=\"p\">(</span><span class=\"n\">clause</span><span class=\"p\">,</span> <span class=\"n\">model</span><span class=\"p\">)])</span>\n",
       "                <span class=\"n\">model</span><span class=\"p\">[</span><span class=\"n\">sym</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"ow\">not</span> <span class=\"n\">model</span><span class=\"p\">[</span><span class=\"n\">sym</span><span class=\"p\">]</span>\n",
       "                <span class=\"k\">return</span> <span class=\"n\">count</span>\n",
       "            <span class=\"n\">sym</span> <span class=\"o\">=</span> <span class=\"n\">argmax</span><span class=\"p\">(</span><span class=\"n\">prop_symbols</span><span class=\"p\">(</span><span class=\"n\">clause</span><span class=\"p\">),</span> <span class=\"n\">key</span><span class=\"o\">=</span><span class=\"n\">sat_count</span><span class=\"p\">)</span>\n",
       "        <span class=\"n\">model</span><span class=\"p\">[</span><span class=\"n\">sym</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"ow\">not</span> <span class=\"n\">model</span><span class=\"p\">[</span><span class=\"n\">sym</span><span class=\"p\">]</span>\n",
       "    <span class=\"c1\"># If no solution is found within the flip limit, we return failure</span>\n",
       "    <span class=\"k\">return</span> <span class=\"bp\">None</span>\n",
       "</pre></div>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "psource(WalkSAT)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The function takes three arguments:\n",
    "<br>\n",
    "1. The `clauses` we want to satisfy.\n",
    "<br>\n",
    "2. The probability `p` of randomly changing a symbol.\n",
    "<br>\n",
    "3. The maximum number of flips (`max_flips`) the algorithm will run for. If the clauses are still unsatisfied, the algorithm returns `None` to denote failure.\n",
    "<br>\n",
    "The algorithm is identical in concept to Hill climbing and the code isn't difficult to understand.\n",
    "<br>\n",
    "<br>\n",
    "Let's see a few examples of usage."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [],
   "source": [
    "A, B, C, D = expr('A, B, C, D')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{A: True, B: True, C: False, D: True}"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "WalkSAT([A, B, ~C, D], 0.5, 100)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is a simple case to show that the algorithm converges."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{A: True, B: True, C: True}"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "WalkSAT([A & B, A & C], 0.5, 100)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{A: True, B: True, C: True, D: True}"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "WalkSAT([A & B, C & D, C & B], 0.5, 100)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [],
   "source": [
    "WalkSAT([A & B, C | D, ~(D | B)], 0.5, 1000)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This one doesn't give any output because WalkSAT did not find any model where these clauses hold. We can solve these clauses to see that they together form a contradiction and hence, it isn't supposed to have a solution."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "One point of difference between this algorithm and the `dpll_satisfiable` algorithms is that both these algorithms take inputs differently. \n",
    "For WalkSAT to take complete sentences as input, \n",
    "we can write a helper function that converts the input sentence into conjunctive normal form and then calls WalkSAT with the list of conjuncts of the CNF form of the sentence."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [],
   "source": [
    "def WalkSAT_CNF(sentence, p=0.5, max_flips=10000):\n",
    "    return WalkSAT(conjuncts(to_cnf(sentence)), 0, max_flips)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we can call `WalkSAT_CNF` and `DPLL_Satisfiable` with the same arguments."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{A: False, B: False, C: True, D: False}"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "WalkSAT_CNF((A & B) | (C & ~A) | (B & ~D), 0.5, 1000)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It works!\n",
    "<br>\n",
    "Notice that the solution generated by WalkSAT doesn't omit variables that the sentence doesn't depend upon. \n",
    "If the sentence is independent of a particular variable, the solution contains a random value for that variable because of the stochastic nature of the algorithm.\n",
    "<br>\n",
    "<br>\n",
    "Let's compare the runtime of WalkSAT and DPLL for a few cases. We will use the `%%timeit` magic to do this."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [],
   "source": [
    "sentence_1 = A |'<=>'| B\n",
    "sentence_2 = (A & B) | (C & ~A) | (B & ~D)\n",
    "sentence_3 = (A | (B & C)) |'<=>'| ((A | B) & (A | C))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6.78 ms ± 238 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit\n",
    "dpll_satisfiable(sentence_1)\n",
    "dpll_satisfiable(sentence_2)\n",
    "dpll_satisfiable(sentence_3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4.64 ms ± 65.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit\n",
    "WalkSAT_CNF(sentence_1)\n",
    "WalkSAT_CNF(sentence_2)\n",
    "WalkSAT_CNF(sentence_3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "On an average, for solvable cases, `WalkSAT` is quite faster than `dpll` because, for a small number of variables, \n",
    "`WalkSAT` can reduce the search space significantly. \n",
    "Results can be different for sentences with more symbols though.\n",
    "Feel free to play around with this to understand the trade-offs of these algorithms better."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### SATPlan"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this section we show how to make plans by logical inference. The basic idea is very simple. It includes the following three steps:\n",
    "1. Constuct a sentence that includes:\n",
    "    1. A colection of assertions about the initial state.\n",
    "    2. The successor-state axioms for all the possible actions at each time up to some maximum time t.\n",
    "    3. The assertion that the goal is achieved at time t.\n",
    "2. Present the whole sentence to a SAT solver.\n",
    "3. Assuming a model is found, extract from the model those variables that represent actions and are assigned true. Together they represent a plan to achieve the goals.\n",
    "\n",
    "\n",
    "Lets have a look at the algorithm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n",
       "   \"http://www.w3.org/TR/html4/strict.dtd\">\n",
       "\n",
       "<html>\n",
       "<head>\n",
       "  <title></title>\n",
       "  <meta http-equiv=\"content-type\" content=\"text/html; charset=None\">\n",
       "  <style type=\"text/css\">\n",
       "td.linenos { background-color: #f0f0f0; padding-right: 10px; }\n",
       "span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }\n",
       "pre { line-height: 125%; }\n",
       "body .hll { background-color: #ffffcc }\n",
       "body  { background: #f8f8f8; }\n",
       "body .c { color: #408080; font-style: italic } /* Comment */\n",
       "body .err { border: 1px solid #FF0000 } /* Error */\n",
       "body .k { color: #008000; font-weight: bold } /* Keyword */\n",
       "body .o { color: #666666 } /* Operator */\n",
       "body .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       "body .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       "body .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       "body .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       "body .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       "body .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       "body .gd { color: #A00000 } /* Generic.Deleted */\n",
       "body .ge { font-style: italic } /* Generic.Emph */\n",
       "body .gr { color: #FF0000 } /* Generic.Error */\n",
       "body .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       "body .gi { color: #00A000 } /* Generic.Inserted */\n",
       "body .go { color: #888888 } /* Generic.Output */\n",
       "body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       "body .gs { font-weight: bold } /* Generic.Strong */\n",
       "body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       "body .gt { color: #0044DD } /* Generic.Traceback */\n",
       "body .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       "body .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       "body .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       "body .kp { color: #008000 } /* Keyword.Pseudo */\n",
       "body .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       "body .kt { color: #B00040 } /* Keyword.Type */\n",
       "body .m { color: #666666 } /* Literal.Number */\n",
       "body .s { color: #BA2121 } /* Literal.String */\n",
       "body .na { color: #7D9029 } /* Name.Attribute */\n",
       "body .nb { color: #008000 } /* Name.Builtin */\n",
       "body .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       "body .no { color: #880000 } /* Name.Constant */\n",
       "body .nd { color: #AA22FF } /* Name.Decorator */\n",
       "body .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       "body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       "body .nf { color: #0000FF } /* Name.Function */\n",
       "body .nl { color: #A0A000 } /* Name.Label */\n",
       "body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       "body .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       "body .nv { color: #19177C } /* Name.Variable */\n",
       "body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       "body .w { color: #bbbbbb } /* Text.Whitespace */\n",
       "body .mb { color: #666666 } /* Literal.Number.Bin */\n",
       "body .mf { color: #666666 } /* Literal.Number.Float */\n",
       "body .mh { color: #666666 } /* Literal.Number.Hex */\n",
       "body .mi { color: #666666 } /* Literal.Number.Integer */\n",
       "body .mo { color: #666666 } /* Literal.Number.Oct */\n",
       "body .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       "body .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       "body .sc { color: #BA2121 } /* Literal.String.Char */\n",
       "body .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       "body .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       "body .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       "body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       "body .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       "body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       "body .sx { color: #008000 } /* Literal.String.Other */\n",
       "body .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       "body .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       "body .ss { color: #19177C } /* Literal.String.Symbol */\n",
       "body .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       "body .fm { color: #0000FF } /* Name.Function.Magic */\n",
       "body .vc { color: #19177C } /* Name.Variable.Class */\n",
       "body .vg { color: #19177C } /* Name.Variable.Global */\n",
       "body .vi { color: #19177C } /* Name.Variable.Instance */\n",
       "body .vm { color: #19177C } /* Name.Variable.Magic */\n",
       "body .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "\n",
       "  </style>\n",
       "</head>\n",
       "<body>\n",
       "<h2></h2>\n",
       "\n",
       "<div class=\"highlight\"><pre><span></span><span class=\"k\">def</span> <span class=\"nf\">SAT_plan</span><span class=\"p\">(</span><span class=\"n\">init</span><span class=\"p\">,</span> <span class=\"n\">transition</span><span class=\"p\">,</span> <span class=\"n\">goal</span><span class=\"p\">,</span> <span class=\"n\">t_max</span><span class=\"p\">,</span> <span class=\"n\">SAT_solver</span><span class=\"o\">=</span><span class=\"n\">dpll_satisfiable</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Converts a planning problem to Satisfaction problem by translating it to a cnf sentence.</span>\n",
       "<span class=\"sd\">    [Figure 7.22]&quot;&quot;&quot;</span>\n",
       "\n",
       "    <span class=\"c1\"># Functions used by SAT_plan</span>\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">translate_to_SAT</span><span class=\"p\">(</span><span class=\"n\">init</span><span class=\"p\">,</span> <span class=\"n\">transition</span><span class=\"p\">,</span> <span class=\"n\">goal</span><span class=\"p\">,</span> <span class=\"n\">time</span><span class=\"p\">):</span>\n",
       "        <span class=\"n\">clauses</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n",
       "        <span class=\"n\">states</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"n\">state</span> <span class=\"k\">for</span> <span class=\"n\">state</span> <span class=\"ow\">in</span> <span class=\"n\">transition</span><span class=\"p\">]</span>\n",
       "\n",
       "        <span class=\"c1\"># Symbol claiming state s at time t</span>\n",
       "        <span class=\"n\">state_counter</span> <span class=\"o\">=</span> <span class=\"n\">itertools</span><span class=\"o\">.</span><span class=\"n\">count</span><span class=\"p\">()</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">s</span> <span class=\"ow\">in</span> <span class=\"n\">states</span><span class=\"p\">:</span>\n",
       "            <span class=\"k\">for</span> <span class=\"n\">t</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">time</span><span class=\"o\">+</span><span class=\"mi\">1</span><span class=\"p\">):</span>\n",
       "                <span class=\"n\">state_sym</span><span class=\"p\">[</span><span class=\"n\">s</span><span class=\"p\">,</span> <span class=\"n\">t</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">Expr</span><span class=\"p\">(</span><span class=\"s2\">&quot;State_{}&quot;</span><span class=\"o\">.</span><span class=\"n\">format</span><span class=\"p\">(</span><span class=\"nb\">next</span><span class=\"p\">(</span><span class=\"n\">state_counter</span><span class=\"p\">)))</span>\n",
       "\n",
       "        <span class=\"c1\"># Add initial state axiom</span>\n",
       "        <span class=\"n\">clauses</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">state_sym</span><span class=\"p\">[</span><span class=\"n\">init</span><span class=\"p\">,</span> <span class=\"mi\">0</span><span class=\"p\">])</span>\n",
       "\n",
       "        <span class=\"c1\"># Add goal state axiom</span>\n",
       "        <span class=\"n\">clauses</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">state_sym</span><span class=\"p\">[</span><span class=\"n\">goal</span><span class=\"p\">,</span> <span class=\"n\">time</span><span class=\"p\">])</span>\n",
       "\n",
       "        <span class=\"c1\"># All possible transitions</span>\n",
       "        <span class=\"n\">transition_counter</span> <span class=\"o\">=</span> <span class=\"n\">itertools</span><span class=\"o\">.</span><span class=\"n\">count</span><span class=\"p\">()</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">s</span> <span class=\"ow\">in</span> <span class=\"n\">states</span><span class=\"p\">:</span>\n",
       "            <span class=\"k\">for</span> <span class=\"n\">action</span> <span class=\"ow\">in</span> <span class=\"n\">transition</span><span class=\"p\">[</span><span class=\"n\">s</span><span class=\"p\">]:</span>\n",
       "                <span class=\"n\">s_</span> <span class=\"o\">=</span> <span class=\"n\">transition</span><span class=\"p\">[</span><span class=\"n\">s</span><span class=\"p\">][</span><span class=\"n\">action</span><span class=\"p\">]</span>\n",
       "                <span class=\"k\">for</span> <span class=\"n\">t</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">time</span><span class=\"p\">):</span>\n",
       "                    <span class=\"c1\"># Action &#39;action&#39; taken from state &#39;s&#39; at time &#39;t&#39; to reach &#39;s_&#39;</span>\n",
       "                    <span class=\"n\">action_sym</span><span class=\"p\">[</span><span class=\"n\">s</span><span class=\"p\">,</span> <span class=\"n\">action</span><span class=\"p\">,</span> <span class=\"n\">t</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">Expr</span><span class=\"p\">(</span>\n",
       "                        <span class=\"s2\">&quot;Transition_{}&quot;</span><span class=\"o\">.</span><span class=\"n\">format</span><span class=\"p\">(</span><span class=\"nb\">next</span><span class=\"p\">(</span><span class=\"n\">transition_counter</span><span class=\"p\">)))</span>\n",
       "\n",
       "                    <span class=\"c1\"># Change the state from s to s_</span>\n",
       "                    <span class=\"n\">clauses</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">action_sym</span><span class=\"p\">[</span><span class=\"n\">s</span><span class=\"p\">,</span> <span class=\"n\">action</span><span class=\"p\">,</span> <span class=\"n\">t</span><span class=\"p\">]</span> <span class=\"o\">|</span><span class=\"s1\">&#39;==&gt;&#39;</span><span class=\"o\">|</span> <span class=\"n\">state_sym</span><span class=\"p\">[</span><span class=\"n\">s</span><span class=\"p\">,</span> <span class=\"n\">t</span><span class=\"p\">])</span>\n",
       "                    <span class=\"n\">clauses</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">action_sym</span><span class=\"p\">[</span><span class=\"n\">s</span><span class=\"p\">,</span> <span class=\"n\">action</span><span class=\"p\">,</span> <span class=\"n\">t</span><span class=\"p\">]</span> <span class=\"o\">|</span><span class=\"s1\">&#39;==&gt;&#39;</span><span class=\"o\">|</span> <span class=\"n\">state_sym</span><span class=\"p\">[</span><span class=\"n\">s_</span><span class=\"p\">,</span> <span class=\"n\">t</span> <span class=\"o\">+</span> <span class=\"mi\">1</span><span class=\"p\">])</span>\n",
       "\n",
       "        <span class=\"c1\"># Allow only one state at any time</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">t</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">time</span><span class=\"o\">+</span><span class=\"mi\">1</span><span class=\"p\">):</span>\n",
       "            <span class=\"c1\"># must be a state at any time</span>\n",
       "            <span class=\"n\">clauses</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">associate</span><span class=\"p\">(</span><span class=\"s1\">&#39;|&#39;</span><span class=\"p\">,</span> <span class=\"p\">[</span><span class=\"n\">state_sym</span><span class=\"p\">[</span><span class=\"n\">s</span><span class=\"p\">,</span> <span class=\"n\">t</span><span class=\"p\">]</span> <span class=\"k\">for</span> <span class=\"n\">s</span> <span class=\"ow\">in</span> <span class=\"n\">states</span><span class=\"p\">]))</span>\n",
       "\n",
       "            <span class=\"k\">for</span> <span class=\"n\">s</span> <span class=\"ow\">in</span> <span class=\"n\">states</span><span class=\"p\">:</span>\n",
       "                <span class=\"k\">for</span> <span class=\"n\">s_</span> <span class=\"ow\">in</span> <span class=\"n\">states</span><span class=\"p\">[</span><span class=\"n\">states</span><span class=\"o\">.</span><span class=\"n\">index</span><span class=\"p\">(</span><span class=\"n\">s</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"mi\">1</span><span class=\"p\">:]:</span>\n",
       "                    <span class=\"c1\"># for each pair of states s, s_ only one is possible at time t</span>\n",
       "                    <span class=\"n\">clauses</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">((</span><span class=\"o\">~</span><span class=\"n\">state_sym</span><span class=\"p\">[</span><span class=\"n\">s</span><span class=\"p\">,</span> <span class=\"n\">t</span><span class=\"p\">])</span> <span class=\"o\">|</span> <span class=\"p\">(</span><span class=\"o\">~</span><span class=\"n\">state_sym</span><span class=\"p\">[</span><span class=\"n\">s_</span><span class=\"p\">,</span> <span class=\"n\">t</span><span class=\"p\">]))</span>\n",
       "\n",
       "        <span class=\"c1\"># Restrict to one transition per timestep</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">t</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">time</span><span class=\"p\">):</span>\n",
       "            <span class=\"c1\"># list of possible transitions at time t</span>\n",
       "            <span class=\"n\">transitions_t</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"n\">tr</span> <span class=\"k\">for</span> <span class=\"n\">tr</span> <span class=\"ow\">in</span> <span class=\"n\">action_sym</span> <span class=\"k\">if</span> <span class=\"n\">tr</span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"p\">]</span> <span class=\"o\">==</span> <span class=\"n\">t</span><span class=\"p\">]</span>\n",
       "\n",
       "            <span class=\"c1\"># make sure at least one of the transitions happens</span>\n",
       "            <span class=\"n\">clauses</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">associate</span><span class=\"p\">(</span><span class=\"s1\">&#39;|&#39;</span><span class=\"p\">,</span> <span class=\"p\">[</span><span class=\"n\">action_sym</span><span class=\"p\">[</span><span class=\"n\">tr</span><span class=\"p\">]</span> <span class=\"k\">for</span> <span class=\"n\">tr</span> <span class=\"ow\">in</span> <span class=\"n\">transitions_t</span><span class=\"p\">]))</span>\n",
       "\n",
       "            <span class=\"k\">for</span> <span class=\"n\">tr</span> <span class=\"ow\">in</span> <span class=\"n\">transitions_t</span><span class=\"p\">:</span>\n",
       "                <span class=\"k\">for</span> <span class=\"n\">tr_</span> <span class=\"ow\">in</span> <span class=\"n\">transitions_t</span><span class=\"p\">[</span><span class=\"n\">transitions_t</span><span class=\"o\">.</span><span class=\"n\">index</span><span class=\"p\">(</span><span class=\"n\">tr</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"mi\">1</span><span class=\"p\">:]:</span>\n",
       "                    <span class=\"c1\"># there cannot be two transitions tr and tr_ at time t</span>\n",
       "                    <span class=\"n\">clauses</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"o\">~</span><span class=\"n\">action_sym</span><span class=\"p\">[</span><span class=\"n\">tr</span><span class=\"p\">]</span> <span class=\"o\">|</span> <span class=\"o\">~</span><span class=\"n\">action_sym</span><span class=\"p\">[</span><span class=\"n\">tr_</span><span class=\"p\">])</span>\n",
       "\n",
       "        <span class=\"c1\"># Combine the clauses to form the cnf</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">associate</span><span class=\"p\">(</span><span class=\"s1\">&#39;&amp;&#39;</span><span class=\"p\">,</span> <span class=\"n\">clauses</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">extract_solution</span><span class=\"p\">(</span><span class=\"n\">model</span><span class=\"p\">):</span>\n",
       "        <span class=\"n\">true_transitions</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"n\">t</span> <span class=\"k\">for</span> <span class=\"n\">t</span> <span class=\"ow\">in</span> <span class=\"n\">action_sym</span> <span class=\"k\">if</span> <span class=\"n\">model</span><span class=\"p\">[</span><span class=\"n\">action_sym</span><span class=\"p\">[</span><span class=\"n\">t</span><span class=\"p\">]]]</span>\n",
       "        <span class=\"c1\"># Sort transitions based on time, which is the 3rd element of the tuple</span>\n",
       "        <span class=\"n\">true_transitions</span><span class=\"o\">.</span><span class=\"n\">sort</span><span class=\"p\">(</span><span class=\"n\">key</span><span class=\"o\">=</span><span class=\"k\">lambda</span> <span class=\"n\">x</span><span class=\"p\">:</span> <span class=\"n\">x</span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"p\">])</span>\n",
       "        <span class=\"k\">return</span> <span class=\"p\">[</span><span class=\"n\">action</span> <span class=\"k\">for</span> <span class=\"n\">s</span><span class=\"p\">,</span> <span class=\"n\">action</span><span class=\"p\">,</span> <span class=\"n\">time</span> <span class=\"ow\">in</span> <span class=\"n\">true_transitions</span><span class=\"p\">]</span>\n",
       "\n",
       "    <span class=\"c1\"># Body of SAT_plan algorithm</span>\n",
       "    <span class=\"k\">for</span> <span class=\"n\">t</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">t_max</span><span class=\"p\">):</span>\n",
       "        <span class=\"c1\"># dictionaries to help extract the solution from model</span>\n",
       "        <span class=\"n\">state_sym</span> <span class=\"o\">=</span> <span class=\"p\">{}</span>\n",
       "        <span class=\"n\">action_sym</span> <span class=\"o\">=</span> <span class=\"p\">{}</span>\n",
       "\n",
       "        <span class=\"n\">cnf</span> <span class=\"o\">=</span> <span class=\"n\">translate_to_SAT</span><span class=\"p\">(</span><span class=\"n\">init</span><span class=\"p\">,</span> <span class=\"n\">transition</span><span class=\"p\">,</span> <span class=\"n\">goal</span><span class=\"p\">,</span> <span class=\"n\">t</span><span class=\"p\">)</span>\n",
       "        <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">SAT_solver</span><span class=\"p\">(</span><span class=\"n\">cnf</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">if</span> <span class=\"n\">model</span> <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"bp\">False</span><span class=\"p\">:</span>\n",
       "            <span class=\"k\">return</span> <span class=\"n\">extract_solution</span><span class=\"p\">(</span><span class=\"n\">model</span><span class=\"p\">)</span>\n",
       "    <span class=\"k\">return</span> <span class=\"bp\">None</span>\n",
       "</pre></div>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "psource(SAT_plan)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's see few examples of its usage. First we define a transition and then call `SAT_plan`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [