{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# CONSTRAINT SATISFACTION PROBLEMS\n",
    "\n",
    "This IPy notebook acts as supporting material for topics covered in **Chapter 6 Constraint Satisfaction Problems** of the book* Artificial Intelligence: A Modern Approach*. We make use of the implementations in **csp.py** module. Even though this notebook includes a brief summary of the main topics, familiarity with the material present in the book is expected. We will look at some visualizations and solve some of the CSP problems described in the book. Let us import everything from the csp module to get started."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from csp import *\n",
    "from notebook import psource, pseudocode, plot_NQueens\n",
    "%matplotlib inline\n",
    "\n",
    "# Hide warnings in the matplotlib sections\n",
    "import warnings\n",
    "warnings.filterwarnings(\"ignore\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## CONTENTS\n",
    "\n",
    "* Overview\n",
    "* Graph Coloring\n",
    "* N-Queens\n",
    "* AC-3\n",
    "* Backtracking Search\n",
    "* Tree CSP Solver\n",
    "* Graph Coloring Visualization\n",
    "* N-Queens Visualization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## OVERVIEW\n",
    "\n",
    "CSPs are a special kind of search problems. Here we don't treat the space as a black box but the state has a particular form and we use that to our advantage to tweak our algorithms to be more suited to the problems. A CSP State is defined by a set of variables which can take values from corresponding domains. These variables can take only certain values in their domains to satisfy the constraints. A set of assignments which satisfies all constraints passes the goal test. Let us start by exploring the CSP class which we will use to model our CSPs. You can keep the popup open and read the main page to get a better idea of the code."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "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\">class</span> <span class=\"nc\">CSP</span><span class=\"p\">(</span><span class=\"n\">search</span><span class=\"o\">.</span><span class=\"n\">Problem</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;This class describes finite-domain Constraint Satisfaction Problems.</span>\n",
       "<span class=\"sd\">    A CSP is specified by the following inputs:</span>\n",
       "<span class=\"sd\">        variables   A list of variables; each is atomic (e.g. int or string).</span>\n",
       "<span class=\"sd\">        domains     A dict of {var:[possible_value, ...]} entries.</span>\n",
       "<span class=\"sd\">        neighbors   A dict of {var:[var,...]} that for each variable lists</span>\n",
       "<span class=\"sd\">                    the other variables that participate in constraints.</span>\n",
       "<span class=\"sd\">        constraints A function f(A, a, B, b) that returns true if neighbors</span>\n",
       "<span class=\"sd\">                    A, B satisfy the constraint when they have values A=a, B=b</span>\n",
       "\n",
       "<span class=\"sd\">    In the textbook and in most mathematical definitions, the</span>\n",
       "<span class=\"sd\">    constraints are specified as explicit pairs of allowable values,</span>\n",
       "<span class=\"sd\">    but the formulation here is easier to express and more compact for</span>\n",
       "<span class=\"sd\">    most cases. (For example, the n-Queens problem can be represented</span>\n",
       "<span class=\"sd\">    in O(n) space using this notation, instead of O(N^4) for the</span>\n",
       "<span class=\"sd\">    explicit representation.) In terms of describing the CSP as a</span>\n",
       "<span class=\"sd\">    problem, that&#39;s all there is.</span>\n",
       "\n",
       "<span class=\"sd\">    However, the class also supports data structures and methods that help you</span>\n",
       "<span class=\"sd\">    solve CSPs by calling a search function on the CSP. Methods and slots are</span>\n",
       "<span class=\"sd\">    as follows, where the argument &#39;a&#39; represents an assignment, which is a</span>\n",
       "<span class=\"sd\">    dict of {var:val} entries:</span>\n",
       "<span class=\"sd\">        assign(var, val, a)     Assign a[var] = val; do other bookkeeping</span>\n",
       "<span class=\"sd\">        unassign(var, a)        Do del a[var], plus other bookkeeping</span>\n",
       "<span class=\"sd\">        nconflicts(var, val, a) Return the number of other variables that</span>\n",
       "<span class=\"sd\">                                conflict with var=val</span>\n",
       "<span class=\"sd\">        curr_domains[var]       Slot: remaining consistent values for var</span>\n",
       "<span class=\"sd\">                                Used by constraint propagation routines.</span>\n",
       "<span class=\"sd\">    The following methods are used only by graph_search and tree_search:</span>\n",
       "<span class=\"sd\">        actions(state)          Return a list of actions</span>\n",
       "<span class=\"sd\">        result(state, action)   Return a successor of state</span>\n",
       "<span class=\"sd\">        goal_test(state)        Return true if all constraints satisfied</span>\n",
       "<span class=\"sd\">    The following are just for debugging purposes:</span>\n",
       "<span class=\"sd\">        nassigns                Slot: tracks the number of assignments made</span>\n",
       "<span class=\"sd\">        display(a)              Print a human-readable representation</span>\n",
       "<span class=\"sd\">    &quot;&quot;&quot;</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">variables</span><span class=\"p\">,</span> <span class=\"n\">domains</span><span class=\"p\">,</span> <span class=\"n\">neighbors</span><span class=\"p\">,</span> <span class=\"n\">constraints</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Construct a CSP problem. If variables is empty, it becomes domains.keys().&quot;&quot;&quot;</span>\n",
       "        <span class=\"n\">variables</span> <span class=\"o\">=</span> <span class=\"n\">variables</span> <span class=\"ow\">or</span> <span class=\"nb\">list</span><span class=\"p\">(</span><span class=\"n\">domains</span><span class=\"o\">.</span><span class=\"n\">keys</span><span class=\"p\">())</span>\n",
       "\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">variables</span> <span class=\"o\">=</span> <span class=\"n\">variables</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">domains</span> <span class=\"o\">=</span> <span class=\"n\">domains</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">neighbors</span> <span class=\"o\">=</span> <span class=\"n\">neighbors</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">constraints</span> <span class=\"o\">=</span> <span class=\"n\">constraints</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">initial</span> <span class=\"o\">=</span> <span class=\"p\">()</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">curr_domains</span> <span class=\"o\">=</span> <span class=\"bp\">None</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">nassigns</span> <span class=\"o\">=</span> <span class=\"mi\">0</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">assign</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Add {var: val} to assignment; Discard the old value if any.&quot;&quot;&quot;</span>\n",
       "        <span class=\"n\">assignment</span><span class=\"p\">[</span><span class=\"n\">var</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">val</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">nassigns</span> <span class=\"o\">+=</span> <span class=\"mi\">1</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">unassign</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Remove {var: val} from assignment.</span>\n",
       "<span class=\"sd\">        DO NOT call this if you are changing a variable to a new value;</span>\n",
       "<span class=\"sd\">        just call assign for that.&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">if</span> <span class=\"n\">var</span> <span class=\"ow\">in</span> <span class=\"n\">assignment</span><span class=\"p\">:</span>\n",
       "            <span class=\"k\">del</span> <span class=\"n\">assignment</span><span class=\"p\">[</span><span class=\"n\">var</span><span class=\"p\">]</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">nconflicts</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Return the number of conflicts var=val has with other variables.&quot;&quot;&quot;</span>\n",
       "        <span class=\"c1\"># Subclasses may implement this more efficiently</span>\n",
       "        <span class=\"k\">def</span> <span class=\"nf\">conflict</span><span class=\"p\">(</span><span class=\"n\">var2</span><span class=\"p\">):</span>\n",
       "            <span class=\"k\">return</span> <span class=\"p\">(</span><span class=\"n\">var2</span> <span class=\"ow\">in</span> <span class=\"n\">assignment</span> <span class=\"ow\">and</span>\n",
       "                    <span class=\"ow\">not</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">constraints</span><span class=\"p\">(</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">,</span> <span class=\"n\">var2</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">[</span><span class=\"n\">var2</span><span class=\"p\">]))</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">count</span><span class=\"p\">(</span><span class=\"n\">conflict</span><span class=\"p\">(</span><span class=\"n\">v</span><span class=\"p\">)</span> <span class=\"k\">for</span> <span class=\"n\">v</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">neighbors</span><span class=\"p\">[</span><span class=\"n\">var</span><span class=\"p\">])</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">display</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Show a human-readable representation of the CSP.&quot;&quot;&quot;</span>\n",
       "        <span class=\"c1\"># Subclasses can print in a prettier way, or display with a GUI</span>\n",
       "        <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">&#39;CSP:&#39;</span><span class=\"p\">,</span> <span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"s1\">&#39;with assignment:&#39;</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"c1\"># These methods are for the tree and graph-search interface:</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">actions</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">state</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Return a list of applicable actions: nonconflicting</span>\n",
       "<span class=\"sd\">        assignments to an unassigned variable.&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">if</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">state</span><span class=\"p\">)</span> <span class=\"o\">==</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">variables</span><span class=\"p\">):</span>\n",
       "            <span class=\"k\">return</span> <span class=\"p\">[]</span>\n",
       "        <span class=\"k\">else</span><span class=\"p\">:</span>\n",
       "            <span class=\"n\">assignment</span> <span class=\"o\">=</span> <span class=\"nb\">dict</span><span class=\"p\">(</span><span class=\"n\">state</span><span class=\"p\">)</span>\n",
       "            <span class=\"n\">var</span> <span class=\"o\">=</span> <span class=\"n\">first</span><span class=\"p\">([</span><span class=\"n\">v</span> <span class=\"k\">for</span> <span class=\"n\">v</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">variables</span> <span class=\"k\">if</span> <span class=\"n\">v</span> <span class=\"ow\">not</span> <span class=\"ow\">in</span> <span class=\"n\">assignment</span><span class=\"p\">])</span>\n",
       "            <span class=\"k\">return</span> <span class=\"p\">[(</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">)</span> <span class=\"k\">for</span> <span class=\"n\">val</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">domains</span><span class=\"p\">[</span><span class=\"n\">var</span><span class=\"p\">]</span>\n",
       "                    <span class=\"k\">if</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">nconflicts</span><span class=\"p\">(</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">)</span> <span class=\"o\">==</span> <span class=\"mi\">0</span><span class=\"p\">]</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">result</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">state</span><span class=\"p\">,</span> <span class=\"n\">action</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Perform an action and return the new state.&quot;&quot;&quot;</span>\n",
       "        <span class=\"p\">(</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">)</span> <span class=\"o\">=</span> <span class=\"n\">action</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">state</span> <span class=\"o\">+</span> <span class=\"p\">((</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">),)</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">goal_test</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">state</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;The goal is to assign all variables, with all constraints satisfied.&quot;&quot;&quot;</span>\n",
       "        <span class=\"n\">assignment</span> <span class=\"o\">=</span> <span class=\"nb\">dict</span><span class=\"p\">(</span><span class=\"n\">state</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">return</span> <span class=\"p\">(</span><span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">assignment</span><span class=\"p\">)</span> <span class=\"o\">==</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">variables</span><span class=\"p\">)</span>\n",
       "                <span class=\"ow\">and</span> <span class=\"nb\">all</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">nconflicts</span><span class=\"p\">(</span><span class=\"n\">variables</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">[</span><span class=\"n\">variables</span><span class=\"p\">],</span> <span class=\"n\">assignment</span><span class=\"p\">)</span> <span class=\"o\">==</span> <span class=\"mi\">0</span>\n",
       "                        <span class=\"k\">for</span> <span class=\"n\">variables</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">variables</span><span class=\"p\">))</span>\n",
       "\n",
       "    <span class=\"c1\"># These are for constraint propagation</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">support_pruning</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Make sure we can prune values from domains. (We want to pay</span>\n",
       "<span class=\"sd\">        for this only if we use it.)&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">if</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">curr_domains</span> <span class=\"ow\">is</span> <span class=\"bp\">None</span><span class=\"p\">:</span>\n",
       "            <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">curr_domains</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"n\">v</span><span class=\"p\">:</span> <span class=\"nb\">list</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">domains</span><span class=\"p\">[</span><span class=\"n\">v</span><span class=\"p\">])</span> <span class=\"k\">for</span> <span class=\"n\">v</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">variables</span><span class=\"p\">}</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">suppose</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">value</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Start accumulating inferences from assuming var=value.&quot;&quot;&quot;</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">support_pruning</span><span class=\"p\">()</span>\n",
       "        <span class=\"n\">removals</span> <span class=\"o\">=</span> <span class=\"p\">[(</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">a</span><span class=\"p\">)</span> <span class=\"k\">for</span> <span class=\"n\">a</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">curr_domains</span><span class=\"p\">[</span><span class=\"n\">var</span><span class=\"p\">]</span> <span class=\"k\">if</span> <span class=\"n\">a</span> <span class=\"o\">!=</span> <span class=\"n\">value</span><span class=\"p\">]</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">curr_domains</span><span class=\"p\">[</span><span class=\"n\">var</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"n\">value</span><span class=\"p\">]</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">removals</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">prune</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">value</span><span class=\"p\">,</span> <span class=\"n\">removals</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Rule out var=value.&quot;&quot;&quot;</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">curr_domains</span><span class=\"p\">[</span><span class=\"n\">var</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">remove</span><span class=\"p\">(</span><span class=\"n\">value</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">if</span> <span class=\"n\">removals</span> <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"bp\">None</span><span class=\"p\">:</span>\n",
       "            <span class=\"n\">removals</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">((</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">value</span><span class=\"p\">))</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">choices</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Return all values for var that aren&#39;t currently ruled out.&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">return</span> <span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">curr_domains</span> <span class=\"ow\">or</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">domains</span><span class=\"p\">)[</span><span class=\"n\">var</span><span class=\"p\">]</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">infer_assignment</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Return the partial assignment implied by the current inferences.&quot;&quot;&quot;</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">support_pruning</span><span class=\"p\">()</span>\n",
       "        <span class=\"k\">return</span> <span class=\"p\">{</span><span class=\"n\">v</span><span class=\"p\">:</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">curr_domains</span><span class=\"p\">[</span><span class=\"n\">v</span><span class=\"p\">][</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n",
       "                <span class=\"k\">for</span> <span class=\"n\">v</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">variables</span> <span class=\"k\">if</span> <span class=\"mi\">1</span> <span class=\"o\">==</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">curr_domains</span><span class=\"p\">[</span><span class=\"n\">v</span><span class=\"p\">])}</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">restore</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">removals</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Undo a supposition and all inferences from it.&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">B</span><span class=\"p\">,</span> <span class=\"n\">b</span> <span class=\"ow\">in</span> <span class=\"n\">removals</span><span class=\"p\">:</span>\n",
       "            <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">curr_domains</span><span class=\"p\">[</span><span class=\"n\">B</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">b</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"c1\"># This is for min_conflicts search</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">conflicted_vars</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">current</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Return a list of variables in current assignment that are in conflict&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">return</span> <span class=\"p\">[</span><span class=\"n\">var</span> <span class=\"k\">for</span> <span class=\"n\">var</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">variables</span>\n",
       "                <span class=\"k\">if</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">nconflicts</span><span class=\"p\">(</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">current</span><span class=\"p\">[</span><span class=\"n\">var</span><span class=\"p\">],</span> <span class=\"n\">current</span><span class=\"p\">)</span> <span class=\"o\">&gt;</span> <span class=\"mi\">0</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(CSP)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The __ _ _init_ _ __ method parameters specify the CSP. Variable can be passed as a list of strings or integers. Domains are passed as dict where key specify the variables and value specify the domains. The variables are passed as an empty list. Variables are extracted from the keys of the domain dictionary. Neighbor is a dict of variables that essentially describes the constraint graph. Here each variable key has a list its value which are the variables that are constraint along with it. The constraint parameter should be a function **f(A, a, B, b**) that **returns true** if neighbors A, B **satisfy the constraint** when they have values **A=a, B=b**. We have additional parameters like nassings which is incremented each time an assignment is made when calling the assign method. You can read more about the methods and parameters in the class doc string. We will talk more about them as we encounter their use. Let us jump to an example."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## GRAPH COLORING\n",
    "\n",
    "We use the graph coloring problem as our running example for demonstrating the different algorithms in the **csp module**. The idea of map coloring problem is that the adjacent nodes (those connected by edges) should not have the same color throughout the graph. The graph can be colored using a fixed number of colors. Here each node is a variable and the values are the colors that can be assigned to them. Given that the domain will be the same for all our nodes we use a custom dict defined by the **UniversalDict** class. The **UniversalDict** Class takes in a parameter which it returns as value for all the keys of the dict. It is very similar to **defaultdict** in Python except that it does not support item assignment."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['R', 'G', 'B']"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = UniversalDict(['R','G','B'])\n",
    "s[5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For our CSP we also need to define a constraint function **f(A, a, B, b)**. In this what we need is that the neighbors must not have the same color. This is defined in the function **different_values_constraint** of the module."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "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\">different_values_constraint</span><span class=\"p\">(</span><span class=\"n\">A</span><span class=\"p\">,</span> <span class=\"n\">a</span><span class=\"p\">,</span> <span class=\"n\">B</span><span class=\"p\">,</span> <span class=\"n\">b</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;A constraint saying two neighboring variables must differ in value.&quot;&quot;&quot;</span>\n",
       "    <span class=\"k\">return</span> <span class=\"n\">a</span> <span class=\"o\">!=</span> <span class=\"n\">b</span>\n",
       "</pre></div>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "psource(different_values_constraint)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The CSP class takes neighbors in the form of a Dict. The module specifies a simple helper function named **parse_neighbors** which allows us to take input in the form of strings and return a Dict of a form compatible with the **CSP Class**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "%pdoc parse_neighbors"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The **MapColoringCSP** function creates and returns a CSP with the above constraint function and states. The variables are the keys of the neighbors dict and the constraint is the one specified by the **different_values_constratint** function. **australia**, **usa** and **france** are three CSPs that have been created using **MapColoringCSP**. **australia** corresponds to ** Figure 6.1 ** in the book."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "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\">MapColoringCSP</span><span class=\"p\">(</span><span class=\"n\">colors</span><span class=\"p\">,</span> <span class=\"n\">neighbors</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Make a CSP for the problem of coloring a map with different colors</span>\n",
       "<span class=\"sd\">    for any two adjacent regions. Arguments are a list of colors, and a</span>\n",
       "<span class=\"sd\">    dict of {region: [neighbor,...]} entries. This dict may also be</span>\n",
       "<span class=\"sd\">    specified as a string of the form defined by parse_neighbors.&quot;&quot;&quot;</span>\n",
       "    <span class=\"k\">if</span> <span class=\"nb\">isinstance</span><span class=\"p\">(</span><span class=\"n\">neighbors</span><span class=\"p\">,</span> <span class=\"nb\">str</span><span class=\"p\">):</span>\n",
       "        <span class=\"n\">neighbors</span> <span class=\"o\">=</span> <span class=\"n\">parse_neighbors</span><span class=\"p\">(</span><span class=\"n\">neighbors</span><span class=\"p\">)</span>\n",
       "    <span class=\"k\">return</span> <span class=\"n\">CSP</span><span class=\"p\">(</span><span class=\"nb\">list</span><span class=\"p\">(</span><span class=\"n\">neighbors</span><span class=\"o\">.</span><span class=\"n\">keys</span><span class=\"p\">()),</span> <span class=\"n\">UniversalDict</span><span class=\"p\">(</span><span class=\"n\">colors</span><span class=\"p\">),</span> <span class=\"n\">neighbors</span><span class=\"p\">,</span>\n",
       "               <span class=\"n\">different_values_constraint</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(MapColoringCSP)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(<csp.CSP at 0x25ddb16ebe0>,\n",
       " <csp.CSP at 0x25ddb193518>,\n",
       " <csp.CSP at 0x25ddb193630>)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "australia, usa, france"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## N-QUEENS\n",
    "\n",
    "The N-queens puzzle is the problem of placing N chess queens on an N×N chessboard so that no two queens threaten each other. Here N is a natural number. Like the graph coloring problem, NQueens is also implemented in the csp module. The **NQueensCSP** class inherits from the **CSP** class. It makes some modifications in the methods to suit the particular problem. The queens are assumed to be placed one per column, from left to right. That means position (x, y) represents (var, val) in the CSP. The constraint that needs to be passed on the CSP is defined in the **queen_constraint** function. The constraint is satisfied (true) if A, B are really the same variable, or if they are not in the same row, down diagonal, or up diagonal. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "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\">queen_constraint</span><span class=\"p\">(</span><span class=\"n\">A</span><span class=\"p\">,</span> <span class=\"n\">a</span><span class=\"p\">,</span> <span class=\"n\">B</span><span class=\"p\">,</span> <span class=\"n\">b</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Constraint is satisfied (true) if A, B are really the same variable,</span>\n",
       "<span class=\"sd\">    or if they are not in the same row, down diagonal, or up diagonal.&quot;&quot;&quot;</span>\n",
       "    <span class=\"k\">return</span> <span class=\"n\">A</span> <span class=\"o\">==</span> <span class=\"n\">B</span> <span class=\"ow\">or</span> <span class=\"p\">(</span><span class=\"n\">a</span> <span class=\"o\">!=</span> <span class=\"n\">b</span> <span class=\"ow\">and</span> <span class=\"n\">A</span> <span class=\"o\">+</span> <span class=\"n\">a</span> <span class=\"o\">!=</span> <span class=\"n\">B</span> <span class=\"o\">+</span> <span class=\"n\">b</span> <span class=\"ow\">and</span> <span class=\"n\">A</span> <span class=\"o\">-</span> <span class=\"n\">a</span> <span class=\"o\">!=</span> <span class=\"n\">B</span> <span class=\"o\">-</span> <span class=\"n\">b</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(queen_constraint)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The **NQueensCSP** method implements methods that support solving the problem via **min_conflicts** which is one of the techniques for solving CSPs. Because **min_conflicts** hill climbs the number of conflicts to solve, the CSP **assign** and **unassign** are modified to record conflicts. More details about the structures **rows**, **downs**, **ups** which help in recording conflicts are explained in the docstring."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "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\">class</span> <span class=\"nc\">NQueensCSP</span><span class=\"p\">(</span><span class=\"n\">CSP</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Make a CSP for the nQueens problem for search with min_conflicts.</span>\n",
       "<span class=\"sd\">    Suitable for large n, it uses only data structures of size O(n).</span>\n",
       "<span class=\"sd\">    Think of placing queens one per column, from left to right.</span>\n",
       "<span class=\"sd\">    That means position (x, y) represents (var, val) in the CSP.</span>\n",
       "<span class=\"sd\">    The main structures are three arrays to count queens that could conflict:</span>\n",
       "<span class=\"sd\">        rows[i]      Number of queens in the ith row (i.e val == i)</span>\n",
       "<span class=\"sd\">        downs[i]     Number of queens in the \\ diagonal</span>\n",
       "<span class=\"sd\">                     such that their (x, y) coordinates sum to i</span>\n",
       "<span class=\"sd\">        ups[i]       Number of queens in the / diagonal</span>\n",
       "<span class=\"sd\">                     such that their (x, y) coordinates have x-y+n-1 = i</span>\n",
       "<span class=\"sd\">    We increment/decrement these counts each time a queen is placed/moved from</span>\n",
       "<span class=\"sd\">    a row/diagonal. So moving is O(1), as is nconflicts.  But choosing</span>\n",
       "<span class=\"sd\">    a variable, and a best value for the variable, are each O(n).</span>\n",
       "<span class=\"sd\">    If you want, you can keep track of conflicted variables, then variable</span>\n",
       "<span class=\"sd\">    selection will also be O(1).</span>\n",
       "<span class=\"sd\">    &gt;&gt;&gt; len(backtracking_search(NQueensCSP(8)))</span>\n",
       "<span class=\"sd\">    8</span>\n",
       "<span class=\"sd\">    &quot;&quot;&quot;</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">n</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Initialize data structures for n Queens.&quot;&quot;&quot;</span>\n",
       "        <span class=\"n\">CSP</span><span class=\"o\">.</span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"nb\">list</span><span class=\"p\">(</span><span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"p\">)),</span> <span class=\"n\">UniversalDict</span><span class=\"p\">(</span><span class=\"nb\">list</span><span class=\"p\">(</span><span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"p\">))),</span>\n",
       "                     <span class=\"n\">UniversalDict</span><span class=\"p\">(</span><span class=\"nb\">list</span><span class=\"p\">(</span><span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"p\">))),</span> <span class=\"n\">queen_constraint</span><span class=\"p\">)</span>\n",
       "\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">rows</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span><span class=\"o\">*</span><span class=\"n\">n</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">ups</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span><span class=\"o\">*</span><span class=\"p\">(</span><span class=\"mi\">2</span><span class=\"o\">*</span><span class=\"n\">n</span> <span class=\"o\">-</span> <span class=\"mi\">1</span><span class=\"p\">)</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">downs</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span><span class=\"o\">*</span><span class=\"p\">(</span><span class=\"mi\">2</span><span class=\"o\">*</span><span class=\"n\">n</span> <span class=\"o\">-</span> <span class=\"mi\">1</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">nconflicts</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;The number of conflicts, as recorded with each assignment.</span>\n",
       "<span class=\"sd\">        Count conflicts in row and in up, down diagonals. If there</span>\n",
       "<span class=\"sd\">        is a queen there, it can&#39;t conflict with itself, so subtract 3.&quot;&quot;&quot;</span>\n",
       "        <span class=\"n\">n</span> <span class=\"o\">=</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">variables</span><span class=\"p\">)</span>\n",
       "        <span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">rows</span><span class=\"p\">[</span><span class=\"n\">val</span><span class=\"p\">]</span> <span class=\"o\">+</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">downs</span><span class=\"p\">[</span><span class=\"n\">var</span><span class=\"o\">+</span><span class=\"n\">val</span><span class=\"p\">]</span> <span class=\"o\">+</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">ups</span><span class=\"p\">[</span><span class=\"n\">var</span><span class=\"o\">-</span><span class=\"n\">val</span><span class=\"o\">+</span><span class=\"n\">n</span><span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">]</span>\n",
       "        <span class=\"k\">if</span> <span class=\"n\">assignment</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"bp\">None</span><span class=\"p\">)</span> <span class=\"o\">==</span> <span class=\"n\">val</span><span class=\"p\">:</span>\n",
       "            <span class=\"n\">c</span> <span class=\"o\">-=</span> <span class=\"mi\">3</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">c</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">assign</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Assign var, and keep track of conflicts.&quot;&quot;&quot;</span>\n",
       "        <span class=\"n\">oldval</span> <span class=\"o\">=</span> <span class=\"n\">assignment</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"bp\">None</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">if</span> <span class=\"n\">val</span> <span class=\"o\">!=</span> <span class=\"n\">oldval</span><span class=\"p\">:</span>\n",
       "            <span class=\"k\">if</span> <span class=\"n\">oldval</span> <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"bp\">None</span><span class=\"p\">:</span>  <span class=\"c1\"># Remove old val if there was one</span>\n",
       "                <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">record_conflict</span><span class=\"p\">(</span><span class=\"n\">assignment</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">oldval</span><span class=\"p\">,</span> <span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n",
       "            <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">record_conflict</span><span class=\"p\">(</span><span class=\"n\">assignment</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">,</span> <span class=\"o\">+</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n",
       "            <span class=\"n\">CSP</span><span class=\"o\">.</span><span class=\"n\">assign</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">unassign</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Remove var from assignment (if it is there) and track conflicts.&quot;&quot;&quot;</span>\n",
       "        <span class=\"k\">if</span> <span class=\"n\">var</span> <span class=\"ow\">in</span> <span class=\"n\">assignment</span><span class=\"p\">:</span>\n",
       "            <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">record_conflict</span><span class=\"p\">(</span><span class=\"n\">assignment</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">[</span><span class=\"n\">var</span><span class=\"p\">],</span> <span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n",
       "        <span class=\"n\">CSP</span><span class=\"o\">.</span><span class=\"n\">unassign</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">record_conflict</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">,</span> <span class=\"n\">delta</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Record conflicts caused by addition or deletion of a Queen.&quot;&quot;&quot;</span>\n",
       "        <span class=\"n\">n</span> <span class=\"o\">=</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">variables</span><span class=\"p\">)</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">rows</span><span class=\"p\">[</span><span class=\"n\">val</span><span class=\"p\">]</span> <span class=\"o\">+=</span> <span class=\"n\">delta</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">downs</span><span class=\"p\">[</span><span class=\"n\">var</span> <span class=\"o\">+</span> <span class=\"n\">val</span><span class=\"p\">]</span> <span class=\"o\">+=</span> <span class=\"n\">delta</span>\n",
       "        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">ups</span><span class=\"p\">[</span><span class=\"n\">var</span> <span class=\"o\">-</span> <span class=\"n\">val</span> <span class=\"o\">+</span> <span class=\"n\">n</span> <span class=\"o\">-</span> <span class=\"mi\">1</span><span class=\"p\">]</span> <span class=\"o\">+=</span> <span class=\"n\">delta</span>\n",
       "\n",
       "    <span class=\"k\">def</span> <span class=\"nf\">display</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Print the queens and the nconflicts values (for debugging).&quot;&quot;&quot;</span>\n",
       "        <span class=\"n\">n</span> <span class=\"o\">=</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">variables</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">for</span> <span class=\"n\">val</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"p\">):</span>\n",
       "            <span class=\"k\">for</span> <span class=\"n\">var</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"p\">):</span>\n",
       "                <span class=\"k\">if</span> <span class=\"n\">assignment</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"s1\">&#39;&#39;</span><span class=\"p\">)</span> <span class=\"o\">==</span> <span class=\"n\">val</span><span class=\"p\">:</span>\n",
       "                    <span class=\"n\">ch</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;Q&#39;</span>\n",
       "                <span class=\"k\">elif</span> <span class=\"p\">(</span><span class=\"n\">var</span> <span class=\"o\">+</span> <span class=\"n\">val</span><span class=\"p\">)</span> <span class=\"o\">%</span> <span class=\"mi\">2</span> <span class=\"o\">==</span> <span class=\"mi\">0</span><span class=\"p\">:</span>\n",
       "                    <span class=\"n\">ch</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;.&#39;</span>\n",
       "                <span class=\"k\">else</span><span class=\"p\">:</span>\n",
       "                    <span class=\"n\">ch</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;-&#39;</span>\n",
       "                <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">ch</span><span class=\"p\">,</span> <span class=\"n\">end</span><span class=\"o\">=</span><span class=\"s1\">&#39; &#39;</span><span class=\"p\">)</span>\n",
       "            <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">&#39;    &#39;</span><span class=\"p\">,</span> <span class=\"n\">end</span><span class=\"o\">=</span><span class=\"s1\">&#39; &#39;</span><span class=\"p\">)</span>\n",
       "            <span class=\"k\">for</span> <span class=\"n\">var</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"p\">):</span>\n",
       "                <span class=\"k\">if</span> <span class=\"n\">assignment</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"s1\">&#39;&#39;</span><span class=\"p\">)</span> <span class=\"o\">==</span> <span class=\"n\">val</span><span class=\"p\">:</span>\n",
       "                    <span class=\"n\">ch</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;*&#39;</span>\n",
       "                <span class=\"k\">else</span><span class=\"p\">:</span>\n",
       "                    <span class=\"n\">ch</span> <span class=\"o\">=</span> <span class=\"s1\">&#39; &#39;</span>\n",
       "                <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"nb\">str</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">nconflicts</span><span class=\"p\">(</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">))</span> <span class=\"o\">+</span> <span class=\"n\">ch</span><span class=\"p\">,</span> <span class=\"n\">end</span><span class=\"o\">=</span><span class=\"s1\">&#39; &#39;</span><span class=\"p\">)</span>\n",
       "            <span class=\"k\">print</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(NQueensCSP)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The _ ___init___ _ method takes only one parameter **n** the size of the problem. To create an instance we just pass the required n into the constructor."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "eight_queens = NQueensCSP(8)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We have defined our CSP. \n",
    "We now need to solve this.\n",
    "\n",
    "### Min-conflicts\n",
    "As stated above, the `min_conflicts` algorithm is an efficient method to solve such a problem.\n",
    "<br>\n",
    "To begin with, all the variables of the CSP are _randomly_ initialized. \n",
    "<br>\n",
    "The algorithm then randomly selects a variable that has conflicts and violates some constraints of the CSP.\n",
    "<br>\n",
    "The selected variable is then assigned a value that _minimizes_ the number of conflicts.\n",
    "<br>\n",
    "This is a simple stochastic algorithm which works on a principle similar to **Hill-climbing**.\n",
    "The conflicting state is repeatedly changed into a state with fewer conflicts in an attempt to reach an approximate solution.\n",
    "<br>\n",
    "This algorithm sometimes benefits from having a good initial assignment.\n",
    "Using greedy techniques to get a good initial assignment and then using `min_conflicts` to solve the CSP can speed up the procedure dramatically, especially for CSPs with a large state space."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "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\">min_conflicts</span><span class=\"p\">(</span><span class=\"n\">csp</span><span class=\"p\">,</span> <span class=\"n\">max_steps</span><span class=\"o\">=</span><span class=\"mi\">100000</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Solve a CSP by stochastic hillclimbing on the number of conflicts.&quot;&quot;&quot;</span>\n",
       "    <span class=\"c1\"># Generate a complete assignment for all variables (probably with conflicts)</span>\n",
       "    <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">current</span> <span class=\"o\">=</span> <span class=\"n\">current</span> <span class=\"o\">=</span> <span class=\"p\">{}</span>\n",
       "    <span class=\"k\">for</span> <span class=\"n\">var</span> <span class=\"ow\">in</span> <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">variables</span><span class=\"p\">:</span>\n",
       "        <span class=\"n\">val</span> <span class=\"o\">=</span> <span class=\"n\">min_conflicts_value</span><span class=\"p\">(</span><span class=\"n\">csp</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">current</span><span class=\"p\">)</span>\n",
       "        <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">assign</span><span class=\"p\">(</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">,</span> <span class=\"n\">current</span><span class=\"p\">)</span>\n",
       "    <span class=\"c1\"># Now repeatedly choose a random conflicted variable and change it</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_steps</span><span class=\"p\">):</span>\n",
       "        <span class=\"n\">conflicted</span> <span class=\"o\">=</span> <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">conflicted_vars</span><span class=\"p\">(</span><span class=\"n\">current</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"n\">conflicted</span><span class=\"p\">:</span>\n",
       "            <span class=\"k\">return</span> <span class=\"n\">current</span>\n",
       "        <span class=\"n\">var</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\">conflicted</span><span class=\"p\">)</span>\n",
       "        <span class=\"n\">val</span> <span class=\"o\">=</span> <span class=\"n\">min_conflicts_value</span><span class=\"p\">(</span><span class=\"n\">csp</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">current</span><span class=\"p\">)</span>\n",
       "        <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">assign</span><span class=\"p\">(</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">,</span> <span class=\"n\">current</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(min_conflicts)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's use this algorithm  to solve the `eight_queens` CSP."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "solution = min_conflicts(eight_queens)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is indeed a valid solution. \n",
    "<br>\n",
    "`notebook.py` has a helper function to visualize the solution space."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAewAAAHwCAYAAABkPlyAAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4wLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvpW3flQAAIABJREFUeJzt3X+4FNWd7/vP97A3IIZfGzaYANfA\nJE/unRhxZI84Q+QSQ8aAYPTeuTNwjR7NzeXc3GMIipMZeZ55YvKcaK4KhIlzJydHBjxnDGjGMaJO\nlGgEA0adDaNMTGbuY8BERH5sYQcUE4Gz7h+1293du6q6uruqq6vq/Xqefrq7atVaq3ux+fZatWqV\nOecEAADa279LuwIAAKA2AjYAABlAwAYAIAMI2AAAZAABGwCADCBgAwCQAQRsAAAygIANAEAGELCB\nNmNmHzSzfzSzY2Z20MzuNrOOkPTjzOxvBtKeNLN/MbN/38o6A0geARtoP/+vpMOS3i/pAkn/s6T/\n2y+hmQ2X9KSkcyX9gaSxkv5M0h1mtrwltQXQEgRsoP1Ml/SAc+43zrmDkh6X9NGAtNdI+h8k/W/O\nuX3OuVPOucclLZf0n8xstCSZmTOzD5UOMrONZvafyt4vMrMXzazfzJ41s/PL9n3AzB40syNmtq/8\nh4CZ3WpmD5jZfzWzE2b2spn1lO3/czN7fWDfv5nZJ+P5ioDiIWAD7WedpCVmNsrMpkhaIC9o+/mU\npB84596u2v6gpFGSLq5VmJldKOlvJf0HSRMk/WdJW8xshJn9O0mPSHpJ0hRJn5S0wswuK8viCkmb\nJY2TtEXS3QP5fkTSDZJ+3zk3WtJlkl6tVR8A/gjYQPvZLq9HfVzSfkm9kr4fkHaipDeqNzrnTkvq\nk9Qdobz/U9J/ds4975w745y7V9Jv5QX735fU7Zz7mnPuXefcXkn/RdKSsuN3OOf+0Tl3RtJ/kzRz\nYPsZSSMk/a6ZdTrnXnXO/SJCfQD4IGADbWSgR/uEpH+QdLa8gDxe0v8TcEifvHPd1fl0DBx7JEKx\n50paOTAc3m9m/ZKmSfrAwL4PVO1bJWly2fEHy16flDTSzDqcc69IWiHpVkmHzWyzmX0gQn0A+CBg\nA+2lS16wvNs591vn3JuSNkhaGJD+SUkLzOzsqu3/q6RTkl4YeH9S3hB5yTllr1+T9HXn3Liyxyjn\n3KaBffuq9o12zgXVp4Jz7rvOuY/LC/xOwT88ANRAwAbaiHOuT9I+SV8wsw4zGyfp38s7h+znv8kb\nNv/ewOVgnQPnl/9K0h3OuV8PpHtR0v9uZsPM7NPyZp6X/BdJ/5eZzTbP2WZ2+cCEtRckHR+YPHbW\nwPHnmdnv1/osZvYRM7vUzEZI+o2kd+QNkwNoAAEbaD//i6RPyxvOfkXSaUk3+iV0zv1W0nx5PeHn\n5QXFxyV9U9JXy5J+SdJiSf2SrlbZOXHnXK+889h3Szo2UOZ1A/vODBx3gbwfEn2S7pF3+VgtIyR9\nY+CYg5ImyRtOB9AAc86lXQcAMTGzTkk/kPS6pOscf+BAbtDDBnLEOXdK3vnrX0j6SMrVARAjetgA\nAGQAPWwAADIg8IYCrTJx4kT3wQ9+MO1qJGbXrl1pVyFRs2bNSrsKiaMNs432y768t6GkPudczUWO\nUh8S7+npcb29vanWIUlmlnYVEpX2v59WiKsNXQz/zAdX6Y5P3tuQv8Hsy3sbStrlnKv5182QOJCg\nm6/xAnUcwVoazOumq+PJD0B2ELCBBHSN8QLrnV9KJv/VN3r5T+pKJn8A7Sf1c9hA3sTVm47i0Fbv\nOYmhcgDthR42EKNWBut2KBdA6xCwgRj85tn0g6brlf70U+nWAUByCNhAk1yvNGJ48/nccEfzeWy+\nPf0fDgCSwTlsoAnv7Gw+j/Lzz3/9gPfcbND9zbPSyD9sLg8A7YUeNtCEkSNqp+meL933A/99QZPF\nmp1EFkePH0B7IWADDarVC7Ye79HXL332L5sPwqX8So/z/qS5+gHIFgI20IBawfBb9/tvbzRo+x33\n8t7axxG0gfwgYAN16o6wWMnyO5OvhxTtB8CEscnXA0DyCNhAnQ5vjS+voB5wnD3jvqfiywtAepgl\nDtThz64ZfO3Xuy0FWtcbffjb9UonTkpj5krHn5FGj4penw1fiVafFUulb26Kni+A9kMPG6jDHQNr\ngwcF4/2HB1/PmTl0f1DPuRSkg4J10HHXLfaef3XQf3+pnmtX+u8HkB0EbCBG0xYOvt6xvjLQhg1z\nf/gq73nCpcFpqvMqf3/uovrqCSB7CNhARM2eV379cPC+V17zno8eD04Tti8KZowD2UbABmK0cE7w\nvqkLg/dFEdb7XnRJc3kDaH8EbKABJwOWJH1sXWvrUfLIWv/t7zzb2noASA4BG4hg8oTK92eN8IaY\nzypbmjTKkPPGRxor/+HttdOUlz9qpPd+ZNUSpRPHNVY+gPQRsIEIDj7hv/3kTunU897rKJdxXf/V\nodtOn6l839c/NM2VEWZ5l8rv3ya9vcM/zZEna+cDoD0RsIEmdQxr7vjhF1e+757fXH5j39fc8QDa\nEwEbiFGUXvaSVZXvnQtP/7mvxVMugGwjYAMtdn+dS5tu2JJMPQBkSyIB28w+bWb/ZmavmNlfJFEG\n0Eo3rYmettW93XrKq+dzAGgvsQdsMxsm6a8lLZD0u5KWmtnvxl0O0Eprboo3vy/cHi1d3Hf9ivtz\nAGidJHrYF0l6xTm31zn3rqTNkj6TQDlA21q0Inz/tx/0nrfv9t+/5RnvOei+2iXVs8evvbx23QBk\nUxIBe4qk18re7x/Y9h4zW2ZmvWbWe+TIkQSqALTW9A9Uvn8s4LKqavOW+W//TMSecPX12ff6XDYG\nIB+SCNjms61iHqxz7jvOuR7nXE93d3cCVQBa68f3DN22YHn4MV0hS41K0vhPhO9fsTp8P4B8SSJg\n75c0rez9VEkHEigHaJmJnwzfP2XS0G2P11gW9FiNm3n0nwjfv66B+1uHrUcOoL0lEbD/SdKHzWy6\nmQ2XtEQSF6Yg0978dWPHJTVj/KqbGzuu2Tt+AUhPR9wZOudOm9kNkp6QNEzS3zrnXo67HKDIvr8t\n7RoAaLXYA7YkOef+UdI/JpE30K4md0mHjqZX/uzz0isbQPJY6QyIqNbw9sE6VzAr97EPSfMvkn5n\nauN5PLcxfD/LlwLZlkgPGygq1xscGBfOae5+2ZfdIG19LrhcAPlGwAbqsHKttPrG8DT926Rx87zX\nh7ZKk7oq9193q3Tvo9HLnDNT2rFeeuLuwW37DkgzrvBeR+nZfzHmFdMAtJ65WrcKSlhPT4/r7c1v\n98DM77L0/Ej7308rVLdhlN6s9Qym27xVWroqPH09vvt1aellQ8upVZ8geW9D/gazL+9tKGmXc67m\nSSsCdsLy/g8t7X8/rVDdhhPHSUeejHBcxHPGi+dK1y+W5s2Sjp2QfrJHum2D9LO9tY+NEqwnXBp+\nOVfe25C/wezLexsqYsBmSByoU19/48duWeMF6CDjx0gzpkhXL6jcvuNF6ZLPN1Ym114D+UDABhoQ\nZSi6NAGts0N6t2qyWD0ztl2v9PELBsvrnC2dPtP8UDiAbCFgAw2Kev64FKwbDZ7lx515QTr1fLS8\nCNZAvnAdNtCEJbfUTmM9wcHz1mXSsae9wF96nNzpbfcz7KJogfiPv1w7DYBsYdJZwvI+WSLtfz+t\nUKsNg3rZ1YH1ynnSQ3c1Xo+lq7wZ542UHSbvbcjfYPblvQ3FpDOgNaxHenuHNGrk0H19T0kTxlZu\nGz1Xeutk9Py7xkhv/kjadJv3kKRvbJRuuXto2iW3SPf/MHreALKDgA3E4OyPe8/VPd6OYdL0K6RX\nm7jB7NHjlT3mXz46tKctcc4ayDvOYQMxKg+arld6eHtzwdrPuYu867bLfxwQrIH8o4cNxMx6pPGj\npaNPS9de7j2S0j2/uevCAWQHPWwgAcdOeIF7xepk8l9+p5c/wRooDnrYQILWbfIeUjx31GLoGygu\nethAi5Sux7aewbt5lVu5dui2cy6rPA5AcdHDBlLw67f8A/Ca+1pfFwDZQA8bAIAMIGADAJABBGwA\nADKAgA0AQAakfvMPM8v1yvVpf79JK8Ci/LRhxtF+2VeANuTmHwCQmDPHpBe7KjatXCutvrEq3fkH\npM73t65eyC162AlL+/tNGr/usy/vbRhr++2K4buaFe+/p7y3n1SIv8FIPWzOYQNAmEN3eoE6jmAt\nDeZ1KKF1a5Fb9LATlvb3mzR+3Wdf3tuw4fY79aa0Z2K8lfFz/kGpc3LDh+e9/aRC/A1yDhsAGhJX\nbzqKPed4zzEPlSN/GBIHgHKtDNbtUC4yg4ANAJK0e0T6QXOXSUc3p1sHtC0CNgDsMsm923Q2N9wR\nQ132LU3/hwPaEpPOEpb295s0JrxkX97bsGb77R4pud82VYbfndeavv+5DZcurF2vvLefVIi/QS7r\nAoCaIgTr7vnSfT/w3xd0n/Km718eQ48f+UIPO2Fpf79J49d99uW9DUPbr8bQc5Sec1hgrpX2ozOk\nnz4QWoWas8fz3n5SIf4G6WEDQKAawfpb9/tvb7Tn7Hfcy3sjHMj5bAwgYAMontOHayZZfmcL6qGI\nPwBO9yVeD7Q/AjaA4nmp8ZXFqgVNLmt60lm5l7pjzAxZxUpnAIrljcFrr8LOUbve6MPfrlc6cVIa\nM1c6/ow0elT06mz4yuDr0HPmB9dK51TfCgxFQg8bQLEc+HNJwcF4f9lo+ZyZQ/cH9ZxLQTooWAcd\nd91i7/lXB/33v1fP12/yT4DCIGADQJlpCwdf71hfGWjDhrk/fJX3POHS4DTVeZW/P3dRffVE8RCw\nARRHkzOuXw+Zq/bKa97z0ePBacL2RcKM8UIjYANAmYVzgvdNXRi8L4qw3veiS5rLG/lHwAZQSCd3\n+m9/bF1r61HyyFr/7e8829p6oH0RsAEUw6nKWV1njfDOIZ81YnBblEuxNj7SWPEPb6+dprz8USO9\n9yOHVyU6daSxCiDzWJo0YWl/v0ljWcTsy3sbvtd+Ied/T5+ROmcPpPcJ2tUzyqvTlB8vSUeelCaO\nqy+P8jT926Sx7wusbsVypXlvP6kQf4MsTQoAUXQMa+744RdXvu+e31x+ocEahUXABoAyURZLWbKq\n8n2tDuDnvhZPuSi22AO2mf2tmR02s5/GnTcAtIP7t9aXfsOWZOqBYkmih71R0qcTyBcAGnbTmuhp\nW93brae8ej4H8iX2gO2ce0bS0bjzBYBmrIl5Zc8v3B4tXdx3/Yr7cyA7OIcNAD4WrQjf/+0Hveft\nu/33b3nGew66r3bJlSsr3197ee26oZhSCdhmtszMes0szhvQAUDDpn+g8v1jO6IdN2+Z//bPROwJ\nV1+ffe9Xox2H4kklYDvnvuOc64ly3RkAtMKP7xm6bcHy8GO6QpYalaTxnwjfv2J1+H6gHEPiAIph\nZvgKYVMmDd32eI1lQY/VuJlH/4nw/es2he/3dX5fAwchD5K4rGuTpJ9I+oiZ7Tez/yPuMgCgbh0T\nGzosqRnjV93c4IGdE2KtB7KjI+4MnXNL484TAPLm+9vSrgGyhiFxABgwuSvd8mefl275aG/c/CNh\naX+/SePGA9mX9zYc0n4hNwGRGh8C/9iHvIC/74D0i/2N5VHzbmGzhv5bzHv7SYX4G4x084/Yh8QB\nIMtcb3DQXjinuftlX3aDtPW54HKBMARsAMUy9S5pf/iMr/5t0rh53utDW6VJVUPl190q3fto9CLn\nzJR2rJeeuHtw274D0owrvNcHo6xNPu2voheIXGJIPGFpf79JYzgu+/Lehr7tV2NYXPJ62aVe7+at\n0tJV4enr8d2vS0svG1pOKJ/hcCn/7ScV4m8w0pA4ATthaX+/SeM/i+zLexv6tt+pI9Ienwuvq0Q9\nn714rnT9YmneLOnYCekne6TbNkg/2xuhflGC9fl9gZdz5b39pEL8DXIOGwB8dXY3fOiWNV6ADjJ+\njDRjinT1gsrtO16ULvl8g4Vy7TVEDztxaX+/SePXffblvQ1D2y/i0Hhnh/Tuc0O3R65DVS+6c7Z0\n+kxzQ+Hv1SPn7ScV4m+QHjYAhJrlIgXtUrBu9JKv8uPOvCCdej5iXjWCNYqFhVMAFNv02gt6W09w\ngL11mXTsaa+3XHqc3Olt9zPsoojBevr3IiRCkTAknrC0v9+kMRyXfXlvw0jtF9DLrg6sV86THrqr\n8bosXeXNOC8XOCwesXed9/aTCvE3yCzxdpD295s0/rPIvry3YeT22z1Kcu9UbLIeqe8pacLYyqSj\n50pvnYxeh64x0ps/qtz2jY3SLXf7BOzpm6SuJZHzznv7SYX4G+QcNgBEduFABK7qbXcMk6ZfIb16\noPGsjx6v7K3/8tGhPW1JnLNGKM5hA0C5sqDpeqWHtzcXrP2cu8i7bruid02wRg0MiScs7e83aQzH\nZV/e27Dh9jt1VNrTguufzz/c1HXheW8/qRB/g5GGxOlhA4Cfzi6v1zttbTL5T1vn5d9EsEax0MNO\nWNrfb9L4dZ99eW/DWNsvwjXbNcU89J339pMK8TdIDxsAYjXLDT5mHhuye6VfZ/z8NyqPAxpEDzth\naX+/SePXffblvQ1pv+wrQBvSwwYAIC8I2AAAZAABGwCADEh9pbNZs2aptzfKPeayKe/nl/J+bkmi\nDbOO9su+vLdhVPSwAQDIgNR72AAAtErg3dHq0Oh90ZtFDxsAkGs3XzN4r/I4lPK66ep48ouKgA0A\nyKWuMV5gvfNLyeS/+kYv/0ldyeRfjSFxAEDuxNWbjuLQwK1Skx4qp4cNAMiVVgbrVpZLwAYA5MJv\nnk0vWJe4XulPP5VM3gRsAEDmuV5pxPDm87nhjubz2Hx7Mj8cOIcNAMi0d3Y2n0f5+ee/fsB7bjbo\n/uZZaeQfNpdHOXrYAIBMGzmidpru+dJ9P/DfFzRZrNlJZHH0+MsRsAEAmVWrF2w93qOvX/rsXzYf\nhEv5lR7n/Ulz9asHARsAkEm1guG37vff3mjQ9jvu5b21j4sraBOwAQCZ0x1hsZLldyZfDynaD4AJ\nY5svh4ANAMicw1vjyyuoBxzncHbfU83nwSxxAECm/Nk1g6/9erelQOt6ow9/u17pxElpzFzp+DPS\n6FHR67PhK9Hqs2Kp9M1N0fOtRg8bAJApdwysDR4UjPcfHnw9Z+bQ/UE951KQDgrWQcddt9h7/tVB\n//2leq5d6b8/KgI2ACBXpi0cfL1jfWWgDRvm/vBV3vOES4PTVOdV/v7cRfXVs14EbABAZjR7Xvn1\nw8H7XnnNez56PDhN2L4omqk/ARsAkCsL5wTvm7oweF8UYb3vRZc0l3ctBGwAQCadDFiS9LF1ra1H\nySNr/be/82w8+ROwAQCZMHlC5fuzRnhDzGeVLU0aZch54yONlf/w9tppyssfNdJ7P7JqidKJ4xor\nn4ANAMiEg0/4bz+5Uzr1vPc6ymVc13916LbTZyrf9/UPTXNlhFnepfL7t0lv7/BPc+TJ2vn4IWAD\nADKvY1hzxw+/uPJ99/zm8hv7vuaO90PABgDkSpRe9pJVle+dC0//ua/FU24zCNgAgMK5v86lTTds\nSaYe9Yg9YJvZNDN72sx+bmYvm9mX4i4DAFA8N62Jnjbp3m4z5dXzOcol0cM+LWmlc+5/knSxpP9o\nZr+bQDkAgAJZc1O8+X3h9mjp4r7rV6OfI/aA7Zx7wzm3e+D1CUk/lzQl7nIAAAizaEX4/m8/6D1v\n3+2/f8sz3nPQfbVLqmePX3t57bo1ItFz2Gb2QUm/J+n5qu3LzKzXzHqPHDmSZBUAAAUx/QOV7x8L\nuKyq2rxl/ts/E7EnXH199r0+l43FIbGAbWbvk/SgpBXOuYrVV51z33HO9Tjnerq7u5OqAgCgQH58\nz9BtC5aHH9MVstSoJI3/RPj+FavD98cpkYBtZp3ygvV9zrl/SKIMAECxTPxk+P4pk4Zue7zGsqDH\natzMo/9E+P51DdzfOmw98jBJzBI3Sesl/dw51+BcOAAAKr3568aOS2rG+FU3N3Zco3f8SqKHPUfS\nNZIuNbMXBx5N3h8FAID28v1trS2vI+4MnXM7JFnc+QIAUMvkLunQ0fTKn31ecnmz0hkAIDNqDW8f\nrHMFs3If+5A0/yLpd6Y2nsdzG8P3NzM8H3sPGwCANLne4MC4cE5z98u+7AZp63PB5SaJgA0AyJSV\na6XVN4an6d8mjZvnvT60VZrUVbn/ululex+NXuacmdKO9dITdw9u23dAmnGF9zpKz/6LTa6YZq7W\nLUoS1tPT43p7E/5ZkiJv0nx+pf3vpxVow2yj/bLPrw2j9GatZzDd5q3S0lXh6evx3a9LSy8bWk6t\n+gTY5ZyrOVhOwE4Y/1lkH22YbbRf9vm14cRx0pEnIxwb8Zzx4rnS9YulebOkYyekn+yRbtsg/Wxv\n7WOjBOsJl4ZezhUpYDMkDgDInL7+xo/dssYL0EHGj5FmTJGuXlC5fceL0iWfb6zMRq+9LkfABgBk\nUpSh6NIEtM4O6d2qyWL1zNh2vdLHLxgsr3O2dPpM00PhdSFgAwAyK+r541KwbjR4lh935gXp1PPR\n8opzlTWuwwYAZNqSW2qnsZ7g4HnrMunY017gLz1O7vS2+xl2UbRA/Mdfrp2mHkw6SxgTXrKPNsw2\n2i/7orRhUC+7OrBeOU966K7G67J0lTfjvJGyQzDpDABQDNYjvb1DGjVy6L6+p6QJYyu3jZ4rvXUy\nev5dY6Q3fyRtus17SNI3Nkq33D007ZJbpPt/GD3vqAjYAIBcOPvj3nN1j7djmDT9CunVA43nffR4\nZY/5l48O7WlLyd0ZTOIcNgAgZ8qDpuuVHt7eXLD2c+4i77rt8h8HSQZriR42ACCHrEcaP1o6+rR0\n7eXeIynd85u7LjwqetgAgFw6dsIL3CtWJ5P/8ju9/FsRrCV62ACAnFu3yXtI8dxRK+mh7yD0sAEA\nhVG6Htt6Bu/mVW7l2qHbzrms8ri00MMGABTSr9/yD8Br7mt9XaKghw0AQAYQsAEAyAACNgAAGUDA\nBgAgA1K/+YeZ5Xrl+rS/36Tl/cYKEm2YdbRf9hWgDSPd/IMeNtrSuNGVt7pzvdJNVw/dds6EtGsK\nAK1BDzthaX+/SYvz1327LmhAG2Yb7Zd9BWhDethofzdfM9hbjkN5bxwA8oQedsLS/n6T1uiv+9K9\nZZM2+Y+kw0eby4M2zDbaL/sK0IaRetisdIaWi6s3HcWhgfvVprmcIADEgSFxtFQrg3U7lAsAcSFg\noyV+82z6QdP1Sn/6qXTrAACNImAjca5XGjG8+XxuuKP5PDbfnv4PBwBoBJPOEpb295u0WhNe3tkp\njRzRZBk+55+bDbq/fVca+YfR0ha9DbOO9su+ArQhl3UhfVGCdfd86b4f+O8LmizW7CSyOHr8ANBK\n9LATlvb3m7SwX/e1esFRes5hgblW2o/OkH76QP11GFJOgdswD2i/7CtAG9LDRnpqBetv3e+/vdGe\ns99xL++tfRznswFkBQEbsevuqp1m+Z3J10OK9gNgwtjk6wEAzSJgI3aHt8aXV1APOM6ecd9T8eUF\nAElhpTPE6s+uGXwddo7a9UYf/na90omT0pi50vFnpNGjotdnw1ei1WfFUumbm6LnCwCtRg8bsbrj\nS95zUDDef3jw9ZyZQ/cH9ZxLQTooWAcdd91i7/lXB/33l+q5dqX/fgBoFwRstNS0hYOvd6yvDLRh\nw9wfvsp7nnBpcJrqvMrfn7uovnoCQLshYCM2zZ5Xfv1w8L5XXvOejx4PThO2LwpmjANoZwRstNTC\nOcH7pi4M3hdFWO970SXN5Q0AaSNgIxEnd/pvf2xda+tR8sha/+3vPNvaegBAowjYiMXkCZXvzxrh\nDTGfVbY0aZQh542PNFb+w9trpykvf9RI7/3IqiVKJ45rrHwASBpLkyYs7e83aaVlEcOC8ekzUuds\nBaarnlFenab8eEk68uTQwForj/I0/dukse8Lru+QvArShnlF+2VfAdqQpUnRHjqGNXf88Isr33fP\nby6/sGANAO2KgI2WirJYypJVle9r/bj+3NfiKRcA2lnsAdvMRprZC2b2kpm9bGZfjbsM5Nv9dS5t\numFLMvUAgHaSRA/7t5Iudc7NlHSBpE+b2cU1jkHG3bQmetpW93brKa+ezwEArRR7wHaetwbedg48\n8j1jAFpzU7z5feH2aOnivutX3J8DAOKSyDlsMxtmZi9KOizph86556v2LzOzXjNjbamCWrQifP+3\nH/Set+/237/lGe856L7aJVdWrRF+7eW16wYA7SjRy7rMbJykhyR90Tn304A0ue59F+ByBEm1r7Ge\ncYW070DlttIxQUPWte7oFbY/KO8o14JzWVe+0H7ZV4A2TP+yLudcv6Rtkj6dZDlofz++Z+i2BcvD\nj+kKWWpUksZ/Inz/itXh+wEgS5KYJd490LOWmZ0lab6kf427HLSXiZ8M3z9l0tBtj9dYFvRYjZt5\n9J8I37+ugftbh61HDgBp6kggz/dLutfMhsn7QfCAc+7RBMpBG3nz140dl9SM8atubuy4Zu/4BQBJ\niT1gO+f2SPq9uPMF6vH9bWnXAADixUpnaJnJXemWP/u8dMsHgGZw84+Epf39Jq16hmqtWdiNDoF/\n7ENewN93QPrF/sbyaLRuRWvDvKH9sq8AbRhplngS57CBQGGXYi2c09z9si+7Qdr6XHC5AJBlBGzE\nauVaafWN4Wn6t0nj5nmvD22VJlUNlV93q3RvHdMU58yUdqyXnrh7cNu+A96135J0MMLa5F+MecU0\nAIgbQ+IJS/v7TZrfcFzUxUlK6TZvlZauCk9fj+9+XVp62dByatUnSBHbME9ov+wrQBtGGhInYCcs\n7e83aX7/WUwcJx15MsKxEc9nL54rXb9YmjdLOnZC+ske6bYN0s/21j42SrCecGn45VxFbMM8of2y\nrwBtyDlspKOvv/Fjt6zxAnSQ8WOkGVOkqxdUbt/xonTJ5xsrk2uvAWQBPeyEpf39Ji3s133UoejO\nDund54Zuj6q6nM7Z0ukzzQ+Fv5d/gdswD2i/7CtAG9LDRrqinj8uBetGL/kqP+7MC9Kp56Pl1er7\ncgNAM1g4BYlackvtNNYTHDxVmMDUAAAgAElEQVRvXSYde9oL/KXHyZ3edj/DLooWiP/4y7XTAEA7\nYUg8YWl/v0mLMhwX1MuuDqxXzpMeuqvxuixd5c04b6TsMLRhttF+2VeANmSWeDtI+/tNWtT/LN7e\nIY0aWXVsj9T3lDRhbOX20XOlt05Gr0PXGOnNH1Vu+8ZG6Za7hwbsJbdI9/8wet4SbZh1tF/2FaAN\nOYeN9nH2x73n6gDaMUyafoX06oHG8z56vLLH/MtHh/a0Jc5ZA8g2zmGjpcqDpuuVHt7eXLD2c+4i\n77rt8h8HBGsAWceQeMLS/n6T1uhw3PjR0tGnY66Mj+75zV0XLtGGWUf7ZV8B2jDSkDg9bKTi2Amv\n17tidTL5L79z4Bx5k8EaANoFPeyEpf39Ji3OX/dx3FEriaFv2jDbaL/sK0Ab0sNGtpSux7aewbt5\nlVu5dui2cy6rPA4A8ooedsLS/n6Txq/77Mt7G9J+2VeANqSHDQBAXhCwAQDIAAI2AAAZkPpKZ7Nm\nzVJvbwzTg9tU3s8v5f3ckkQbZh3tl315b8Oo6GEDAJABqfewY7Mrhl9gs/L/SxUAkE3Z7mEfutML\n1HEEa2kwr0MJLb8FAECDshmwT73pBdb9X04m//03e/mfOpRM/gAA1Cl7Q+Jx9aaj2HOO98xQOQAg\nZdnqYbcyWLdDuQAADMhGwN49Iv2gucuko5vTrQMAoLDaP2DvMsm923Q2N9wRQ132LU3/hwMAoJDa\n+xz27pFNZ1F+B6e/fsB7bvo2jrtHSBf+tslMAACIrr172K52UOyeL933A/99QbdbbPo2jDH0+AEA\nqEf7BuwaQ8+l+x/39Uuf/cvmg3D5PZWtRzrvT5qrHwAAcWrPgF0jGH7rfv/tjQZtv+Ne3hvhQII2\nAKBF2i9gnz5cM8nyO1tQD0X8AXC6L/F6AADQfgH7pcmxZRU0uazpSWflXuqOMTMAAPy11yzxNwav\nvfLr3ZYCreuNPvzteqUTJ6Uxc6Xjz0ijR0WvzoavDL4Oq48OrpXOuTF6xgAA1Km9etgH/lxScDDe\nXzZaPmfm0P1BPedSkA4K1kHHXbfYe/7VQf/979Xz9Zv8EwAAEJP2Ctg1TFs4+HrH+spAGzbM/eGr\nvOcJlwanqc6r/P25i+qrJwAAcWufgN3kjOvXQ+aqvfKa93z0eHCasH2RMGMcAJCg9gnYESycE7xv\n6sLgfVGE9b4XXdJc3gAANKstA/bJnf7bH1vX2nqUPLLWf/s7z7a2HgCA4mqPgH2qclbXWSO8c8hn\njRjcFuVSrI2PNFb8w9trpykvf9RI7/3I4VWJTh1prAIAANTQHgF7z/t9N5/cKZ163nsd5TKu6786\ndNvpM5Xv+/qHprlyZe28S+X3b5Pe3hGQaM+k2hkBANCA9gjYITqGNXf88Isr33fPby6/se9r7ngA\nABrR9gG7XJRe9pJVle+dC0//ua/FUy4AAElKJGCb2TAz+2czezSJ/MPcv7W+9Bu2JFMPAADilFQP\n+0uSfh418U1romfc6t5uPeXV8zkAAKhH7AHbzKZKulzSPVGPWRPzyp5fuD1aurjv+hX35wAAoCSJ\nHvY3JX1Z0n8PSmBmy8ys18x6jxyp/1KoRSvC93/7Qe95+27//Vue8Z6D7qtdUj17/NrLa9cNAIAk\nxBqwzWyRpMPOuV1h6Zxz33HO9Tjnerq7a9+ecvoHKt8/FnRZVZV5y/y3fyZiT7j6+ux7fS4bAwCg\nFeLuYc+RdIWZvSpps6RLzezvms30xz6D6wuWhx/TFbLUqCSN/0T4/hWrw/cDANBKsQZs59wtzrmp\nzrkPSloi6UfOuc/WPHBm+LD4FJ/1SB6vsSzosRo38+g/Eb5/3abw/b7O72vgIAAAamuP67A7JjZ0\nWFIzxq+6ucEDOyfEWg8AAEo6ksrYObdN0rak8k/S97elXQMAACq1Rw87gsld6ZY/+7x0ywcAFFv7\nBOxZ4WuIHqxzBbNyH/uQNP8i6XemNp7HcxtrJKhRfwAAmpHYkHgSXG/weeuFc5q7X/ZlN0hbnwsu\nFwCANLVXwJ56l7Q/fMZX/zZp3Dzv9aGt0qSqofLrbpXurWMF8zkzpR3rpSfuHty274A04wrvdaSe\n/bS/il4gAAANaJ8hcUmaXPvG1KXbW7peL1hv3ur1ukuPeoK1JO18qfL4TU94C7WUetWRzp1P+mJ9\nhQIAUCdzte4/mbCenh7X21s25nzqiLTH58LrKlEv6Vo8V7p+sTRvlnTshPSTPdJtG6Sf7a19bKSh\n8PP7Qi/nMrNoFc2otP/9tAJtmG20X/blvQ0l7XLO1Yxq7TUkLkmdtZcqDbJljRegg4wfI82YIl29\noHL7jhelSz7fYKFcew0AaIH2C9iSN+N6V/gvqtIEtM4O6d2qyWL1LKjieqWPXzDYm+6cLZ0+E7F3\nzcxwAECLtGfAliIFbWkwWDe66ln5cWdekE49HzEvgjUAoIXaa9JZtem1F/QuTRbzc+sy6djTXm+5\n9Di509vuZ9hFEYP19O9FSAQAQHzab9JZtYBednVgvXKe9NBdjddj6Spvxnm5wGHxOnrXeZ8skfa/\nn1agDbON9su+vLehMjvprNosJ+0eJbl3huzqe0qaMLZy2+i50lsno2ffNUZ680fSptu8hyR9Y6N0\ny90+iadvkrqWRM8cAICYtH/AlqQLByJwVW+7Y5g0/Qrp1QONZ330eGVv/ZePDu1pS+KcNQAgVe19\nDrtaWdB0vdLD25sL1n7OXeRdt10xHE6wBgCkLBs97HKznHTqqLRngq69XLr28gTLOv9wU9eFAwAQ\nl2z1sEs6u7zAPW1tMvlPW+flT7AGALSJ7PWwy01a4T2kSNds18TQNwCgTWWzh+1nlht8zDw2ZPdK\nv874+W9UHgcAQJvKdg87SMe4IQF49d+lVBcAAGKQnx42AAA5RsAGACADCNgAAGRA6muJm1muZ3ul\n/f0mrQBr/NKGGUf7ZV8B2jDSWuL0sAEAyIB8zhIHADQk8C6FdYh0m2LUjR42ABTczdd4gTqOYC0N\n5nXT1fHkBw/nsBOW9vebNM6fZV/e25D2C1a6vXDSJv+RdPho48cXoA1zcj9sAEDs4upNR3Fo4JbF\nDJU3hyFxACiYVgbrdig3LwjYAFAQv3k2/aDpeqU//VS6dcgqAjYAFIDrlUYMbz6fG+5oPo/Nt6f/\nwyGLmHSWsLS/36TlfcKSRBtmHe0nvbNTGjmiyXJ8zj83G3R/+6408g9rpytAG7JwCgAgWrDuni/d\n9wP/fUGTxZqdRBZHj79I6GEnLO3vN2l5751JtGHWFb39avWCo/ScwwJzrbQfnSH99IH661BRRv7b\nkB42ABRZrWD9rfv9tzfac/Y77uW9tY/jfHY0BGwAyKHurtpplt+ZfD2kaD8AJoxNvh5ZR8AGgBw6\nvDW+vIJ6wHH2jPueii+vvGKlMwDImT+7ZvB12Dlq1xt9+Nv1SidOSmPmSsefkUaPil6fDV+JVp8V\nS6Vvboqeb9HQwwaAnLnjS95zUDDef3jw9ZyZQ/cH9ZxLQTooWAcdd91i7/lXB/33l+q5dqX/fngI\n2ABQMNMWDr7esb4y0IYNc3/4Ku95wqXBaarzKn9/7qL66olKBGwAyJFmzyu/fjh43yuvec9Hjwen\nCdsXBTPGgxGwAaBgFs4J3jd1YfC+KMJ634suaS7voiNgA0BOndzpv/2xda2tR8kja/23v/Nsa+uR\nVQRsAMiJyRMq3581whtiPqtsadIoQ84bH2ms/Ie3105TXv6okd77kVVLlE4c11j5ecfSpAlL+/tN\nWt6XtZRow6wrUvuFBePTZ6TO2cHpqmeUV6cpP16Sjjw5NLDWyqM8Tf82aez7gutbnlcB2pClSQEA\nno5hzR0//OLK993zm8svLFjDHwEbAAomymIpS1ZVvq/Vyf3c1+IpF8ESCdhm9qqZ/YuZvWhmTNIH\ngIy5v86lTTdsSaYeGJRkD/sTzrkLoozLAwCad9Oa6Glb3dutp7x6PkeRMCQOADmx5qZ48/vC7dHS\nxX3Xr7g/R14kFbCdpK1mtsvMllXvNLNlZtbLcDkApGfRivD9337Qe96+23//lme856D7apdcWbVG\n+LWX164bhkrksi4z+4Bz7oCZTZL0Q0lfdM49E5A21/P1C3A5QtpVSBxtmG1Far9a11jPuELad6By\nW+mYoCHrWnf0CtsflHeUa8G5rGuoRHrYzrkDA8+HJT0k6aIkygEARPfje4ZuW7A8/JiukKVGJWn8\nJ8L3r1gdvh/RxR6wzexsMxtdei3pjyT9NO5yAACVJn4yfP+USUO3PV5jWdBjNW7m0X8ifP+6Bu5v\nHbYeeZF1JJDnZEkPDQzTdEj6rnPu8QTKAQCUefPXjR2X1Izxq25u7Lhm7/iVV7EHbOfcXkk+t0QH\nABTJ97elXYN84bIuACiQyV3plj/7vHTLzzJu/pGwtL/fpOV9hrFEG2ZdEduv1izsRofAP/YhL+Dv\nOyD9Yn9jeTRStwK0YaRZ4kmcwwYAtLGwS7EWzmnuftmX3SBtfS64XDSOgA0AObNyrbT6xvA0/duk\ncfO814e2SpOqhsqvu1W699HoZc6ZKe1YLz1x9+C2fQe8a78l6WCEtcm/GPOKaXnDkHjC0v5+k5b3\n4VSJNsy6orZf1MVJSuk2b5WWrgpPX4/vfl1aetnQcmrVx08B2jDSkDgBO2Fpf79Jy/t/9hJtmHVF\nbb+J46QjT0Y4PuL57MVzpesXS/NmScdOSD/ZI922QfrZ3trHRgnWEy4NvpyrAG3IOWwAKKq+/saP\n3bLGC9BBxo+RZkyRrl5QuX3Hi9Iln2+sTK69ro0edsLS/n6TlvfemUQbZl3R2y/qUHRnh/Tuc0O3\nR1VdTuds6fSZ5obC38s7/21IDxsAii7q+eNSsG70kq/y4868IJ16Plperb4vd5axcAoA5NySW2qn\nsZ7g4HnrMunY017gLz1O7vS2+xl2UbRA/Mdfrp0GgxgST1ja32/S8j6cKtGGWUf7eYJ62dWB9cp5\n0kN3NV6fpau8GeeNlB2kAG3ILPF2kPb3m7S8/2cv0YZZR/sNenuHNGpk1fE9Ut9T0oSxldtHz5Xe\nOhm9Hl1jpDd/VLntGxulW+4eGrCX3CLd/8PoeRegDTmHDQAYdPbHvefqANoxTJp+hfTqgcbzPnq8\nssf8y0eH9rQlzlk3g3PYAFAw5UHT9UoPb28uWPs5d5F33Xb5jwOCdXMYEk9Y2t9v0vI+nCrRhllH\n+wUbP1o6+nSMlQnQPb+568IL0IaRhsTpYQNAQR074fV6V6xOJv/ldw6cI28iWGMQPeyEpf39Ji3v\nvTOJNsw62q8+cdxRK+6h7wK0IT1sAEB9StdjW8/g3bzKrVw7dNs5l1Ueh2TQw05Y2t9v0vLeO5No\nw6yj/bKvAG1IDxsAgLwgYAMAkAEEbAAAMiD1lc5mzZql3t4YpiW2qbyfX8r7uSWJNsw62i/78t6G\nUdHDBgAgAwjYAABkQOpD4gByZFcMQ5ez8j/ECzSCHjaA5hy60wvUcQRraTCvQwmtlwlkFAEbQGNO\nvekF1v1fTib//Td7+Z86lEz+QMYwJA6gfnH1pqPYc473zFA5Co4eNoD6tDJYt0O5QJsgYAOIZveI\n9IPmLpOObk63DkBKCNgAattlknu36WxuuCOGuuxbmv4PByAFnMMGEG73yKazKL/l4l8/4D03fd/l\n3SOkC3/bZCZAdtDDBhDO1Q6K3fOl+37gvy/o/shN3zc5hh4/kCUEbADBagw9W4/36OuXPvuXzQfh\nUn6lx3l/0lz9gDwhYAPwVyMYfut+/+2NBm2/417eG+FAgjYKgoANYKjTh2smWX5nC+qhiD8ATvcl\nXg8gbQRsAEO9NDm2rIImlzU96azcS90xZga0J2aJA6j0xuC1V36921Kgdb3Rh79dr3TipDRmrnT8\nGWn0qOjV2fCVwddh9dHBtdI5N0bPGMgYetgAKh34c0nBwXh/2Wj5nJlD9wf1nEtBOihYBx133WLv\n+VcH/fe/V8/Xb/JPAOQEARtAXaYtHHy9Y31loA0b5v7wVd7zhEuD01TnVf7+3EX11RPIGwI2gEFN\nzrh+PWSu2iuvec9HjwenCdsXCTPGkWMEbAB1WTgneN/UhcH7ogjrfS+6pLm8gawjYAPwdXKn//bH\n1rW2HiWPrPXf/s6zra0HkBYCNgDPqcpZXWeN8M4hnzVicFuUS7E2PtJY8Q9vr52mvPxRI733I4dX\nJTp1pLEKAG2OgA3As+f9vptP7pROPe+9jnIZ1/VfHbrt9JnK9339Q9NcubJ23qXy+7dJb+8ISLRn\nUu2MgAwiYAOoqWNYc8cPv7jyfff85vIb+77mjgeyKJGAbWbjzOzvzexfzeznZvYHSZQDoPWi9LKX\nrKp871x4+s99LZ5ygTxLqoe9TtLjzrn/UdJMST9PqBwAbej+rfWl37AlmXoAeRJ7wDazMZLmSlov\nSc65d51zPmesALSTm9ZET9vq3m495dXzOYAsSaKHPUPSEUkbzOyfzeweMzs7gXIAxGhNzCt7fuH2\naOnivutX3J8DaBdJBOwOSRdK+hvn3O9JelvSX5QnMLNlZtZrZr1HjnAJBpBFi1aE7//2g97z9t3+\n+7c84z0H3Ve7pHr2+LWX164bkEdJBOz9kvY75wYuBNHfywvg73HOfcc51+Oc6+nu5rZ4QBZM/0Dl\n+8eCLquqMm+Z//bPROwJV1+ffa/PZWNAEcQesJ1zByW9ZmYfGdj0SUk/i7scAK3143uGbluwPPyY\nrpClRiVp/CfC969YHb4fKJKk7of9RUn3mdlwSXslXZ9QOQDiMvOI9FLwiNcUn/VIHq+xLOixGjfz\n6D8Rvn/dpvD9vs7va+AgoP0lErCdcy9K4qpJIEs6JjZ0WFIzxq+6ucEDOyfEWg+gXbDSGYC29P1t\nadcAaC8EbACRTe5Kt/zZ56VbPpAmAjaAQbPC1xA9WOcKZuU+9iFp/kXS70xtPI/nNtZIUKP+QJYl\nNekMQE653uDz1gvnNHe/7MtukLY+F1wuUGQEbACVpt4l7Q+f8dW/TRo3z3t9aKs0qWqo/LpbpXsf\njV7knJnSjvXSE3cPbtt3QJpxhfc6Us9+2l9FLxDIIIbEAVSaXPvG1KXbW7peL1hv3ur1ukuPeoK1\nJO18qfL4TU94C7WUetWRzp1P+mJ9hQIZY67Wfe8S1tPT43p78zvWZWZpVyFRaf/7aYVCtuGpI9Ie\nnwuvq0S9pGvxXOn6xdK8WdKxE9JP9ki3bZB+tjdC/aL893B+X+DlXIVsv5zJextK2uWcq/nXxJA4\ngKE6G18yeMsaL0AHGT9GmjFFunpB5fYdL0qXfL7BQrn2GgVAwAbgb5aTdoX3bEoT0Do7pHerJovV\ns6CK65U+fsFgb7pztnT6TMTeNTPDURAEbADBIgRtaTBYN7rqWflxZ16QTj0fMS+CNQqESWcAwk2v\nvaB3abKYn1uXScee9nrLpcfJnd52P8Muihisp38vQiIgP5h0lrC8T5ZI+99PK9CGCuxlVwfWK+dJ\nD93VeF2WrvJmnJcLHBaP2Lum/bIv720oJp0BiM0sJ+0eJbl3huzqe0qaMLZy2+i50lsno2ffNUZ6\n80fSptu8hyR9Y6N0y90+iadvkrqWRM8cyAkCNoBoLhyIwFW97Y5h0vQrpFcPNJ710eOVvfVfPjq0\npy2Jc9YoNM5hA6hPWdB0vdLD25sL1n7OXeRdt10xHE6wRsHRwwZQv1lOOnVU2jNB114uXXt5gmWd\nf7ip68KBvKCHDaAxnV1e4J62Npn8p63z8idYA5LoYQNo1qQV3kOKdM12TQx9A77oYQOIzyw3+Jh5\nbMjulX6d8fPfqDwOgC962ACS0TFuSABe/Xcp1QXIAXrYAABkAAEbAIAMIGADAJABqa8lbma5nmWS\n9vebtAKs8UsbZhztl30FaMNIa4nTwwYAIAOYJZ4lXOMKAIVFD7vdHbrTC9RxBGtpMK9Dq+PJDwDQ\nEpzDTljD3++pN6U9E+OtjJ/zD0qdkxs+nPNn2Zf3NqT9sq8Abcj9sDMrrt50FHvO8Z4ZKgeAtsaQ\neLtpZbBuh3IBAJEQsNvF7hHpB81dJh3dnG4dAAC+CNjtYJdJ7t2ms7nhjhjqsm9p+j8cAABDMOks\nYTW/390jJffbpsown6kKrrepLCUbLl1Yu15MeMm+vLch7Zd9BWhDFk7JhAjBunu+dN8P/Pf5Beuw\n7ZHF0OMHAMSHHnbCQr/fGkPPUXrOYYG5VtqPzpB++kBoFWrOHufXffblvQ1pv+wrQBvSw25rNYL1\nt+73395oz9nvuJf3RjiQ89kA0BYI2Gk4fbhmkuV3tqAeivgD4HRf4vUAAIQjYKfhpcZXFqsWNLms\n6Uln5V7qjjEzAEAjWOms1d4YvPYq7By1640+/O16pRMnpTFzpePPSKNHRa/Ohq8Mvg49Z35wrXTO\njdEzBgDEih52qx34c0nBwXh/2Wj5nJlD9wf1nEtBOihYBx133WLv+VcH/fe/V8/Xb/JPAABoCQJ2\nm5m2cPD1jvWVgTZsmPvDV3nPEy4NTlOdV/n7cxfVV08AQGsRsFupyRnXr4fMVXvlNe/56PHgNGH7\nImHGOACkhoDdZhbOCd43dWHwvijCet+LLmkubwBAsgjYKTm503/7Y+taW4+SR9b6b3/n2dbWAwDg\nj4DdKqcqZ3WdNcI7h3zWiMFtUS7F2vhIY8U/vL12mvLyR4303o8cXpXo1JHGKgAAaApLkybsve83\n5Pzv6TNS5+yB9D5Bu3pGeXWa8uMl6ciT0sRx9eVRnqZ/mzT2fYHVrViulGURsy/vbUj7ZV8B2pCl\nSbOiY1hzxw+/uPJ99/zm8gsN1gCAVBCw20yUxVKWrKp8X+vH5+e+Fk+5AID0xB6wzewjZvZi2eO4\nma2Iu5wiu39rfek3bEmmHgCA1ok9YDvn/s05d4Fz7gJJsySdlPRQ3OVkzU1roqdtdW+3nvLq+RwA\ngPgkPST+SUm/cM79MuFy2t6amFf2/MLt0dLFfdevuD8HACCapAP2Ekmbqjea2TIz6zWzOO8plSuL\napxE+PaD3vP23f77tzzjPQfdV7vkypWV76+9vHbdAACtl9hlXWY2XNIBSR91zh0KSZfr+fpRLuuS\npBlXSPsOVB078HMmaMi61h29wvYH5R3ptpxc1pUreW9D2i/7CtCGqV/WtUDS7rBgjUE/vmfotgXL\nw4/pCllqVJLGfyJ8/4rV4fsBAO0jyYC9VD7D4YU1M3yFsCmThm57vMayoMdq3Myj/0T4/nWNtM75\nfQ0cBABoViIB28xGSfqUpH9IIv9M6pjY0GFJzRi/6uYGD+ycEGs9AADRdCSRqXPupCT+Z29j39+W\ndg0AAPVgpbM2Mrkr3fJnn5du+QCAYNz8I2FDvt8as8UbHQL/2Ie8gL/vgPSL/Y3lUXOG+KyhTcUM\n1ezLexvSftlXgDaMNEs8kSFxNC7sUqyFc5q7X/ZlN0hbnwsuFwDQvgjYrTb1Lml/+Iyv/m3SuHne\n60NbpUlVQ+XX3Srd+2j0IufMlHasl564e3DbvgPetd+SdDDK2uTT/ip6gQCA2DEknjDf77fGsLjk\n9bJLvd7NW6Wlq8LT1+O7X5eWXja0nFA+w+ESw3F5kPc2pP2yrwBtGGlInICdMN/v99QRaY/PhddV\nop7PXjxXun6xNG+WdOyE9JM90m0bpJ/tjVC/KMH6/L7Ay7n4zyL78t6GtF/2FaANOYfdtjq7Gz50\nyxovQAcZP0aaMUW6ekHl9h0vSpd8vsFCufYaAFJHDzthod9vxKHxzg7p3eeGbo9ch6pedOds6fSZ\n5obC36sHv+4zL+9tSPtlXwHakB5225vlIgXtUrBu9JKv8uPOvCCdej5iXjWCNQCgdVg4JW3Tay/o\nbT3BAfbWZdKxp73eculxcqe33c+wiyIG6+nfi5AIANAqDIknLNL3G9DLrg6sV86THrqr8bosXeXN\nOC8XOCwesXfNcFz25b0Nab/sK0AbMku8HUT+fnePktw7FZusR+p7SpowtjLp6LnSWyej16FrjPTm\njyq3fWOjdMvdPgF7+iapa0nkvPnPIvvy3oa0X/YVoA05h50pFw5E4KredscwafoV0qsHGs/66PHK\n3vovHx3a05bEOWsAaGOcw243ZUHT9UoPb28uWPs5d5F33XZF75pgDQBtjSHxhDX8/Z46Ku1pwfXP\n5x9u6rpwhuOyL+9tSPtlXwHaMNKQOD3sdtXZ5fV6p61NJv9p67z8mwjWAIDWoYedsFi/3wjXbNcU\n89A3v+6zL+9tSPtlXwHakB527sxyg4+Zx4bsXunXGT//jcrjAACZRA87YWl/v0nj13325b0Nab/s\nK0Ab0sMGACAvCNgAAGQAARsAgAxoh5XO+iT9soXlTRwosyVSOr/U0s+Ygry3Ie0XI9ovdi3/fAVo\nw3OjJEp90lmrmVlvlJP7WZb3z8jnyzY+X7bl/fNJ7fsZGRIHACADCNgAAGRAEQP2d9KuQAvk/TPy\n+bKNz5dtef98Upt+xsKdwwYAIIuK2MMGACBzCNgAAGRAoQK2mX3azP7NzF4xs79Iuz5xMrO/NbPD\nZvbTtOuSBDObZmZPm9nPzexlM/tS2nWKm5mNNLMXzOylgc/41bTrFDczG2Zm/2xmj6ZdlySY2atm\n9i9m9qKZ9aZdn7iZ2Tgz+3sz+9eBv8U/SLtOcTGzjwy0W+lx3MxWpF2vcoU5h21mwyT9f5I+JWm/\npH+StNQ597NUKxYTM5sr6S1J/9U5d17a9Ymbmb1f0vudc7vNbLSkXZKuzEv7SZJ5q0Oc7Zx7y8w6\nJe2Q9CXn3HMpVy02ZnaTpB5JY5xzi9KuT9zM7FVJPc65XC6cYmb3Svqxc+4eMxsuaZRzrj/tesVt\nIF68Lmm2c66VC3uFKlIP+yJJrzjn9jrn3pW0WdJnUq5TbJxzz0g6mnY9kuKce8M5t3vg9QlJP5c0\nJd1axct53hp42znwyF6IdlEAAAJeSURBVM0vajObKulySfekXRfUz8zGSJorab0kOefezWOwHvBJ\nSb9op2AtFStgT5H0Wtn7/crZf/hFYWYflPR7kp5PtybxGxgyflHSYUk/dM7l6TN+U9KXJf33tCuS\nICdpq5ntMrNlaVcmZjMkHZG0YeC0xj1mdnbalUrIEkmb0q5EtSIFbL/FaHPTeykKM3ufpAclrXDO\nHU+7PnFzzp1xzl0gaaqki8wsF6c3zGyRpMPOuV1p1yVhc5xzF0paIOk/DpyqyosOSRdK+hvn3O9J\neltSruYCSdLAUP8Vkr6Xdl2qFSlg75c0rez9VEkHUqoLGjBwXvdBSfc55/4h7fokaWCocZukT6dc\nlbjMkXTFwDnezZIuNbO/S7dK8XPOHRh4PizpIXmn4vJiv6T9ZaM+fy8vgOfNAkm7nXOH0q5ItSIF\n7H+S9GEzmz7wC2qJpC0p1wkRDUzIWi/p5865NWnXJwlm1m1m4wZenyVpvqR/TbdW8XDO3eKcm+qc\n+6C8v70fOec+m3K1YmVmZw9MiNTAUPEfScrNVRvOuYOSXjOzjwxs+qSk3Ez6LLNUbTgcLrXH7TVb\nwjl32sxukPSEpGGS/tY593LK1YqNmW2SNE/SRDPbL+krzrn16dYqVnMkXSPpXwbO8UrSKufcP6ZY\np7i9X9K9AzNU/52kB5xzubz8KacmS3po4FaQHZK+65x7PN0qxe6Lku4b6PTslXR9yvWJlZmNkncl\n0X9Iuy5+CnNZFwAAWVakIXEAADKLgA0AQAYQsAEAyAACNgAAGUDABgAgAwjYAABkAAEbAIAM+P8B\nYrfnP4SxJKkAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x25de3ac6a58>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_NQueens(solution)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Lets' see if we can find a different solution."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\nAUlr8AXRtSNBAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x25ddb1286a0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "eight_queens = NQueensCSP(8)\n",
    "solution = min_conflicts(eight_queens)\n",
    "plot_NQueens(solution)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The solution is a bit different this time. \n",
    "Running the above cell several times should give you various valid solutions.\n",
    "<br>\n",
    "In the `search.ipynb` notebook, we will see how NQueensProblem can be solved using a heuristic search method such as `uniform_cost_search` and `astar_search`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Helper Functions\n",
    "\n",
    "We will now implement a few helper functions that will help us visualize the Coloring Problem. We will make some modifications to the existing Classes and Functions for additional book keeping. To begin we modify the **assign** and **unassign** methods in the **CSP** to add a copy of the assignment to the **assignment_history**. We call this new class **InstruCSP**. This will allow us to see how the assignment evolves over time."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import copy\n",
    "class InstruCSP(CSP):\n",
    "    \n",
    "    def __init__(self, variables, domains, neighbors, constraints):\n",
    "        super().__init__(variables, domains, neighbors, constraints)\n",
    "        self.assignment_history = []\n",
    "        \n",
    "    def assign(self, var, val, assignment):\n",
    "        super().assign(var,val, assignment)\n",
    "        self.assignment_history.append(copy.deepcopy(assignment))\n",
    "    \n",
    "    def unassign(self, var, assignment):\n",
    "        super().unassign(var,assignment)\n",
    "        self.assignment_history.append(copy.deepcopy(assignment))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we define **make_instru** which takes an instance of **CSP** and returns a **InstruCSP** instance. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def make_instru(csp):\n",
    "    return InstruCSP(csp.variables, csp.domains, csp.neighbors, csp.constraints)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will now use a graph defined as a dictionary for plotting purposes in our Graph Coloring Problem. The keys are the nodes and their corresponding values are the nodes they are connected to."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "neighbors = {\n",
    "    0: [6, 11, 15, 18, 4, 11, 6, 15, 18, 4], \n",
    "    1: [12, 12, 14, 14], \n",
    "    2: [17, 6, 11, 6, 11, 10, 17, 14, 10, 14], \n",
    "    3: [20, 8, 19, 12, 20, 19, 8, 12], \n",
    "    4: [11, 0, 18, 5, 18, 5, 11, 0], \n",
    "    5: [4, 4], \n",
    "    6: [8, 15, 0, 11, 2, 14, 8, 11, 15, 2, 0, 14], \n",
    "    7: [13, 16, 13, 16], \n",
    "    8: [19, 15, 6, 14, 12, 3, 6, 15, 19, 12, 3, 14], \n",
    "    9: [20, 15, 19, 16, 15, 19, 20, 16], \n",
    "    10: [17, 11, 2, 11, 17, 2], \n",
    "    11: [6, 0, 4, 10, 2, 6, 2, 0, 10, 4], \n",
    "    12: [8, 3, 8, 14, 1, 3, 1, 14], \n",
    "    13: [7, 15, 18, 15, 16, 7, 18, 16], \n",
    "    14: [8, 6, 2, 12, 1, 8, 6, 2, 1, 12], \n",
    "    15: [8, 6, 16, 13, 18, 0, 6, 8, 19, 9, 0, 19, 13, 18, 9, 16], \n",
    "    16: [7, 15, 13, 9, 7, 13, 15, 9], \n",
    "    17: [10, 2, 2, 10], \n",
    "    18: [15, 0, 13, 4, 0, 15, 13, 4], \n",
    "    19: [20, 8, 15, 9, 15, 8, 3, 20, 3, 9], \n",
    "    20: [3, 19, 9, 19, 3, 9]\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we are ready to create an InstruCSP instance for our problem. We are doing this for an instance of **MapColoringProblem** class which inherits from the **CSP** Class. This means that our **make_instru** function will work perfectly for it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "coloring_problem = MapColoringCSP('RGBY', neighbors)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "coloring_problem1 = make_instru(coloring_problem)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### CONSTRAINT PROPAGATION\n",
    "Algorithms that solve CSPs have a choice between searching and or do a _constraint propagation_, a specific type of inference.\n",
    "The constraints can be used to reduce the number of legal values for a another variable, which in turn can reduce the legal values for another variable, and so on.\n",
    "<br>\n",
    "Constraint propagation tries to enforce _local consistency_.\n",
    "Consider each variable as a node in a graph and each binary constraint as an arc.\n",
    "Enforcing local consistency causes inconsistent values to be eliminated throughout the graph, \n",
    "a lot like the `GraphPlan` algorithm in planning, where mutex links are removed from a planning graph.\n",
    "There are different types of local consistency:\n",
    "1. Node consistency\n",
    "2. Arc consistency\n",
    "3. Path consistency\n",
    "4. K-consistency\n",
    "5. Global constraints\n",
    "\n",
    "Refer __section 6.2__ in the book for details.\n",
    "<br>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## AC-3\n",
    "Before we dive into AC-3, we need to know what _arc-consistency_ is.\n",
    "<br>\n",
    "A variable $X_i$ is __arc-consistent__ with respect to another variable $X_j$ if for every value in the current domain $D_i$ there is some value in the domain $D_j$ that satisfies the binary constraint on the arc $(X_i, X_j)$.\n",
    "<br>\n",
    "A network is arc-consistent if every variable is arc-consistent with every other variable.\n",
    "<br>\n",
    "\n",
    "AC-3 is an algorithm that enforces arc consistency.\n",
    "After applying AC-3, either every arc is arc-consistent, or some variable has an empty domain, indicating that the CSP cannot be solved.\n",
    "Let's see how `AC3` is implemented in the module."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "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\">AC3</span><span class=\"p\">(</span><span class=\"n\">csp</span><span class=\"p\">,</span> <span class=\"n\">queue</span><span class=\"o\">=</span><span class=\"bp\">None</span><span class=\"p\">,</span> <span class=\"n\">removals</span><span class=\"o\">=</span><span class=\"bp\">None</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;[Figure 6.3]&quot;&quot;&quot;</span>\n",
       "    <span class=\"k\">if</span> <span class=\"n\">queue</span> <span class=\"ow\">is</span> <span class=\"bp\">None</span><span class=\"p\">:</span>\n",
       "        <span class=\"n\">queue</span> <span class=\"o\">=</span> <span class=\"p\">[(</span><span class=\"n\">Xi</span><span class=\"p\">,</span> <span class=\"n\">Xk</span><span class=\"p\">)</span> <span class=\"k\">for</span> <span class=\"n\">Xi</span> <span class=\"ow\">in</span> <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">variables</span> <span class=\"k\">for</span> <span class=\"n\">Xk</span> <span class=\"ow\">in</span> <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">neighbors</span><span class=\"p\">[</span><span class=\"n\">Xi</span><span class=\"p\">]]</span>\n",
       "    <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">support_pruning</span><span class=\"p\">()</span>\n",
       "    <span class=\"k\">while</span> <span class=\"n\">queue</span><span class=\"p\">:</span>\n",
       "        <span class=\"p\">(</span><span class=\"n\">Xi</span><span class=\"p\">,</span> <span class=\"n\">Xj</span><span class=\"p\">)</span> <span class=\"o\">=</span> <span class=\"n\">queue</span><span class=\"o\">.</span><span class=\"n\">pop</span><span class=\"p\">()</span>\n",
       "        <span class=\"k\">if</span> <span class=\"n\">revise</span><span class=\"p\">(</span><span class=\"n\">csp</span><span class=\"p\">,</span> <span class=\"n\">Xi</span><span class=\"p\">,</span> <span class=\"n\">Xj</span><span class=\"p\">,</span> <span class=\"n\">removals</span><span class=\"p\">):</span>\n",
       "            <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">curr_domains</span><span class=\"p\">[</span><span class=\"n\">Xi</span><span class=\"p\">]:</span>\n",
       "                <span class=\"k\">return</span> <span class=\"bp\">False</span>\n",
       "            <span class=\"k\">for</span> <span class=\"n\">Xk</span> <span class=\"ow\">in</span> <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">neighbors</span><span class=\"p\">[</span><span class=\"n\">Xi</span><span class=\"p\">]:</span>\n",
       "                <span class=\"k\">if</span> <span class=\"n\">Xk</span> <span class=\"o\">!=</span> <span class=\"n\">Xj</span><span class=\"p\">:</span>\n",
       "                    <span class=\"n\">queue</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">((</span><span class=\"n\">Xk</span><span class=\"p\">,</span> <span class=\"n\">Xi</span><span class=\"p\">))</span>\n",
       "    <span class=\"k\">return</span> <span class=\"bp\">True</span>\n",
       "</pre></div>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "psource(AC3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`AC3` also employs a helper function `revise`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "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\">revise</span><span class=\"p\">(</span><span class=\"n\">csp</span><span class=\"p\">,</span> <span class=\"n\">Xi</span><span class=\"p\">,</span> <span class=\"n\">Xj</span><span class=\"p\">,</span> <span class=\"n\">removals</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Return true if we remove a value.&quot;&quot;&quot;</span>\n",
       "    <span class=\"n\">revised</span> <span class=\"o\">=</span> <span class=\"bp\">False</span>\n",
       "    <span class=\"k\">for</span> <span class=\"n\">x</span> <span class=\"ow\">in</span> <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">curr_domains</span><span class=\"p\">[</span><span class=\"n\">Xi</span><span class=\"p\">][:]:</span>\n",
       "        <span class=\"c1\"># If Xi=x conflicts with Xj=y for every possible y, eliminate Xi=x</span>\n",
       "        <span class=\"k\">if</span> <span class=\"nb\">all</span><span class=\"p\">(</span><span class=\"ow\">not</span> <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">constraints</span><span class=\"p\">(</span><span class=\"n\">Xi</span><span class=\"p\">,</span> <span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">Xj</span><span class=\"p\">,</span> <span class=\"n\">y</span><span class=\"p\">)</span> <span class=\"k\">for</span> <span class=\"n\">y</span> <span class=\"ow\">in</span> <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">curr_domains</span><span class=\"p\">[</span><span class=\"n\">Xj</span><span class=\"p\">]):</span>\n",
       "            <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">prune</span><span class=\"p\">(</span><span class=\"n\">Xi</span><span class=\"p\">,</span> <span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">removals</span><span class=\"p\">)</span>\n",
       "            <span class=\"n\">revised</span> <span class=\"o\">=</span> <span class=\"bp\">True</span>\n",
       "    <span class=\"k\">return</span> <span class=\"n\">revised</span>\n",
       "</pre></div>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "psource(revise)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`AC3` maintains a queue of arcs to consider which initially contains all the arcs in the CSP.\n",
    "An arbitrary arc $(X_i, X_j)$ is popped from the queue and $X_i$ is made _arc-consistent_ with respect to $X_j$.\n",
    "<br>\n",
    "If in doing so, $D_i$ is left unchanged, the algorithm just moves to the next arc, \n",
    "but if the domain $D_i$ is revised, then we add all the neighboring arcs $(X_k, X_i)$ to the queue.\n",
    "<br>\n",
    "We repeat this process and if at any point, the domain $D_i$ is reduced to nothing, then we know the whole CSP has no consistent solution and `AC3` can immediately return failure.\n",
    "<br>\n",
    "Otherwise, we keep removing values from the domains of variables until the queue is empty.\n",
    "We finally get the arc-consistent CSP which is faster to search because the variables have smaller domains."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's see how `AC3` can be used.\n",
    "<br>\n",
    "We'll first define the required variables."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "neighbors = parse_neighbors('A: B; B: ')\n",
    "domains = {'A': [0, 1, 2, 3, 4], 'B': [0, 1, 2, 3, 4]}\n",
    "constraints = lambda X, x, Y, y: x % 2 == 0 and (x + y) == 4 and y % 2 != 0\n",
    "removals = []"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We'll now define a `CSP` object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "csp = CSP(variables=None, domains=domains, neighbors=neighbors, constraints=constraints)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "AC3(csp, removals=removals)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This configuration is inconsistent."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "constraints = lambda X, x, Y, y: (x % 2) == 0 and (x + y) == 4\n",
    "removals = []\n",
    "csp = CSP(variables=None, domains=domains, neighbors=neighbors, constraints=constraints)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "AC3(csp,removals=removals)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This configuration is consistent."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## BACKTRACKING SEARCH\n",
    "\n",
    "For solving a CSP the main issue with Naive search algorithms is that they can continue expanding obviously wrong paths. In backtracking search, we check constraints as we go. Backtracking is just the above idea combined with the fact that we are dealing with one variable at a time. Backtracking Search is implemented in the repository as the function **backtracking_search**. This is the same as **Figure 6.5** in the book. The function takes as input a CSP and few other optional parameters which can be used to further speed it up. The function returns the correct assignment if it satisfies the goal. We will discuss these later. Let us solve our **coloring_problem1** with **backtracking_search**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "result = backtracking_search(coloring_problem1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{0: 'R',\n",
       " 1: 'R',\n",
       " 2: 'R',\n",
       " 3: 'R',\n",
       " 4: 'G',\n",
       " 5: 'R',\n",
       " 6: 'G',\n",
       " 7: 'R',\n",
       " 8: 'B',\n",
       " 9: 'R',\n",
       " 10: 'G',\n",
       " 11: 'B',\n",
       " 12: 'G',\n",
       " 13: 'G',\n",
       " 14: 'Y',\n",
       " 15: 'Y',\n",
       " 16: 'B',\n",
       " 17: 'B',\n",
       " 18: 'B',\n",
       " 19: 'G',\n",
       " 20: 'B'}"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result # A dictonary of assignments."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let us also check the number of assignments made."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "21"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "coloring_problem1.nassigns"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let us check the total number of assignments and unassignments which is the length of our assignment history."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "21"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(coloring_problem1.assignment_history)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let us explore the optional keyword arguments that the **backtracking_search** function takes. These optional arguments help speed up the assignment further. Along with these, we will also point out to methods in the CSP class that help make this work. \n",
    "\n",
    "The first of these is **select_unassigned_variable**. It takes in a function that helps in deciding the order in which variables will be selected for assignment. We use a heuristic called Most Restricted Variable which is implemented by the function **mrv**. The idea behind **mrv** is to choose the variable with the fewest legal values left in its domain. The intuition behind selecting the **mrv** or the most constrained variable is that it allows us to encounter failure quickly before going too deep into a tree if we have selected a wrong step before. The **mrv** implementation makes use of another function **num_legal_values** to sort out the variables by a number of legal values left in its domain. This function, in turn, calls the **nconflicts** method of the **CSP** to return such values.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "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\">mrv</span><span class=\"p\">(</span><span class=\"n\">assignment</span><span class=\"p\">,</span> <span class=\"n\">csp</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Minimum-remaining-values heuristic.&quot;&quot;&quot;</span>\n",
       "    <span class=\"k\">return</span> <span class=\"n\">argmin_random_tie</span><span class=\"p\">(</span>\n",
       "        <span class=\"p\">[</span><span class=\"n\">v</span> <span class=\"k\">for</span> <span class=\"n\">v</span> <span class=\"ow\">in</span> <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">variables</span> <span class=\"k\">if</span> <span class=\"n\">v</span> <span class=\"ow\">not</span> <span class=\"ow\">in</span> <span class=\"n\">assignment</span><span class=\"p\">],</span>\n",
       "        <span class=\"n\">key</span><span class=\"o\">=</span><span class=\"k\">lambda</span> <span class=\"n\">var</span><span class=\"p\">:</span> <span class=\"n\">num_legal_values</span><span class=\"p\">(</span><span class=\"n\">csp</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">assignment</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(mrv)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "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\">num_legal_values</span><span class=\"p\">(</span><span class=\"n\">csp</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">):</span>\n",
       "    <span class=\"k\">if</span> <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">curr_domains</span><span class=\"p\">:</span>\n",
       "        <span class=\"k\">return</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">curr_domains</span><span class=\"p\">[</span><span class=\"n\">var</span><span class=\"p\">])</span>\n",
       "    <span class=\"k\">else</span><span class=\"p\">:</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">count</span><span class=\"p\">(</span><span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">nconflicts</span><span class=\"p\">(</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">)</span> <span class=\"o\">==</span> <span class=\"mi\">0</span>\n",
       "                     <span class=\"k\">for</span> <span class=\"n\">val</span> <span class=\"ow\">in</span> <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">domains</span><span class=\"p\">[</span><span class=\"n\">var</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(num_legal_values)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "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\">nconflicts</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">):</span>\n",
       "        <span class=\"sd\">&quot;&quot;&quot;Return the number of conflicts var=val has with other variables.&quot;&quot;&quot;</span>\n",
       "        <span class=\"c1\"># Subclasses may implement this more efficiently</span>\n",
       "        <span class=\"k\">def</span> <span class=\"nf\">conflict</span><span class=\"p\">(</span><span class=\"n\">var2</span><span class=\"p\">):</span>\n",
       "            <span class=\"k\">return</span> <span class=\"p\">(</span><span class=\"n\">var2</span> <span class=\"ow\">in</span> <span class=\"n\">assignment</span> <span class=\"ow\">and</span>\n",
       "                    <span class=\"ow\">not</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">constraints</span><span class=\"p\">(</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">,</span> <span class=\"n\">var2</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">[</span><span class=\"n\">var2</span><span class=\"p\">]))</span>\n",
       "        <span class=\"k\">return</span> <span class=\"n\">count</span><span class=\"p\">(</span><span class=\"n\">conflict</span><span class=\"p\">(</span><span class=\"n\">v</span><span class=\"p\">)</span> <span class=\"k\">for</span> <span class=\"n\">v</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">neighbors</span><span class=\"p\">[</span><span class=\"n\">var</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(CSP.nconflicts)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Another ordering related parameter **order_domain_values** governs the value ordering. Here we select the Least Constraining Value which is implemented by the function **lcv**. The idea is to select the value which rules out the fewest values in the remaining variables. The intuition behind selecting the **lcv** is that it leaves a lot of freedom to assign values later. The idea behind selecting the mrc and lcv makes sense because we need to do all variables but for values, we might better try the ones that are likely. So for vars, we face the hard ones first.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "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\">lcv</span><span class=\"p\">(</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">,</span> <span class=\"n\">csp</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;Least-constraining-values heuristic.&quot;&quot;&quot;</span>\n",
       "    <span class=\"k\">return</span> <span class=\"nb\">sorted</span><span class=\"p\">(</span><span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">choices</span><span class=\"p\">(</span><span class=\"n\">var</span><span class=\"p\">),</span>\n",
       "                  <span class=\"n\">key</span><span class=\"o\">=</span><span class=\"k\">lambda</span> <span class=\"n\">val</span><span class=\"p\">:</span> <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">nconflicts</span><span class=\"p\">(</span><span class=\"n\">var</span><span class=\"p\">,</span> <span class=\"n\">val</span><span class=\"p\">,</span> <span class=\"n\">assignment</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(lcv)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally, the third parameter **inference** can make use of one of the two techniques called Arc Consistency or Forward Checking. The details of these methods can be found in the **Section 6.3.2** of the book. In short the idea of inference is to detect the possible failure before it occurs and to look ahead to not make mistakes. **mac** and **forward_checking** implement these two techniques. The **CSP** methods **support_pruning**, **suppose**, **prune**, **choices**, **infer_assignment** and **restore** help in using these techniques. You can know more about these by looking up the source code."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let us compare the performance with these parameters enabled vs the default parameters. We will use the Graph Coloring problem instance usa for comparison. We will call the instances **solve_simple** and **solve_parameters** and solve them using backtracking and compare the number of assignments."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "solve_simple = copy.deepcopy(usa)\n",
    "solve_parameters = copy.deepcopy(usa)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'AL': 'G',\n",
       " 'AR': 'G',\n",
       " 'AZ': 'B',\n",
       " 'CA': 'Y',\n",
       " 'CO': 'B',\n",
       " 'CT': 'R',\n",
       " 'DC': 'G',\n",
       " 'DE': 'B',\n",
       " 'FL': 'R',\n",
       " 'GA': 'B',\n",
       " 'IA': 'G',\n",
       " 'ID': 'B',\n",
       " 'IL': 'R',\n",
       " 'IN': 'B',\n",
       " 'KA': 'G',\n",
       " 'KY': 'G',\n",
       " 'LA': 'R',\n",
       " 'MA': 'G',\n",
       " 'MD': 'R',\n",
       " 'ME': 'R',\n",
       " 'MI': 'G',\n",
       " 'MN': 'R',\n",
       " 'MO': 'B',\n",
       " 'MS': 'B',\n",
       " 'MT': 'R',\n",
       " 'NC': 'G',\n",
       " 'ND': 'G',\n",
       " 'NE': 'R',\n",
       " 'NH': 'B',\n",
       " 'NJ': 'R',\n",
       " 'NM': 'G',\n",
       " 'NV': 'G',\n",
       " 'NY': 'B',\n",
       " 'OH': 'R',\n",
       " 'OK': 'R',\n",
       " 'OR': 'R',\n",
       " 'PA': 'G',\n",
       " 'RI': 'B',\n",
       " 'SC': 'R',\n",
       " 'SD': 'B',\n",
       " 'TN': 'R',\n",
       " 'TX': 'B',\n",
       " 'UT': 'R',\n",
       " 'VA': 'B',\n",
       " 'VT': 'R',\n",
       " 'WA': 'G',\n",
       " 'WI': 'B',\n",
       " 'WV': 'Y',\n",
       " 'WY': 'G'}"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "backtracking_search(solve_simple)\n",
    "backtracking_search(solve_parameters, order_domain_values=lcv, select_unassigned_variable=mrv, inference=mac)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "49"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "solve_simple.nassigns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "49"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "solve_parameters.nassigns"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## TREE CSP SOLVER\n",
    "\n",
    "The `tree_csp_solver` function (**Figure 6.11** in the book) can be used to solve problems whose constraint graph is a tree. Given a CSP, with `neighbors` forming a tree, it returns an assignment that satisfies the given constraints. The algorithm works as follows:\n",
    "\n",
    "First it finds the *topological sort* of the tree. This is an ordering of the tree where each variable/node comes after its parent in the tree. The function that accomplishes this is `topological_sort`, which builds the topological sort using the recursive function `build_topological`. That function is an augmented DFS, where each newly visited node of the tree is pushed on a stack. The stack in the end holds the variables topologically sorted.\n",
    "\n",
    "Then the algorithm makes arcs between each parent and child consistent. *Arc-consistency* between two variables, *a* and *b*, occurs when for every possible value of *a* there is an assignment in *b* that satisfies the problem's constraints. If such an assignment cannot be found, then the problematic value is removed from *a*'s possible values. This is done with the use of the function `make_arc_consistent` which takes as arguments a variable `Xj` and its parent, and makes the arc between them consistent by removing any values from the parent which do not allow for a consistent assignment in `Xj`.\n",
    "\n",
    "If an arc cannot be made consistent, the solver fails. If every arc is made consistent, we move to assigning values.\n",
    "\n",
    "First we assign a random value to the root from its domain and then we start assigning values to the rest of the variables. Since the graph is now arc-consistent, we can simply move from variable to variable picking any remaining consistent values. At the end we are left with a valid assignment. If at any point though we find a variable where no consistent value is left in its domain, the solver fails.\n",
    "\n",
    "The implementation of the algorithm:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "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\">tree_csp_solver</span><span class=\"p\">(</span><span class=\"n\">csp</span><span class=\"p\">):</span>\n",
       "    <span class=\"sd\">&quot;&quot;&quot;[Figure 6.11]&quot;&quot;&quot;</span>\n",
       "    <span class=\"n\">assignment</span> <span class=\"o\">=</span> <span class=\"p\">{}</span>\n",
       "    <span class=\"n\">root</span> <span class=\"o\">=</span> <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">variables</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n",
       "    <span class=\"n\">X</span><span class=\"p\">,</span> <span class=\"n\">parent</span> <span class=\"o\">=</span> <span class=\"n\">topological_sort</span><span class=\"p\">(</span><span class=\"n\">csp</span><span class=\"p\">,</span> <span class=\"n\">root</span><span class=\"p\">)</span>\n",
       "\n",
       "    <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">support_pruning</span><span class=\"p\">()</span>\n",
       "    <span class=\"k\">for</span> <span class=\"n\">Xj</span> <span class=\"ow\">in</span> <span class=\"nb\">reversed</span><span class=\"p\">(</span><span class=\"n\">X</span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">:]):</span>\n",
       "        <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"n\">make_arc_consistent</span><span class=\"p\">(</span><span class=\"n\">parent</span><span class=\"p\">[</span><span class=\"n\">Xj</span><span class=\"p\">],</span> <span class=\"n\">Xj</span><span class=\"p\">,</span> <span class=\"n\">csp</span><span class=\"p\">):</span>\n",
       "            <span class=\"k\">return</span> <span class=\"bp\">None</span>\n",
       "\n",
       "    <span class=\"n\">assignment</span><span class=\"p\">[</span><span class=\"n\">root</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">csp</span><span class=\"o\">.</span><span class=\"n\">curr_domains</span><span class=\"p\">[</span><span class=\"n\">root</span><span class=\"p\">][</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n",
       "    <span class=\"k\">for</span> <span class=\"n\">Xi</span> <span class=\"ow\">in</span> <span class=\"n\">X</span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">:]:</span>\n",
       "        <span class=\"n\">assignment</span><span class=\"p\">[</span><span class=\"n\">Xi</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">assign_value</span><span class=\"p\">(</span><span class=\"n\">parent</span><span class=\"p\">[</span><span class=\"n\">Xi</span><span class=\"p\">],</span> <span class=\"n\">Xi</span><span class=\"p\">,</span> <span class=\"n\">csp</span><span class=\"p\">,</span> <span class=\"n\">assignment</span><span class=\"p\">)</span>\n",
       "        <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"n\">assignment</span><span class=\"p\">[</span><span class=\"n\">Xi</span><span class=\"p\">]:</span>\n",
       "            <span class=\"k\">return</span> <span class=\"bp\">None</span>\n",
       "    <span class=\"k\">return</span> <span class=\"n\">assignment</span>\n",
       "</pre></div>\n",
       "</body>\n",
       "</html>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "psource(tree_csp_solver)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will now use the above function to solve a problem. More specifically, we will solve the problem of coloring the map of Australia. At our disposal we have two colors: Red and Blue. As a reminder, this is the graph of Australia:\n",
    "\n",
    "`\"SA: WA NT Q NSW V; NT: WA Q; NSW: Q V; T: \"`\n",
    "\n",
    "Unfortunately as you can see the above is not a tree. If, though, we remove `SA`, which has arcs to `WA`, `NT`, `Q`, `NSW` and `V`, we are left with a tree (we also remove `T`, since it has no in-or-out arcs). We can now solve this using our algorithm. Let's define the map coloring problem at hand:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "australia_small = MapColoringCSP(list('RB'),\n",
    "                           'NT: WA Q; NSW: Q V')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will input `australia_small` to the `tree_csp_solver` and we will print the given assignment."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'NT': 'R', 'Q': 'B', 'NSW': 'R', 'V': 'B', 'WA': 'B'}\n"
     ]
    }
   ],
   "source": [
    "assignment = tree_csp_solver(australia_small)\n",
    "print(assignment)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`WA`, `Q` and `V` got painted with the same color and `NT` and `NSW` got painted with the other."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## GRAPH COLORING VISUALIZATION\n",
    "\n",
    "Next, we define some functions to create the visualisation from the assignment_history of **coloring_problem1**. The reader need not concern himself with the code that immediately follows as it is the usage of Matplotib with IPython Widgets. If you are interested in reading more about these visit [ipywidgets.readthedocs.io](http://ipywidgets.readthedocs.io). We will be using the **networkx** library to generate graphs. These graphs can be treated as the graph that needs to be colored or as a constraint graph for this problem. If interested you can read a dead simple tutorial [here](https://www.udacity.com/wiki/creating-network-graphs-with-python). We start by importing the necessary libraries and initializing matplotlib inline.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import networkx as nx\n",
    "import matplotlib.pyplot as plt\n",
    "import matplotlib\n",
    "import time"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The ipython widgets we will be using require the plots in the form of a step function such that there is a graph corresponding to each value. We define the **make_update_step_function** which return such a function. It takes in as inputs the neighbors/graph along with an instance of the **InstruCSP**. This will be more clear with the example below. If this sounds confusing do not worry this is not the part of the core material and our only goal is to help you visualize how the process works."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def make_update_step_function(graph, instru_csp):\n",
    "    \n",
    "    def draw_graph(graph):\n",
    "        # create networkx graph\n",
    "        G=nx.Graph(graph)\n",
    "        # draw graph\n",
    "        pos = nx.spring_layout(G,k=0.15)\n",
    "        return (G, pos)\n",
    "    \n",
    "    G, pos = draw_graph(graph)\n",
    "    \n",
    "    def update_step(iteration):\n",
    "        # here iteration is the index of the assignment_history we want to visualize.\n",
    "        current = instru_csp.assignment_history[iteration]\n",
    "        #  We convert the particular assignment to a default dict so that the color for nodes which \n",
    "        # have not been assigned defaults to black.\n",
    "        current = defaultdict(lambda: 'Black', current)\n",
    "\n",
    "        # Now we use colors in the list and default to black otherwise.\n",
    "        colors = [current[node] for node in G.node.keys()]\n",
    "        # Finally drawing the nodes.\n",
    "        nx.draw(G, pos, node_color=colors, node_size=500)\n",
    "\n",
    "        labels = {label:label for label in G.node}\n",
    "        # Labels shifted by offset so as to not overlap nodes.\n",
    "        label_pos = {key:[value[0], value[1]+0.03] for key, value in pos.items()}\n",
    "        nx.draw_networkx_labels(G, label_pos, labels, font_size=20)\n",
    "\n",
    "        # show graph\n",
    "        plt.show()\n",
    "\n",
    "    return update_step  # <-- this is a function\n",
    "\n",
    "def make_visualize(slider):\n",
    "    ''' Takes an input a slider and returns \n",
    "        callback function for timer and animation\n",
    "    '''\n",
    "    \n",
    "    def visualize_callback(Visualize, time_step):\n",
    "        if Visualize is True:\n",
    "            for i in range(slider.min, slider.max + 1):\n",
    "                slider.value = i\n",
    "                time.sleep(float(time_step))\n",
    "    \n",
    "    return visualize_callback\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally let us plot our problem. We first use the function above to obtain a step function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "step_func = make_update_step_function(neighbors, coloring_problem1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we set the canvas size."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "matplotlib.rcParams['figure.figsize'] = (18.0, 18.0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally our plot using ipywidget slider and matplotib. You can move the slider to experiment and see the coloring change. It is also possible to move the slider using arrow keys or to jump to the value by directly editing the number with a double click. The **Visualize Button** will automatically animate the slider for you. The **Extra Delay Box** allows you to set time delay in seconds upto one second for each time step."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAABTgAAAUyCAYAAAAqcpudAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4wLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvpW3flQAAIABJREFUeJzs3U3IpWUZwPHrjDOj8wFlBaUoaYgE\nzoAWhNAQqBOtdFVEFCVRVAs3ESSCtMlVQXtHSSFw0SJUBPEDXQlKBGkGA9GEBSEmLWyc8R3ltFDH\n+Xg/zsdzP8993ffvt3zf51xc6z/Xc85sPp/PAwAAAAAgoV1TLwAAAAAAsCqBEwAAAABIS+AEAAAA\nANISOAEAAACAtAROAAAAACAtgRMAAAAASEvgBAAAAADSEjgBAAAAgLQETgAAAAAgLYETAAAAAEhL\n4AQAAAAA0hI4AQAAAIC0BE4AAAAAIC2BEwAAAABIS+AEAAAAANISOAEAAACAtAROAAAAACAtgRMA\nAAAASEvgBAAAAADSEjgBAAAAgLQETgAAAAAgLYETAAAAAEhL4AQAAAAA0hI4AQAAAIC0BE4AAAAA\nIC2BEwAAAABIS+AEAAAAANISOAEAAACAtAROAAAAACAtgRMAAAAASEvgBAAAAADSEjgBAAAAgLQE\nTgAAAAAgLYETAAAAAEhL4AQAAAAA0hI4AQAAAIC0BE4AAAAAIC2BEwAAAABIS+AEAAAAANISOAEA\nAACAtAROAAAAACAtgRMAAAAASEvgBAAAAADSEjgBAAAAgLQETgAAAAAgLYETAAAAAEhL4AQAAAAA\n0hI4AQAAAIC0BE4AAAAAIC2BEwAAAABIS+AEAAAAANISOAEAAACAtAROAAAAACAtgRMAAAAASEvg\nBAAAAADSEjgBAAAAgLQETgAAAAAgLYETAAAAAEhL4AQAAAAA0hI4AQAAAIC0BE4AAAAAIC2BEwAA\nAABIS+AEAAAAANISOAEAAACAtAROAAAAACAtgRMAAAAASEvgBAAAAADSEjgBAAAAgLQETgAAAAAg\nLYETAAAAAEhL4AQAAAAA0hI4AQAAAIC0BE4AAAAAIC2BEwAAAABIS+AEAAAAANISOAEAAACAtARO\nAAAAACAtgRMAAAAASEvgBAAAAADSEjgBAAAAgLQETgAAAAAgLYETAAAAAEhL4AQAAACgKffdd1/M\nZrOYzWZx/PjxqdehMIETAAAAgGbM5/N48MEHYzabRUTEsWPHJt6I0gROAAAAAJrx1FNPxYkTJ+J7\n3/tefPrTn46HH344NjY2pl6LggROAAAAAJrx4cXmD3/4w/j2t78d//nPf+IPf/jDxFtR0mw+n8+n\nXgIAAAAA1vX666/H1VdfHddee20cP348/vKXv8Thw4fj1ltvjWeffXbq9SjEBScAAAAATfjtb38b\nZ86ciTvvvDMiIg4dOhRf+MIX4rnnnou//e1v0y5HMQInAAAAAOnN5/N44IEHYteuXfHd73737N/v\nvPPOs/+jTV5RBwAAACC9Z599No4ePRpf+9rX4sknnzz79zfffDOuvPLKuPzyy+Of//xn7NmzZ8It\nKcEFJwAAAADp3X///RERZ19P/9AnP/nJuP322+P111+PRx99dILNKM0FJwAAAACpvfHGG3HVVVfF\nxsbGts999atfjaeeemqkrRjL7qkXAAAAAIB1PPzww7GxsRFf/OIX48Ybb9z0mcceeyyeeeaZOHHi\nRFx77bUjb0hJLjgBAAAASO3zn/98HD9+PF588cX40pe+tOkz9957b/zyl7+Me+65J+67776RN6Qk\ngRMAAACAtJ5//vm45ZZb4vDhw/Hyyy9v+dw//vGP+NznPhef+cxn4rXXXovdu73Y3Ao/MgQAAABA\nWseOHYuIiB/84AfbPnfNNdfE0aNH49///nc8/vjjY6zGSFxwAgAAAABpueAEAAAAANISOAEAAACA\ntAROAAAAACAtgRMAAAAASEvgBAAAAADSEjgBAAAAgLQETgAAAAAgLYETAAAAAEhL4AQAAAAA0hI4\nAQAAAIC0BE4AAAAAIC2BEwAAAABIa/fUCwAAAADAEDY2NuLVV1+NV155JU6ePBl79+6N66+/Pm66\n6aY4ePDg1OtRiMAJAAAAQGovvPBC/PrXv44nnngiLr300pjP5/Hee+/Frl274pJLLolTp07FTTfd\nFD//+c/jjjvuiN27JbGWzObz+XzqJQAAAABgWW+88UZ8//vfj+eeey7efvvt2ClzHTx4MK6++ur4\n/e9/HzfccMNIW1KawAkAAABAOn/605/itttui7fffjs2NjYW/txsNovLLrss7r///vjOd75TcEPG\nInACAAAAkMrLL78cR44cibfeemvlGfv27YsHH3wwvvWtbw24GVMQOAEAAABI49SpU3H99dfHv/71\n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\ngEGImwBMQeAEAABgbeImAFMROAEAAFiLuAnAlAROAAAAViZuAjA1gRMAAICViJsA1EDgBAAAYGni\nJgC1EDgBAABYirgJQE0ETgAAABYmbgJQG4ETAACAhYibANRI4AQAAGBH4iYAtRI4AQAA2Ja4CUDN\nBE4AAAC2JG4CUDuBEwAAgE2JmwBkIHACAABwEXETgCwETgAAAM4jbgKQicAJAADAWeImANkInAAA\nAESEuAlATgInAAAA4iYAaQmcAAAAnRM3AchM4AQAAOiYuAlAdgInAABAp8RNAFogcAIAAHRI3ASg\nFQInAABAZ8RNAFoicAIAAHRE3ASgNQInAABAJ8RNAFokcAIAAHRA3ASgVQInAABA48RNAFomcAIA\nADRM3ASgdQInAABAo8RNAHogcAIAADRI3ASgFwInAABAY8RNAHoicAIAADRE3ASgNwInAABAI8RN\nAHokcAIAADRA3ASgVwInAABAcuImAD0TOAEAABITNwHoncAJAACQlLgJAAInAABASuImALxP4AQA\nAEhG3ASAjwicAAAAiYibAHA+gRMAACAJcRMALiZwAgAAJCBuAsDmBE4AAIDKiZsAsDWBEwAAoGLi\nJgBsT+AEAAColLgJADsTOAEAACokbgLAYgROAACAyoibALA4gRMAAKAi4iYALEfgBAAAqIS4CQDL\nEzgBAAAqIG4CwGoETgAAgImJmwCwOoETAABgQuImAKxH4AQAAJiIuAkA6xM4AQAAJiBuAsAwBE4A\nAICRiZsAMByBEwAAYETiJgAMS+AEAAAYibgJAMMTOAEAAEYgbgJAGQInAABAYeImAJQjcAIAABQk\nbgJAWQInAABAIeImAJQncAIAABQgbgLAOAROAACAgYmbADAegRMAAGBA4iYAjEvgBAAAGIi4CQDj\nEzgBAAAGIG4CwDQETgAAgDWJmwAwHYETAABgDeImAExL4AQAAFiRuAkA0xM4AQAAViBuAkAdBE4A\nAIAliZsAUA+BEwAAYAniJgDUReAEAABYkLgJAPUROAEAABYgbgJAnQROAACAHYibAFAvgRMAAGAb\n4iYA1E3gBAAA2IK4CQD1EzgBAAA2IW4CQA4CJwAAwAXETQDIQ+AEAAA4h7gJALkInAAAAB8QNwEg\nH4ETAAAgxE0AyErgBAAAuiduAkBeAicAANA1cRMAchM4AQCAbombAJCfwAkAAHRJ3ASANgicAABA\n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\ntErgBIDkxE0AAKBlAicAJCZuAgAArRM4ASApcRMAAEDgBICUxE0AAIADBE4ASEbcBAAA+I/ACQCJ\niJsAAABHEjgBIAlxEwAAYC2BEwASEDcBAADWJ3ACQOHETQAAgI0JnABQMHETAABgcwInABRK3AQA\nANiawAkABRI3AQAAJiNwAkBhxE0AAIDJCZwAUBBxEwAAYDoCJwAUQtwEAACYnsAJAAUQNwEAAGYj\ncALAyMRNAACA2QmcADAicRMAAGA+AicAjETcBAAAmJ/ACQAjEDcBAAC6IXACwMDETQAAgO4InAAw\nIHETAACgWwInAAxE3AQAAOiewAkAAxA3AQAA+iFwAkDPxE0AAID+CJwA0CNxEwAAoF8CJwD0RNwE\nAADon8AJAD0QNwEAAIYhcAJAx8RNAACA4QicANAhcRMAAGBYAicAdETcBAAAGJ7ACQAdEDcBAADG\nIXACwJzETQAAgPEInAAwB3ETAABgXAInAMxI3AQAABifwAkAMxA3AQAAyiBwAsCUxE0AAIByCJwA\nMAVxEwAAoCwCJwBMSNwEAAAoj8AJABMQNwEAAMokcALAFsRNAACAcgmcALAJcRMAAKBsAicAbEDc\nBAAAKJ/ACQDrEDcBAAByEDgB4CjiJgAAQB4CJwAcRtwEAADIReAEgH+JmwAAAPkInAAQ4iYAAEBW\nAicAzRM3AQAA8hI4AWiauAkAAJCbwAlAs8RNAACA/AROAJokbgIAANRB4ASgOeImAABAPQROAJoi\nbgIAANRF4ASgGeImAABAfQROAJogbgIAANRJ4ASgeuImAABAvQROAKombgIAANRN4ASgWuImAABA\n/QROAKokbgIAALRB4ASgOuImAABAOwROAKoibgIAALRF4ASgGuImAABAewROAKogbgIAALRJ4AQg\nPXETAACgXQInAKmJmwAAAG0TOAFIS9wEAABA4AQgJXETAACACIETgITETQAAAA4SOAFIRdwEAADg\ncAInAGmImwAAABxN4AQgBXETAACA9QicABRP3AQAAGAjAicARRM3AQAA2IzACUCxxE0AAAC2InAC\nUCRxEwAAgEkInAAUR9wEAABgUgInAEURNwEAAJiGwAlAMcRNAAAApiVwAlAEcRMAAIBZCJwAjE7c\nBAAAYFYCJwCjEjcBAACYh8AJwGjETQAAAOYlcAIwCnETAACALgicAAxO3AQAAKArAicAgxI3AQAA\n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\n/Pbbb53PXlpaij/++COOPfbYzmcDAAAA0DYnOImIA7eRX3rppb3MPv/888VNAAAAAHohcHLIPffc\n0/mt5MvLy3H33Xd3OhMAAAAADnKLOofs3bs3Tj311Ni9e3dnM48//vj47rvvYufOnZ3NBAAAAICD\nnODkkG3btsUzzzwTy8vLncxbXl6Oxx9/XNwEAAAAoDdOcHKE1dXVuOGGG+L111+Pv/76a+Y527Zt\ni0suuSTeeeedWFzU0QEAAADoh8DJGnv27Imrr746Pv/885ki57Zt2+Lss8+O999/P0466aQeNgQA\nAACAAxytY43l5eV444034oYbbogTTjhh6s9ec8014iYAAAAAg3CCk0299NJLce+998avv/4av//+\n+4bv27FjRxx33HHx5JNPxq233hoLCwsDbgkAAABAqwROtrR///547bXXYteuXfHuu+/G119/HSsr\nK7G4uBhnnXVWXHHFFXHbbbfF9ddfH8ccc8zY6wIAAADQEIGTmaysrIiZAAAAAIxO4AQAAAAA0vKQ\nIQAAAAAgLYETAAAAAEhL4AQAAAAA0hI4AQAAAIC0BE4AAAAAIC2BEwAAAABIS+AEAAAAANISOAEA\nAACAtAROAAAAACAtgRMAAAAASEvgBAAAAADSEjgBAAAAgLQETgAAAAAgLYETAAAAAEhL4AQAAAAA\n0hI4AQAAAIC0BE4AAAAAIC2BEwAAAABIS+AEAAAAANISOAEAAACAtAROAAAAACAtgRMAAAAASEvg\nBAAAAADSEjgBAAAAgLQETgAAAAAgLYETAAAAAEhL4AQAAAAA0hI4AQAAAIC0BE4AAAAAIC2BEwAA\nAABIS+AEAAAAANISOAEAAACAtAROAAAAACAtgRMAAAAASEvgBAAAAADSEjgBAAAAgLQETgAAAAAg\nLYETAAAAAEhL4AQAAAAA0hI4AQAAAIC0BE4AAAAAIC2BEwAAAABIS+AEAAAAANISOAEAAACAtARO\nAAAAACAtgRMAAAAASEvgBAAAAADSEjgBAAAAgLQETgAAAAAgLYETAAAAAEhL4AQAAAAA0hI4AQAA\nAIC0BE4AAAAAIC2BEwAAAABIS+AEAAAAANISOAEAAACAtAROAAAAACAtgRMAAAAASEvgBAAAAADS\nEjgBAAAAgLQETgAAAAAgLYETAAAAAEhL4AQAAAAA0hI4AQAAAIC0BE4AAAAAIC2BEwAAAABIS+AE\nAAAAANISOAEAAACAtAROAAAAACAtgRMAAAAASEvgBAAAAADSEjgBAAAAgLQETgAAAAAgLYETAAAA\nAEhL4AQAAAAA0hI4AQAAAIC0BE4AAAAAIC2BEwAAAABIS+AEAAAAANISOAEAAACAtAROAAAAACAt\ngRMAAAAASEvgBAAAAADSEjgBAAAAgLQETgAAAAAgLYETAAAAAEhL4AQAAAAA0hI4AQAAAIC0BE4A\nAAAAIC2BEwAAAABIS+AEAAAAANISOAEAAACAtAROAAAAACAtgRMAAAAASEvgBAAAAADSEjgBAAAA\ngLQETgAAAAAgLYETAAAAAEhL4AQAAAAA0hI4AQAAAIC0BE4AAAAAIC2BEwAAAABIS+AEAAAAANIS\nOAEAAACAtAROAAAAACAtgRMAAAAASEvgBAAAAADSEjgBAAAAgLQETgAAAAAgLYETAAAAAEhL4AQA\nAAAA0hI4AQAAAIC0BE4AAAAAIC2BEwAAAABIS+AEAAAAANISOAEAAACAtAROAAAAACAtgRMAAAAA\nSEvgBAAAAADSEjgBAAAAgLQETgAAAAAgLYETAAAAAEhL4AQAAAAA0vo/E5n8oUH60/sAAAAASUVO\nRK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x25de3c934e0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "The installed widget Javascript is the wrong version. It must satisfy the semver range ~2.1.4.\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "0a993a2fa8864b4d984f41784f8e1e8f"
      }
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import ipywidgets as widgets\n",
    "from IPython.display import display\n",
    "\n",
    "iteration_slider = widgets.IntSlider(min=0, max=len(coloring_problem1.assignment_history)-1, step=1, value=0)\n",
    "w=widgets.interactive(step_func,iteration=iteration_slider)\n",
    "display(w)\n",
    "\n",
    "visualize_callback = make_visualize(iteration_slider)\n",
    "\n",
    "visualize_button = widgets.ToggleButton(description = \"Visualize\", value = False)\n",
    "time_select = widgets.ToggleButtons(description='Extra Delay:',options=['0', '0.1', '0.2', '0.5', '0.7', '1.0'])\n",
    "\n",
    "a = widgets.interactive(visualize_callback, Visualize = visualize_button, time_step=time_select)\n",
    "display(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## N-QUEENS VISUALIZATION\n",
    "\n",
    "Just like the Graph Coloring Problem we will start with defining a few helper functions to help us visualize the assignments as they evolve over time. The **make_plot_board_step_function** behaves similar to the **make_update_step_function** introduced earlier. It initializes a chess board in the form of a 2D grid with alternating 0s and 1s. This is used by **plot_board_step** function which draws the board using matplotlib and adds queens to it. This function also calls the **label_queen_conflicts** which modifies the grid placing 3 in positions in a position where there is a conflict."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def label_queen_conflicts(assignment,grid):\n",
    "    ''' Mark grid with queens that are under conflict. '''\n",
    "    for col, row in assignment.items(): # check each queen for conflict\n",
    "        row_conflicts = {temp_col:temp_row for temp_col,temp_row in assignment.items() \n",
    "                         if temp_row == row and temp_col != col}\n",
    "        up_conflicts = {temp_col:temp_row for temp_col,temp_row in assignment.items() \n",
    "                        if temp_row+temp_col == row+col and temp_col != col}\n",
    "        down_conflicts = {temp_col:temp_row for temp_col,temp_row in assignment.items() \n",
    "                          if temp_row-temp_col == row-col and temp_col != col}\n",
    "        \n",
    "        # Now marking the grid.\n",
    "        for col, row in row_conflicts.items():\n",
    "                grid[col][row] = 3\n",
    "        for col, row in up_conflicts.items():\n",
    "                grid[col][row] = 3\n",
    "        for col, row in down_conflicts.items():\n",
    "                grid[col][row] = 3\n",
    "\n",
    "    return grid\n",
    "\n",
    "def make_plot_board_step_function(instru_csp):\n",
    "    '''ipywidgets interactive function supports\n",
    "       single parameter as input. This function\n",
    "       creates and return such a function by taking\n",
    "       in input other parameters.\n",
    "    '''\n",
    "    n = len(instru_csp.variables)\n",
    "    \n",
    "    \n",
    "    def plot_board_step(iteration):\n",
    "        ''' Add Queens to the Board.'''\n",
    "        data = instru_csp.assignment_history[iteration]\n",
    "        \n",
    "        grid = [[(col+row+1)%2 for col in range(n)] for row in range(n)]\n",
    "        grid = label_queen_conflicts(data, grid) # Update grid with conflict labels.\n",
    "        \n",
    "        # color map of fixed colors\n",
    "        cmap = matplotlib.colors.ListedColormap(['white','lightsteelblue','red'])\n",
    "        bounds=[0,1,2,3] # 0 for white 1 for black 2 onwards for conflict labels (red).\n",
    "        norm = matplotlib.colors.BoundaryNorm(bounds, cmap.N)\n",
    "        \n",
    "        fig = plt.imshow(grid, interpolation='nearest', cmap = cmap,norm=norm)\n",
    "\n",
    "        plt.axis('off')\n",
    "        fig.axes.get_xaxis().set_visible(False)\n",
    "        fig.axes.get_yaxis().set_visible(False)\n",
    "\n",
    "        # Place the Queens Unicode Symbol\n",
    "        for col, row in data.items():\n",
    "            fig.axes.text(row, col, u\"\\u265B\", va='center', ha='center', family='Dejavu Sans', fontsize=32)\n",
    "        plt.show()\n",
    "    \n",
    "    return plot_board_step"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let us visualize a solution obtained via backtracking. We use of the previosuly defined **make_instru** function for keeping a history of steps."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "twelve_queens_csp = NQueensCSP(12)\n",
    "backtracking_instru_queen = make_instru(twelve_queens_csp)\n",
    "result = backtracking_search(backtracking_instru_queen)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "backtrack_queen_step = make_plot_board_step_function(backtracking_instru_queen) # Step Function for Widgets"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now finally we set some matplotlib parameters to adjust how our plot will look. The font is necessary because the Black Queen Unicode character is not a part of all fonts. You can move the slider to experiment and observe the how queens are assigned. It is also possible to move the slider using arrow keys or to jump to the value by directly editing the number with a double click.The **Visualize Button** will automatically animate the slider for you. The **Extra Delay Box** allows you to set time delay in seconds upto one second for each time step.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAcgAAAHICAYAAADKoXrqAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4wLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvpW3flQAADTBJREFUeJzt3V+M5XdZx/HnzA4BafdPgbrtdnfb\nKSwNLCHbSFx0Sov86QIKI2CIGMoFNKgX2iAmXqi94cYQo0kT1JBYkQgqpcAUMESxIeBo223Zbrvt\nlrbplG2LVWO0u7MzO9vZ+Xkxs1Mn+8n5s5lfzzG+XjebnHx39slz8873nN+e6TRNUwDAemPDHgAA\nRpFAAkAgkAAQCCQABAIJAIFAAkAgkAAQCCQABAIJAMH4IIenZ2ZH6mt3piYnhj3COtMzs8Me4Rx2\n1J399GZH3dlPb6O2o6rq9HPIDRIAAoEEgOBFD+Szzxyre/7pO7UwP/di/9MA0LeBPoMc1H/+x7M1\nP3eidk3sqaqqHz81W7/1sffWqYX5eu3r99VnPvfVqqo6vbhYx2YfrV0Te+qlL31ZmyMBQF9au0Ee\nuvt79YlfurZ+44YDddsXPltVK4E8tTBfVVVP/+jxOrO0VM+fXqxPffx99ds3TtWnPv6+Or242NZI\nANC31gJ5+N6ZOnNmqaqq7p25s6qq3vSzb6sP3vDrVVX16Vu+VJvGx+vZZ47VU08+VlVVTz/5eP34\n6dF7AguA/382NJBN09TiqYWqqnr3+z9Se/ftr6qq9//KJ9bO7Lz8NVVVtXv1bdedV7ym9u7bX2Ob\nNtXPvesDdfmVV1VVuUkCMFQbFsh/f/aZ+rUPvbU+fOCNddsXPlvbd+yqT9/yxRobW/9PLJw8sfLn\n6lutnU6nLrhwc7352gN10+/9YZ1amK/f+dUP1i+/c2/9yWd+d6PGA4CBbFgg7/n+P9S//etTtXzm\nTH37a19c+eFjY3XBhVvqyP13r51bmD9ZVbX2WeTy8nI9fPhgXbJjV1VVPfLgffXDhw7V8vJy/f0d\nf13zq0EFgBfThgXy6v3X1rZXvKqqqq6f+vDa65u3bKsjh84N5OJqIJ98/GjNnXiutl+6Esg9r99X\nF2/fUWNjY3XdgV+sl1+weaNGBIC+bVggL9t9Zd369bvqp37mrfXqq96w9vrmrRfVsSd+WHPHn6uq\nqvnV//949i3WI4fuqqqq7ZetBLJplmvuxPH6gz/9Sn3y9/9oo8YDgIFs6EM6Y2Nj9ebrDtRX/+rP\n1l67cMvWlbdRHzhYVf/7LdaVP8/eLrfv2F1VVXf8zZ/Xlm2vqNfu3beRowHAQDb8v3n89OQ76pEH\n76tHHryvqqo2b7moql4I4dlv0Dm1MF9N09TDhw/W2KZNdfH2HTV3/Ln61u1/Wde8/ec3eiwAGMiG\nB3LrRa+sq/ZeXbev3iI3b91WVVUPrT6os3DyhUDOrn7++MqLL6nx8ZfUHV++teZPztU1b/uFjR4L\nAAbSyhcF7H/L9XXvP99Zx554dO0GOfv40Zo/eWLdU6xnP3+8ZMfumjtxvL75lc/XzstfXRN7XtfG\nWADQt3YCee07q2ma+tqXPlcXbtlaVVXLZ87Uw4cPrvsM8uzbrj956c76xpdvrfm5E3XN290eARi+\nVgJ56c4ratcVe+r73/nG2jfrVFUduf+eF55inT9ZRw+vPLizecu2+uZtn6+qqre8471tjAQAA2nt\nu1jfcPX+Wlp6vu78u9vXXnvo0N1rD+k88uAP6sTx/66qqoMz/1gn547Xxdt31GW7r2xrJADoW2u/\n7mrT+MqPPvtF5FVVTzz6UDXNclVVHbn/rrXXnzn2xOrfeUlb4wDAQFr9fZCve+Ob6j0fuKGvs0tL\nS/W3f3FLm+MAQN9aDeTS86fr+HP/1dfZs78aCwBGQauBfOzoA/XY0Qf6Pn/JZZe3OA0A9K+1h3QA\n4P8ygQSAoNW3WK+7fqo+efMf93X29OJi/eZH39XmOADQt1YD+S/f/XYdvnem7/Mv+4kLWpwGAPrX\nWiBvvOnmuvGmm9v68QDQKp9BAkAgkAAQCCQABAIJAIFAAkAgkAAQCCQABAIJAEGnaZpBzg90uG3T\nM7PDHmGdqcmJYY9wDjvqzn56s6Pu7Ke3EdxRp59zbpAAEAgkAAQCCQCBQAJAIJAAEAgkAAQCCQCB\nQAJAIJAAEAgkAAQCCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAAEAgkAAQC\nCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAAEAgkAAQCCQDB+CCHp2dm25rj\nvExNTgx7hHVGbT9VdtSL/fRmR93ZT2+jtqN+uUECQCCQABAIJAAEAgkAgUACQCCQABAIJAAEAgkA\ngUACQCCQABAIJAAEAgkAgUACQCCQABAIJAAEAgkAgUACQCCQABAIJAAEAgkAgUACQCCQABAIJAAE\nAgkAgUACQCCQABAIJAAEAgkAgUACQCCQABAIJAAEAgkAgUACQCCQABAIJAAEAgkAQadpmkHOD3S4\nbdMzs8MeYZ2pyYlhj3AOO+rOfnqzo+7sp7cR3FGnn3NukAAQCCQABAIJAIFAAkAgkAAQCCQABAIJ\nAIFAAkAgkAAQCCQABAIJAIFAAkAgkAAQCCQABAIJAIFAAkAgkAAQCCQABAIJAIFAAkAgkAAQCCQA\nBAIJAIFAAkAgkAAQCCQABAIJAIFAAkAgkAAQCCQABAIJAIFAAkAgkAAQCCQABAIJAMH4IIenZ2bb\nmuO8TE1ODHuEdUZtP1V21Iv99GZH3dlPb6O2o365QQJAIJAAEAgkAAQCCQCBQAJAIJAAEAgkAAQC\nCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAAEAgk\nAAQCCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAAEAgkAASdpmkGOT/Q4bZN\nz8wOe4R1piYnhj3COeyoO/vpzY66s5/eRnBHnX7OuUECQCCQABAIJAAEAgkAgUACQCCQABAIJAAE\nAgkAgUACQCCQABAIJAAEAgkAgUACQCCQABAIJAAEAgkAgUACQCCQABAIJAAEAgkAgUACQCCQABAI\nJAAEAgkAgUACQCCQABAIJAAEAgkAgUACQCCQABAIJAAEAgkAgUACQCCQABAIJAAE44Mcnp6ZbWuO\n8zI1OTHsEdYZtf1U2VEv9tObHXVnP72N2o765QYJAIFAAkAgkAAQCCQABAIJAIFAAkAgkAAQCCQA\nBAIJAIFAAkAgkAAQCCQABAIJAIFAAkAgkAAQCCQABAIJAIFAAkAgkAAQCCQABAIJAIFAAkAgkAAQ\nCCQABAIJAIFAAkAgkAAQCCQABAIJAIFAAkAgkAAQCCQABAIJAIFAAkAgkAAQCCQABJ2maQY5P9Dh\ntk3PzA57hHWmJieGPcI57Kg7++nNjrqzn95GcEedfs65QQJAIJAAEAgkAAQCCQCBQAJAIJAAEAgk\nAAQCCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAA\nEAgkAAQCCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAAEAgkAATjgxyenplt\na47zMjU5MewR1hm1/VTZUS/205sddWc/vY3ajvrlBgkAgUACQCCQABAIJAAEAgkAgUACQCCQABAI\nJAAEAgkAgUACQCCQABAIJAAEAgkAgUACQCCQABAIJAAEAgkAgUACQCCQABAIJAAEAgkAgUACQCCQ\nABAIJAAEAgkAgUACQCCQABAIJAAEAgkAgUACQCCQABAIJAAEAgkAgUACQCCQABB0mqYZ5PxAh9s2\nPTM77BHWmZqcGPYI57Cj7uynNzvqzn56G8Eddfo55wYJAIFAAkAgkAAQCCQABAIJAIFAAkAgkAAQ\nCCQABAIJAIFAAkAgkAAQCCQABAIJAIFAAkAgkAAQCCQABAIJAIFAAkAgkAAQCCQABAIJAIFAAkAg\nkAAQCCQABAIJAIFAAkAgkAAQCCQABAIJAIFAAkAgkAAQCCQABAIJAIFAAkAgkAAQjA9yeHpmtq05\nzsvU5MSwR1hn1PZTZUe92E9vdtSd/fQ2ajvqlxskAAQCCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAA\nEAgkAAQCCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAAEAgkAAQCCQCBQAJA\nIJAAEAgkAAQCCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAAEAgkAAQCCQCBQAJAIJAAEHSaphnk/ECH\n2zY9MzvsEdaZmpwY9gjnsKPu7Kc3O+rOfnobwR11+jnnBgkAgUACQCCQABAIJAAEAgkAgUACQCCQ\nABAIJAAEAgkAgUACQCCQABAIJAAEAgkAgUACQCCQABAIJAAEAgkAgUACQCCQABAIJAAEAgkAgUAC\nQCCQABAIJAAEAgkAgUACQCCQABAIJAAEAgkAgUACQCCQABAIJAAEAgkAgUACQCCQABB0mqYZ9gwA\nMHLcIAEgEEgACAQSAAKBBIBAIAEgEEgACAQSAAKBBIBAIAEgEEgACP4HKIKNpa18Bp8AAAAASUVO\nRK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x25de3e004e0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "The installed widget Javascript is the wrong version. It must satisfy the semver range ~2.1.4.\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "516a8bb7f00d48a0b208c3f69a6f887d"
      }
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "matplotlib.rcParams['figure.figsize'] = (8.0, 8.0)\n",
    "matplotlib.rcParams['font.family'].append(u'Dejavu Sans')\n",
    "\n",
    "iteration_slider = widgets.IntSlider(min=0, max=len(backtracking_instru_queen.assignment_history)-1, step=0, value=0)\n",
    "w=widgets.interactive(backtrack_queen_step,iteration=iteration_slider)\n",
    "display(w)\n",
    "\n",
    "visualize_callback = make_visualize(iteration_slider)\n",
    "\n",
    "visualize_button = widgets.ToggleButton(description = \"Visualize\", value = False)\n",
    "time_select = widgets.ToggleButtons(description='Extra Delay:',options=['0', '0.1', '0.2', '0.5', '0.7', '1.0'])\n",
    "\n",
    "a = widgets.interactive(visualize_callback, Visualize = visualize_button, time_step=time_select)\n",
    "display(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let us finally repeat the above steps for **min_conflicts** solution."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "conflicts_instru_queen = make_instru(twelve_queens_csp)\n",
    "result = min_conflicts(conflicts_instru_queen)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "conflicts_step = make_plot_board_step_function(conflicts_instru_queen)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The visualization has same features as the above. But here it also highlights the conflicts by labeling the conflicted queens with a red background."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\nTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x25de3e00f28>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "The installed widget Javascript is the wrong version. It must satisfy the semver range ~2.1.4.\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "29f5dba226b3492383ad768b54876588"
      }
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "iteration_slider = widgets.IntSlider(min=0, max=len(conflicts_instru_queen.assignment_history)-1, step=0, value=0)\n",
    "w=widgets.interactive(conflicts_step,iteration=iteration_slider)\n",
    "display(w)\n",
    "\n",
    "visualize_callback = make_visualize(iteration_slider)\n",
    "\n",
    "visualize_button = widgets.ToggleButton(description = \"Visualize\", value = False)\n",
    "time_select = widgets.ToggleButtons(description='Extra Delay:',options=['0', '0.1', '0.2', '0.5', '0.7', '1.0'])\n",
    "\n",
    "a = widgets.interactive(visualize_callback, Visualize = visualize_button, time_step=time_select)\n",
    "display(a)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
