{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# cadCAD Template: Robot and the Marbles - Part 4\n",
    "\n",
    "![](images/Overview.jpeg)\n",
    "![](images/Mech1.jpeg)\n",
    "\n",
    "\n",
    "## Non-determinism\n",
    "Non-deterministic systems exhibit different behaviors on different runs for the same input. The order of heads and tails in a series of 3 coin tosses, for example, is non deterministic. \n",
    "\n",
    "Our robots and marbles system is currently modelled as a deterministic system. Meaning that every time we run the simulation: none of the robots act on timestep 1; robot 1 acts on timestep 2; robot 2 acts on timestep 3; an so on. \n",
    "\n",
    "If however we were to define that at every timestep each robot would act with a probability P, then we would have a non-deterministic (probabilistic) system. Let's make the following changes to our system.\n",
    "* Robot 1: instead of acting once every two timesteps, there's a 50% chance it will act in any given timestep\n",
    "* Robot 2: instead of acting once every three timesteps, there's a 33.33% chance it will act in any given timestep"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# import libraries\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib \n",
    "from cadCAD.engine import ExecutionMode, ExecutionContext, Executor\n",
    "import config\n",
    "from cadCAD import configs\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "%matplotlib inline\n",
    "\n",
    "exec_mode = ExecutionMode()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "single_proc: [<cadCAD.configuration.Configuration object at 0x10ae23710>]\n",
      "[<cadCAD.configuration.Configuration object at 0x10ae23710>]\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>box_A</th>\n",
       "      <th>box_B</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>run</th>\n",
       "      <th>timestep</th>\n",
       "      <th>substep</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"11\" valign=\"top\">1</th>\n",
       "      <th>0</th>\n",
       "      <th>0</th>\n",
       "      <td>10</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <th>1</th>\n",
       "      <td>10</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <th>1</th>\n",
       "      <td>9</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <th>1</th>\n",
       "      <td>9</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <th>1</th>\n",
       "      <td>8</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <th>1</th>\n",
       "      <td>6</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <th>1</th>\n",
       "      <td>5</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <th>1</th>\n",
       "      <td>5</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <th>1</th>\n",
       "      <td>5</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <th>1</th>\n",
       "      <td>5</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <th>1</th>\n",
       "      <td>5</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                      box_A  box_B\n",
       "run timestep substep              \n",
       "1   0        0           10      0\n",
       "    1        1           10      0\n",
       "    2        1            9      1\n",
       "    3        1            9      1\n",
       "    4        1            8      2\n",
       "    5        1            6      4\n",
       "    6        1            5      5\n",
       "    7        1            5      5\n",
       "    8        1            5      5\n",
       "    9        1            5      5\n",
       "    10       1            5      5"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Run Cad^2\n",
    "\n",
    "first_config = configs # only contains config1\n",
    "single_proc_ctx = ExecutionContext(context=exec_mode.single_proc)\n",
    "run = Executor(exec_context=single_proc_ctx, configs=first_config)\n",
    "\n",
    "raw_result, tensor_field = run.execute()\n",
    "df = pd.DataFrame(raw_result)\n",
    "df.set_index(['run', 'timestep', 'substep'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 15296 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "df.plot('timestep', ['box_A', 'box_B'], grid=True, \n",
    "        colormap = 'RdYlGn',\n",
    "        xticks=list(df['timestep'].drop_duplicates()), \n",
    "        yticks=list(range(1+(df['box_A']+df['box_B']).max())));"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Since it is random, lets run it again:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "single_proc: [<cadCAD.configuration.Configuration object at 0x10ae23710>]\n",
      "[<cadCAD.configuration.Configuration object at 0x10ae23710>]\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 15312 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Run Cad^2\n",
    "\n",
    "first_config = configs # only contains config1\n",
    "single_proc_ctx = ExecutionContext(context=exec_mode.single_proc)\n",
    "run = Executor(exec_context=single_proc_ctx, configs=first_config)\n",
    "\n",
    "raw_result, tensor_field = run.execute()\n",
    "df = pd.DataFrame(raw_result)\n",
    "df.plot('timestep', ['box_A', 'box_B'], grid=True, \n",
    "        colormap = 'RdYlGn',\n",
    "        xticks=list(df['timestep'].drop_duplicates()), \n",
    "        yticks=list(range(1+(df['box_A']+df['box_B']).max())));"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Run 50 Monte Carlo Runs\n",
    "In order to take advantage of cadCAD's Monte Carlo simulation features, we should modify the configuration file so as to define the number of times we want the same simulation to be run. This is done in the N key of the sim_config dictionary."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "single_proc: [<cadCAD.configuration.Configuration object at 0x10ae23710>, <cadCAD.configuration.Configuration object at 0x10b8cd0f0>]\n",
      "[<cadCAD.configuration.Configuration object at 0x10ae23710>, <cadCAD.configuration.Configuration object at 0x10b8cd0f0>]\n"
     ]
    }
   ],
   "source": [
    "import config2\n",
    "first_config = configs # only contains config1\n",
    "single_proc_ctx = ExecutionContext(context=exec_mode.single_proc)\n",
    "run = Executor(exec_context=single_proc_ctx, configs=first_config)\n",
    "\n",
    "raw_result, tensor_field = run.execute()\n",
    "df2 = pd.DataFrame(raw_result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>box_A</th>\n",
       "      <th>box_B</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>run</th>\n",
       "      <th>timestep</th>\n",
       "      <th>substep</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"5\" valign=\"top\">1</th>\n",
       "      <th>0</th>\n",
       "      <th>0</th>\n",
       "      <td>10</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <th>1</th>\n",
       "      <td>8</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <th>1</th>\n",
       "      <td>6</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <th>1</th>\n",
       "      <td>5</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <th>1</th>\n",
       "      <td>5</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <th>...</th>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"5\" valign=\"top\">50</th>\n",
       "      <th>6</th>\n",
       "      <th>1</th>\n",
       "      <td>5</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <th>1</th>\n",
       "      <td>5</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <th>1</th>\n",
       "      <td>5</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <th>1</th>\n",
       "      <td>5</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <th>1</th>\n",
       "      <td>5</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>550 rows × 2 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                      box_A  box_B\n",
       "run timestep substep              \n",
       "1   0        0           10      0\n",
       "    1        1            8      2\n",
       "    2        1            6      4\n",
       "    3        1            5      5\n",
       "    4        1            5      5\n",
       "...                     ...    ...\n",
       "50  6        1            5      5\n",
       "    7        1            5      5\n",
       "    8        1            5      5\n",
       "    9        1            5      5\n",
       "    10       1            5      5\n",
       "\n",
       "[550 rows x 2 columns]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from IPython.display import display\n",
    "tmp_rows = pd.options.display.max_rows\n",
    "pd.options.display.max_rows = 10\n",
    "display(df2.set_index(['run', 'timestep', 'substep']))\n",
    "pd.options.display.max_rows = tmp_rows"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Plotting two of those runs allows us to see the different behaviors over time."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 14528 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 15164 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "df2[df2['run']==1].plot('timestep', ['box_A', 'box_B'], grid=True,\n",
    "                          xticks=list(df['timestep'].drop_duplicates()), \n",
    "                          yticks=list(range(11)),\n",
    "                          colormap = 'RdYlGn');\n",
    "df2[df2['run']==9].plot('timestep', ['box_A', 'box_B'], grid=True,\n",
    "                            xticks=list(df['timestep'].drop_duplicates()), \n",
    "                            yticks=list(range(11)),\n",
    "                            colormap = 'RdYlGn');"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If we plot all those runs onto a single chart, we can see every possible trajectory for the number of marbles in each box."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 67924 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "ax = None\n",
    "for i in range(50):\n",
    "    ax = df2[df2['run']==i+1].plot('timestep', ['box_A', 'box_B'],\n",
    "                                     grid=True,\n",
    "                                     xticks=list(df['timestep'].drop_duplicates()), \n",
    "                                     yticks=list(range(1+max(df2['box_A'].max(),df2['box_B'].max()))),\n",
    "                                     legend = (ax == None),\n",
    "                                     colormap = 'RdYlGn',\n",
    "                                     ax = ax\n",
    "                                  )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For some analyses, it might make sense to look at the data in aggregate. Take the median for example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.axes._subplots.AxesSubplot at 0x10bb37828>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 16108 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "dfmc_median = df2.groupby(['timestep', 'substep']).median().reset_index()\n",
    "dfmc_median.plot('timestep', ['box_A', 'box_B'], \n",
    "                 grid=True,\n",
    "                 xticks=list(dfmc_median['timestep'].drop_duplicates()), \n",
    "                 yticks=list(range(int(1+max(dfmc_median['box_A'].max(),dfmc_median['box_B'].max())))),\n",
    "                 colormap = 'RdYlGn'\n",
    "                )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Or look at edge cases"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 20160 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "max_final_A = df2[df2['timestep']==df2['timestep'].max()]['box_A'].max()\n",
    "# max_final_A\n",
    "slow_runs = df2[(df2['timestep']==df2['timestep'].max()) & \n",
    "         (df2['box_A']==max_final_A)]['run']\n",
    "slow_runs = list(slow_runs)\n",
    "slow_runs\n",
    "\n",
    "ax = None\n",
    "for i in slow_runs:\n",
    "    ax = df2[df2['run']==i].plot('timestep', ['box_A', 'box_B'],\n",
    "                                     grid=True,\n",
    "                                     xticks=list(df2['timestep'].drop_duplicates()), \n",
    "                                     yticks=list(range(1+max(df2['box_A'].max(),df2['box_B'].max()))),\n",
    "                                     legend = (ax == None),\n",
    "                                     colormap = 'RdYlGn',\n",
    "                                     ax = ax\n",
    "                                  )"
   ]
  }
 ],
 "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.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
