Last active
December 3, 2016 01:59
-
-
Save dadaromeo/3f37ffb883e9c6b0793e684e7bf0c0a1 to your computer and use it in GitHub Desktop.
An attempt to understand the behaviour of Mesa's BatchRunner API.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Mesa BatchRunner's behaviour" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"I was trying to reproduce in Mesa the *Credit Risk* case study in [Agent-Based Modeling and Simulation](http://link.springer.com/book/10.1057/9781137453648) and noticed that the bacth running results were different from the ones output by the running model in the browser. After trying to debug the code for days without a success, I decided to explore the implementation of `BatchRunner`." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"from itertools import product\n", | |
"\n", | |
"import pandas as pd\n", | |
"from mesa.model import Model\n", | |
"from mesa.agent import Agent\n", | |
"from mesa.time import RandomActivation\n", | |
"from mesa.batchrunner import BatchRunner" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"class Bar(Agent):\n", | |
" \n", | |
" gain = 0\n", | |
" \n", | |
" def __init__(self, unique_id, model, option, amount):\n", | |
" super().__init__(unique_id, model)\n", | |
" mpg = {\"inc\": self.inc, \"dec\": self.dec}\n", | |
" self.option = mpg[option]\n", | |
" self.amount = amount\n", | |
" \n", | |
" def step(self):\n", | |
" self.option()\n", | |
" \n", | |
" def inc(self):\n", | |
" self.model.total += self.amount\n", | |
" self.gain += self.amount\n", | |
" \n", | |
" def dec(self):\n", | |
" self.model.total -= self.amount\n", | |
" self.gain -= self.amount" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"class Foo(Model):\n", | |
" \n", | |
" total = 0\n", | |
" \n", | |
" def __init__(self, seed=42, option=\"inc\", amount=1):\n", | |
" super().__init__(seed=seed)\n", | |
" self.schedule = RandomActivation(self)\n", | |
" agent = Bar(1, self, option, amount)\n", | |
" self.schedule.add(agent)\n", | |
" other = Bar(2, self, option, amount)\n", | |
" self.schedule.add(other)\n", | |
" \n", | |
" def step(self):\n", | |
" self.schedule.step()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The way I understood the batch running scheme is that, you pass your model along with a range of parameter and it runs it for all combinations of parameters and stores the results. Like in the following:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"param_vals = {\"option\": [\"dec\", \"inc\"], \"amount\": [1,2]}\n", | |
"model_rep = {\"total\": lambda m: m.total}\n", | |
"agent_rep = {\"gain\": lambda a: a.gain}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"100%|██████████| 20/20 [00:00<00:00, 81.47it/s]\n" | |
] | |
} | |
], | |
"source": [ | |
"batch = BatchRunner(Foo, param_vals, iterations=5, model_reporters=model_rep, agent_reporters=agent_rep)\n", | |
"\n", | |
"batch.run_all()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>Run</th>\n", | |
" <th>amount</th>\n", | |
" <th>option</th>\n", | |
" <th>total</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>4</td>\n", | |
" <td>1</td>\n", | |
" <td>dec</td>\n", | |
" <td>-2000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>13</td>\n", | |
" <td>1</td>\n", | |
" <td>inc</td>\n", | |
" <td>2000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2</th>\n", | |
" <td>3</td>\n", | |
" <td>1</td>\n", | |
" <td>dec</td>\n", | |
" <td>-2000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>3</th>\n", | |
" <td>9</td>\n", | |
" <td>2</td>\n", | |
" <td>dec</td>\n", | |
" <td>-4000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>4</th>\n", | |
" <td>5</td>\n", | |
" <td>2</td>\n", | |
" <td>dec</td>\n", | |
" <td>-4000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>5</th>\n", | |
" <td>6</td>\n", | |
" <td>2</td>\n", | |
" <td>dec</td>\n", | |
" <td>-4000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>6</th>\n", | |
" <td>15</td>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>4000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>7</th>\n", | |
" <td>2</td>\n", | |
" <td>1</td>\n", | |
" <td>dec</td>\n", | |
" <td>-2000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>8</th>\n", | |
" <td>17</td>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>4000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>9</th>\n", | |
" <td>14</td>\n", | |
" <td>1</td>\n", | |
" <td>inc</td>\n", | |
" <td>2000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>10</th>\n", | |
" <td>7</td>\n", | |
" <td>2</td>\n", | |
" <td>dec</td>\n", | |
" <td>-4000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>11</th>\n", | |
" <td>10</td>\n", | |
" <td>1</td>\n", | |
" <td>inc</td>\n", | |
" <td>2000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>12</th>\n", | |
" <td>16</td>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>4000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>13</th>\n", | |
" <td>19</td>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>4000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>14</th>\n", | |
" <td>1</td>\n", | |
" <td>1</td>\n", | |
" <td>dec</td>\n", | |
" <td>-2000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>15</th>\n", | |
" <td>11</td>\n", | |
" <td>1</td>\n", | |
" <td>inc</td>\n", | |
" <td>2000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>16</th>\n", | |
" <td>12</td>\n", | |
" <td>1</td>\n", | |
" <td>inc</td>\n", | |
" <td>2000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>17</th>\n", | |
" <td>0</td>\n", | |
" <td>1</td>\n", | |
" <td>dec</td>\n", | |
" <td>-2000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>18</th>\n", | |
" <td>8</td>\n", | |
" <td>2</td>\n", | |
" <td>dec</td>\n", | |
" <td>-4000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>19</th>\n", | |
" <td>18</td>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>4000</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" Run amount option total\n", | |
"0 4 1 dec -2000\n", | |
"1 13 1 inc 2000\n", | |
"2 3 1 dec -2000\n", | |
"3 9 2 dec -4000\n", | |
"4 5 2 dec -4000\n", | |
"5 6 2 dec -4000\n", | |
"6 15 2 inc 4000\n", | |
"7 2 1 dec -2000\n", | |
"8 17 2 inc 4000\n", | |
"9 14 1 inc 2000\n", | |
"10 7 2 dec -4000\n", | |
"11 10 1 inc 2000\n", | |
"12 16 2 inc 4000\n", | |
"13 19 2 inc 4000\n", | |
"14 1 1 dec -2000\n", | |
"15 11 1 inc 2000\n", | |
"16 12 1 inc 2000\n", | |
"17 0 1 dec -2000\n", | |
"18 8 2 dec -4000\n", | |
"19 18 2 inc 4000" | |
] | |
}, | |
"execution_count": 6, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"batch.get_model_vars_dataframe()\n" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### A problem?\n", | |
"\n", | |
"But as you can see in the dataframe above, the result is a bit strange (at least, for me). The model is suppose to increment or decrement an amount to/from the total at each step. We only ran for 5 iterations and the decremented/incremented amount was 1 or 2. How did we get such big numbers? The answer lies in the `BatchRunner`'s code." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"class BatchRunner:\n", | |
" \n", | |
" #... everything else\n", | |
" \n", | |
" def run_all(self):\n", | |
" #... everything else\n", | |
" for param_values in list(product(*param_ranges)):\n", | |
" kwargs = dict(zip(params, param_values))\n", | |
" for _ in range(self.iterations):\n", | |
" model = self.model_cls(**kwargs)\n", | |
" self.run_model(model)\n", | |
" #... everything else\n", | |
" \n", | |
" def run_model(self, model):\n", | |
" \"\"\" Run a model object to completion, or until reaching max steps.\n", | |
"\n", | |
" If your model runs in a non-standard way, this is the method to modify\n", | |
" in your subclass.\n", | |
"\n", | |
" \"\"\"\n", | |
" while model.running and model.schedule.steps < self.max_steps:\n", | |
" model.step()\n", | |
" \n", | |
" #... everything else" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Is there a problem? First of all, the model is instanciated in the for loop on the number of iterations which confuses me because I thought, the `iterations` was the running time of the model for each combination of model's parameters. The second thing that confuses me is the call of `run_model` method (also in the same for loop) that runs the model at least `max_steps` times in this loop. We can see now where the big numbers in the above result were coming from. `max_steps` default value is 1000 and I didn't change it, meaning that at the first iteration, the model ran 1000 times. But what happened during the other iterations?" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### A solution?\n", | |
"\n", | |
"The way I see the batch running implementation is as follow. First, we instanciate the model out of the iterations loop. Second, we get rid of `run_model` method and `max_steps` parameter." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"class AltBatchRunner:\n", | |
" \"\"\"Alternative batch runner\"\"\"\n", | |
" \n", | |
" def __init__(self, model_cls,\n", | |
" parameter_values,\n", | |
" iterations=10,\n", | |
" model_reporters=None,\n", | |
" agent_reporters=None, \n", | |
" display_progress=True,\n", | |
" ):\n", | |
" self.model_cls = model_cls\n", | |
" self.parameter_values = {param: self.make_iterable(vals)\n", | |
" for param, vals in parameter_values.items()}\n", | |
" self.iterations = iterations\n", | |
"\n", | |
" self.model_reporters = model_reporters\n", | |
"\n", | |
" if self.model_reporters:\n", | |
" self.model_vars = {}\n", | |
" \n", | |
" def run_all(self):\n", | |
" param_names = self.parameter_values.keys()\n", | |
" param_ranges = self.parameter_values.values()\n", | |
" \n", | |
" for param_values in product(*param_ranges):\n", | |
" kwargs = dict(zip(param_names, param_values))\n", | |
" \n", | |
" model = self.model_cls(**kwargs)\n", | |
" for i in range(self.iterations):\n", | |
" if model.running:\n", | |
" model.step()\n", | |
" else:\n", | |
" break\n", | |
" \n", | |
" # Collect and store results:\n", | |
" if self.model_reporters:\n", | |
" key = tuple(list(param_values) + [i])\n", | |
" self.model_vars[key] = self.collect_model_vars(model)\n", | |
" \n", | |
" def collect_model_vars(self, model):\n", | |
" \"\"\" Run reporters and collect model-level variables. \"\"\"\n", | |
" model_vars = {}\n", | |
" for var, reporter in self.model_reporters.items():\n", | |
" model_vars[var] = reporter(model)\n", | |
" return model_vars\n", | |
" \n", | |
" def get_model_vars_dataframe(self):\n", | |
" \"\"\" Generate a pandas DataFrame from the model-level variables collected.\n", | |
"\n", | |
" \"\"\"\n", | |
" index_col_names = list(self.parameter_values.keys())\n", | |
" index_col_names.append(\"Run\")\n", | |
" records = []\n", | |
" for key, val in self.model_vars.items():\n", | |
" record = dict(zip(index_col_names, key))\n", | |
" for k, v in val.items():\n", | |
" record[k] = v\n", | |
" records.append(record)\n", | |
" return pd.DataFrame(records)\n", | |
" \n", | |
" @staticmethod\n", | |
" def make_iterable(val):\n", | |
" \"\"\" Helper method to ensure a value is a non-string iterable. \"\"\"\n", | |
" if hasattr(val, \"__iter__\") and not isinstance(val, str):\n", | |
" return val\n", | |
" else:\n", | |
" return [val]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"alt = AltBatchRunner(Foo, param_vals, iterations=5, model_reporters=model_rep)\n", | |
"\n", | |
"alt.run_all()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>Run</th>\n", | |
" <th>amount</th>\n", | |
" <th>option</th>\n", | |
" <th>total</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>4</td>\n", | |
" <td>1</td>\n", | |
" <td>dec</td>\n", | |
" <td>-10</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>2</td>\n", | |
" <td>1</td>\n", | |
" <td>dec</td>\n", | |
" <td>-6</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2</th>\n", | |
" <td>3</td>\n", | |
" <td>1</td>\n", | |
" <td>dec</td>\n", | |
" <td>-8</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>3</th>\n", | |
" <td>1</td>\n", | |
" <td>1</td>\n", | |
" <td>dec</td>\n", | |
" <td>-4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>4</th>\n", | |
" <td>4</td>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>20</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>5</th>\n", | |
" <td>2</td>\n", | |
" <td>1</td>\n", | |
" <td>inc</td>\n", | |
" <td>6</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>6</th>\n", | |
" <td>3</td>\n", | |
" <td>2</td>\n", | |
" <td>dec</td>\n", | |
" <td>-16</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>7</th>\n", | |
" <td>3</td>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>16</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>8</th>\n", | |
" <td>1</td>\n", | |
" <td>2</td>\n", | |
" <td>dec</td>\n", | |
" <td>-8</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>9</th>\n", | |
" <td>3</td>\n", | |
" <td>1</td>\n", | |
" <td>inc</td>\n", | |
" <td>8</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>10</th>\n", | |
" <td>0</td>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>11</th>\n", | |
" <td>4</td>\n", | |
" <td>1</td>\n", | |
" <td>inc</td>\n", | |
" <td>10</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>12</th>\n", | |
" <td>2</td>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>12</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>13</th>\n", | |
" <td>0</td>\n", | |
" <td>2</td>\n", | |
" <td>dec</td>\n", | |
" <td>-4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>14</th>\n", | |
" <td>0</td>\n", | |
" <td>1</td>\n", | |
" <td>inc</td>\n", | |
" <td>2</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>15</th>\n", | |
" <td>2</td>\n", | |
" <td>2</td>\n", | |
" <td>dec</td>\n", | |
" <td>-12</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>16</th>\n", | |
" <td>4</td>\n", | |
" <td>2</td>\n", | |
" <td>dec</td>\n", | |
" <td>-20</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>17</th>\n", | |
" <td>1</td>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>8</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>18</th>\n", | |
" <td>0</td>\n", | |
" <td>1</td>\n", | |
" <td>dec</td>\n", | |
" <td>-2</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>19</th>\n", | |
" <td>1</td>\n", | |
" <td>1</td>\n", | |
" <td>inc</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" Run amount option total\n", | |
"0 4 1 dec -10\n", | |
"1 2 1 dec -6\n", | |
"2 3 1 dec -8\n", | |
"3 1 1 dec -4\n", | |
"4 4 2 inc 20\n", | |
"5 2 1 inc 6\n", | |
"6 3 2 dec -16\n", | |
"7 3 2 inc 16\n", | |
"8 1 2 dec -8\n", | |
"9 3 1 inc 8\n", | |
"10 0 2 inc 4\n", | |
"11 4 1 inc 10\n", | |
"12 2 2 inc 12\n", | |
"13 0 2 dec -4\n", | |
"14 0 1 inc 2\n", | |
"15 2 2 dec -12\n", | |
"16 4 2 dec -20\n", | |
"17 1 2 inc 8\n", | |
"18 0 1 dec -2\n", | |
"19 1 1 inc 4" | |
] | |
}, | |
"execution_count": 11, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"alt.get_model_vars_dataframe()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"We can see that the `total` variable is incremented or decremented properly." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Final solution?\n", | |
"\n", | |
"This is a suggested more *clean* version of the batch runner api if of course, there was a problem." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 12, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"class CleanBatchRunner:\n", | |
" \n", | |
" def __init__(self, model_cls, params, run=10, model_reporters=None, agent_reporters=None, display_progress=True):\n", | |
" self.model_cls = model_cls\n", | |
" self.time = run\n", | |
" self.params = {name: self._make_iterable(val)\n", | |
" for name, val in params.items()}\n", | |
" self.model_reporters = model_reporters\n", | |
" self.agent_reporters = agent_reporters\n", | |
" \n", | |
" def run_all(self):\n", | |
" names = self.params.keys()\n", | |
" ranges = self.params.values()\n", | |
" \n", | |
" if self.model_reporters:\n", | |
" self.model_vars = {name:[] for name in names}\n", | |
" self.model_vars[\"run\"] = []\n", | |
" for name in self.model_reporters:\n", | |
" self.model_vars[name] = []\n", | |
" \n", | |
" if self.agent_reporters:\n", | |
" self.agent_vars = {name:[] for name in names}\n", | |
" self.agent_vars[\"run\"] = []\n", | |
" self.agent_vars[\"agent_id\"] = []\n", | |
" for name in self.agent_reporters:\n", | |
" self.agent_vars[name] = []\n", | |
" \n", | |
" for values in product(*ranges):\n", | |
" kwargs = dict(zip(names, values))\n", | |
" model = self.model_cls(**kwargs)\n", | |
" \n", | |
" for t in range(self.time):\n", | |
" if model.running:\n", | |
" model.step()\n", | |
" else:\n", | |
" break\n", | |
" \n", | |
" if self.model_reporters:\n", | |
" self.model_vars[\"run\"].append(t)\n", | |
" for k, v in kwargs.items():\n", | |
" self.model_vars[k].append(v)\n", | |
" self._collect_model_vars(model)\n", | |
" \n", | |
" if self.agent_reporters:\n", | |
" for agent in model.schedule.agents:\n", | |
" self.agent_vars[\"run\"].append(t)\n", | |
" self.agent_vars[\"agent_id\"].append(agent.unique_id)\n", | |
" for k,v in kwargs.items():\n", | |
" self.agent_vars[k].append(v)\n", | |
" self._collect_agent_vars(agent)\n", | |
" \n", | |
" def _collect_agent_vars(self, agent):\n", | |
" for name, reporter in self.agent_reporters.items():\n", | |
" self.agent_vars[name].append(reporter(agent))\n", | |
"\n", | |
" def _collect_model_vars(self, model):\n", | |
" for name, reporter in self.model_reporters.items():\n", | |
" self.model_vars[name].append(reporter(model))\n", | |
" \n", | |
" def get_agent_vars_dataframe(self):\n", | |
" return pd.DataFrame(self.agent_vars)\n", | |
" \n", | |
" def get_model_vars_dataframe(self):\n", | |
" return pd.DataFrame(self.model_vars)\n", | |
" \n", | |
" @staticmethod\n", | |
" def _make_iterable(val):\n", | |
" \"\"\" Helper method to ensure a value is a non-string iterable. \"\"\"\n", | |
" if hasattr(val, \"__iter__\") and not isinstance(val, str):\n", | |
" return val\n", | |
" else:\n", | |
" return [val]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 13, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"clean = CleanBatchRunner(Foo, param_vals, run=5, model_reporters=model_rep, agent_reporters=agent_rep)\n", | |
"\n", | |
"clean.run_all()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 14, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>amount</th>\n", | |
" <th>option</th>\n", | |
" <th>run</th>\n", | |
" <th>total</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>1</td>\n", | |
" <td>dec</td>\n", | |
" <td>0</td>\n", | |
" <td>-2</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>1</td>\n", | |
" <td>dec</td>\n", | |
" <td>1</td>\n", | |
" <td>-4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2</th>\n", | |
" <td>1</td>\n", | |
" <td>dec</td>\n", | |
" <td>2</td>\n", | |
" <td>-6</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>3</th>\n", | |
" <td>1</td>\n", | |
" <td>dec</td>\n", | |
" <td>3</td>\n", | |
" <td>-8</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>4</th>\n", | |
" <td>1</td>\n", | |
" <td>dec</td>\n", | |
" <td>4</td>\n", | |
" <td>-10</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>5</th>\n", | |
" <td>2</td>\n", | |
" <td>dec</td>\n", | |
" <td>0</td>\n", | |
" <td>-4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>6</th>\n", | |
" <td>2</td>\n", | |
" <td>dec</td>\n", | |
" <td>1</td>\n", | |
" <td>-8</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>7</th>\n", | |
" <td>2</td>\n", | |
" <td>dec</td>\n", | |
" <td>2</td>\n", | |
" <td>-12</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>8</th>\n", | |
" <td>2</td>\n", | |
" <td>dec</td>\n", | |
" <td>3</td>\n", | |
" <td>-16</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>9</th>\n", | |
" <td>2</td>\n", | |
" <td>dec</td>\n", | |
" <td>4</td>\n", | |
" <td>-20</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>10</th>\n", | |
" <td>1</td>\n", | |
" <td>inc</td>\n", | |
" <td>0</td>\n", | |
" <td>2</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>11</th>\n", | |
" <td>1</td>\n", | |
" <td>inc</td>\n", | |
" <td>1</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>12</th>\n", | |
" <td>1</td>\n", | |
" <td>inc</td>\n", | |
" <td>2</td>\n", | |
" <td>6</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>13</th>\n", | |
" <td>1</td>\n", | |
" <td>inc</td>\n", | |
" <td>3</td>\n", | |
" <td>8</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>14</th>\n", | |
" <td>1</td>\n", | |
" <td>inc</td>\n", | |
" <td>4</td>\n", | |
" <td>10</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>15</th>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>0</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>16</th>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>1</td>\n", | |
" <td>8</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>17</th>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>2</td>\n", | |
" <td>12</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>18</th>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>3</td>\n", | |
" <td>16</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>19</th>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>4</td>\n", | |
" <td>20</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" amount option run total\n", | |
"0 1 dec 0 -2\n", | |
"1 1 dec 1 -4\n", | |
"2 1 dec 2 -6\n", | |
"3 1 dec 3 -8\n", | |
"4 1 dec 4 -10\n", | |
"5 2 dec 0 -4\n", | |
"6 2 dec 1 -8\n", | |
"7 2 dec 2 -12\n", | |
"8 2 dec 3 -16\n", | |
"9 2 dec 4 -20\n", | |
"10 1 inc 0 2\n", | |
"11 1 inc 1 4\n", | |
"12 1 inc 2 6\n", | |
"13 1 inc 3 8\n", | |
"14 1 inc 4 10\n", | |
"15 2 inc 0 4\n", | |
"16 2 inc 1 8\n", | |
"17 2 inc 2 12\n", | |
"18 2 inc 3 16\n", | |
"19 2 inc 4 20" | |
] | |
}, | |
"execution_count": 14, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"clean.get_model_vars_dataframe()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 15, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>agent_id</th>\n", | |
" <th>amount</th>\n", | |
" <th>gain</th>\n", | |
" <th>option</th>\n", | |
" <th>run</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>2</td>\n", | |
" <td>1</td>\n", | |
" <td>-1</td>\n", | |
" <td>dec</td>\n", | |
" <td>0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>1</td>\n", | |
" <td>1</td>\n", | |
" <td>-1</td>\n", | |
" <td>dec</td>\n", | |
" <td>0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2</th>\n", | |
" <td>1</td>\n", | |
" <td>1</td>\n", | |
" <td>-2</td>\n", | |
" <td>dec</td>\n", | |
" <td>1</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>3</th>\n", | |
" <td>2</td>\n", | |
" <td>1</td>\n", | |
" <td>-2</td>\n", | |
" <td>dec</td>\n", | |
" <td>1</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>4</th>\n", | |
" <td>1</td>\n", | |
" <td>1</td>\n", | |
" <td>-3</td>\n", | |
" <td>dec</td>\n", | |
" <td>2</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>5</th>\n", | |
" <td>2</td>\n", | |
" <td>1</td>\n", | |
" <td>-3</td>\n", | |
" <td>dec</td>\n", | |
" <td>2</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>6</th>\n", | |
" <td>2</td>\n", | |
" <td>1</td>\n", | |
" <td>-4</td>\n", | |
" <td>dec</td>\n", | |
" <td>3</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>7</th>\n", | |
" <td>1</td>\n", | |
" <td>1</td>\n", | |
" <td>-4</td>\n", | |
" <td>dec</td>\n", | |
" <td>3</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>8</th>\n", | |
" <td>1</td>\n", | |
" <td>1</td>\n", | |
" <td>-5</td>\n", | |
" <td>dec</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>9</th>\n", | |
" <td>2</td>\n", | |
" <td>1</td>\n", | |
" <td>-5</td>\n", | |
" <td>dec</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>10</th>\n", | |
" <td>2</td>\n", | |
" <td>2</td>\n", | |
" <td>-2</td>\n", | |
" <td>dec</td>\n", | |
" <td>0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>11</th>\n", | |
" <td>1</td>\n", | |
" <td>2</td>\n", | |
" <td>-2</td>\n", | |
" <td>dec</td>\n", | |
" <td>0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>12</th>\n", | |
" <td>1</td>\n", | |
" <td>2</td>\n", | |
" <td>-4</td>\n", | |
" <td>dec</td>\n", | |
" <td>1</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>13</th>\n", | |
" <td>2</td>\n", | |
" <td>2</td>\n", | |
" <td>-4</td>\n", | |
" <td>dec</td>\n", | |
" <td>1</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>14</th>\n", | |
" <td>1</td>\n", | |
" <td>2</td>\n", | |
" <td>-6</td>\n", | |
" <td>dec</td>\n", | |
" <td>2</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>15</th>\n", | |
" <td>2</td>\n", | |
" <td>2</td>\n", | |
" <td>-6</td>\n", | |
" <td>dec</td>\n", | |
" <td>2</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>16</th>\n", | |
" <td>2</td>\n", | |
" <td>2</td>\n", | |
" <td>-8</td>\n", | |
" <td>dec</td>\n", | |
" <td>3</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>17</th>\n", | |
" <td>1</td>\n", | |
" <td>2</td>\n", | |
" <td>-8</td>\n", | |
" <td>dec</td>\n", | |
" <td>3</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>18</th>\n", | |
" <td>1</td>\n", | |
" <td>2</td>\n", | |
" <td>-10</td>\n", | |
" <td>dec</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>19</th>\n", | |
" <td>2</td>\n", | |
" <td>2</td>\n", | |
" <td>-10</td>\n", | |
" <td>dec</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>20</th>\n", | |
" <td>2</td>\n", | |
" <td>1</td>\n", | |
" <td>1</td>\n", | |
" <td>inc</td>\n", | |
" <td>0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>21</th>\n", | |
" <td>1</td>\n", | |
" <td>1</td>\n", | |
" <td>1</td>\n", | |
" <td>inc</td>\n", | |
" <td>0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>22</th>\n", | |
" <td>1</td>\n", | |
" <td>1</td>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>1</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>23</th>\n", | |
" <td>2</td>\n", | |
" <td>1</td>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>1</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>24</th>\n", | |
" <td>1</td>\n", | |
" <td>1</td>\n", | |
" <td>3</td>\n", | |
" <td>inc</td>\n", | |
" <td>2</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>25</th>\n", | |
" <td>2</td>\n", | |
" <td>1</td>\n", | |
" <td>3</td>\n", | |
" <td>inc</td>\n", | |
" <td>2</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>26</th>\n", | |
" <td>2</td>\n", | |
" <td>1</td>\n", | |
" <td>4</td>\n", | |
" <td>inc</td>\n", | |
" <td>3</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>27</th>\n", | |
" <td>1</td>\n", | |
" <td>1</td>\n", | |
" <td>4</td>\n", | |
" <td>inc</td>\n", | |
" <td>3</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>28</th>\n", | |
" <td>1</td>\n", | |
" <td>1</td>\n", | |
" <td>5</td>\n", | |
" <td>inc</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>29</th>\n", | |
" <td>2</td>\n", | |
" <td>1</td>\n", | |
" <td>5</td>\n", | |
" <td>inc</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>30</th>\n", | |
" <td>2</td>\n", | |
" <td>2</td>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>31</th>\n", | |
" <td>1</td>\n", | |
" <td>2</td>\n", | |
" <td>2</td>\n", | |
" <td>inc</td>\n", | |
" <td>0</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>32</th>\n", | |
" <td>1</td>\n", | |
" <td>2</td>\n", | |
" <td>4</td>\n", | |
" <td>inc</td>\n", | |
" <td>1</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>33</th>\n", | |
" <td>2</td>\n", | |
" <td>2</td>\n", | |
" <td>4</td>\n", | |
" <td>inc</td>\n", | |
" <td>1</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>34</th>\n", | |
" <td>1</td>\n", | |
" <td>2</td>\n", | |
" <td>6</td>\n", | |
" <td>inc</td>\n", | |
" <td>2</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>35</th>\n", | |
" <td>2</td>\n", | |
" <td>2</td>\n", | |
" <td>6</td>\n", | |
" <td>inc</td>\n", | |
" <td>2</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>36</th>\n", | |
" <td>2</td>\n", | |
" <td>2</td>\n", | |
" <td>8</td>\n", | |
" <td>inc</td>\n", | |
" <td>3</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>37</th>\n", | |
" <td>1</td>\n", | |
" <td>2</td>\n", | |
" <td>8</td>\n", | |
" <td>inc</td>\n", | |
" <td>3</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>38</th>\n", | |
" <td>1</td>\n", | |
" <td>2</td>\n", | |
" <td>10</td>\n", | |
" <td>inc</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>39</th>\n", | |
" <td>2</td>\n", | |
" <td>2</td>\n", | |
" <td>10</td>\n", | |
" <td>inc</td>\n", | |
" <td>4</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" agent_id amount gain option run\n", | |
"0 2 1 -1 dec 0\n", | |
"1 1 1 -1 dec 0\n", | |
"2 1 1 -2 dec 1\n", | |
"3 2 1 -2 dec 1\n", | |
"4 1 1 -3 dec 2\n", | |
"5 2 1 -3 dec 2\n", | |
"6 2 1 -4 dec 3\n", | |
"7 1 1 -4 dec 3\n", | |
"8 1 1 -5 dec 4\n", | |
"9 2 1 -5 dec 4\n", | |
"10 2 2 -2 dec 0\n", | |
"11 1 2 -2 dec 0\n", | |
"12 1 2 -4 dec 1\n", | |
"13 2 2 -4 dec 1\n", | |
"14 1 2 -6 dec 2\n", | |
"15 2 2 -6 dec 2\n", | |
"16 2 2 -8 dec 3\n", | |
"17 1 2 -8 dec 3\n", | |
"18 1 2 -10 dec 4\n", | |
"19 2 2 -10 dec 4\n", | |
"20 2 1 1 inc 0\n", | |
"21 1 1 1 inc 0\n", | |
"22 1 1 2 inc 1\n", | |
"23 2 1 2 inc 1\n", | |
"24 1 1 3 inc 2\n", | |
"25 2 1 3 inc 2\n", | |
"26 2 1 4 inc 3\n", | |
"27 1 1 4 inc 3\n", | |
"28 1 1 5 inc 4\n", | |
"29 2 1 5 inc 4\n", | |
"30 2 2 2 inc 0\n", | |
"31 1 2 2 inc 0\n", | |
"32 1 2 4 inc 1\n", | |
"33 2 2 4 inc 1\n", | |
"34 1 2 6 inc 2\n", | |
"35 2 2 6 inc 2\n", | |
"36 2 2 8 inc 3\n", | |
"37 1 2 8 inc 3\n", | |
"38 1 2 10 inc 4\n", | |
"39 2 2 10 inc 4" | |
] | |
}, | |
"execution_count": 15, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"clean.get_agent_vars_dataframe()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"anaconda-cloud": {}, | |
"kernelspec": { | |
"display_name": "Python [default]", | |
"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.5.2" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 1 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment