Last active
February 27, 2020 11:07
-
-
Save markusbkoch/3abb127ae8444d4be845f0ad688cbd1d to your computer and use it in GitHub Desktop.
This file contains 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": "code", | |
"execution_count": 1, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"%%capture\n", | |
"from cadCAD.configuration import append_configs\n", | |
"from cadCAD.configuration.utils import config_sim\n", | |
"import networkx as nx\n", | |
"\n", | |
"# create a base networkx object\n", | |
"base_network = nx.DiGraph()\n", | |
"base_network.add_node('i')\n", | |
"base_network.add_node('j')\n", | |
"\n", | |
"# base genesis state\n", | |
"genesis = {\n", | |
" 'network': base_network,\n", | |
" 'a': 0,\n", | |
" 'b': 0\n", | |
"}\n", | |
"\n", | |
"# params to be swept\n", | |
"params = {\n", | |
" 'node_param_i': [1, 2, 3],\n", | |
" 'node_param_j': [4, 5, 6],\n", | |
" 'b': [100, 200, 300],\n", | |
" 'r': [1, 2, 3]\n", | |
"}\n", | |
"\n", | |
"# mockup state update function for state variable a\n", | |
"def func_a(params, substep, state_history, prev_state, policy_input):\n", | |
" key = 'a'\n", | |
" value = 0\n", | |
" value += prev_state['network'].nodes['i']['param']\n", | |
" value += prev_state['network'].nodes['j']['param']\n", | |
" return (key, value)\n", | |
"\n", | |
"# mockup state update function for state variable a\n", | |
"def func_b(params, substep, state_history, prev_state, policy_input):\n", | |
" key = 'b'\n", | |
" value = prev_state['b']*params['r']\n", | |
" return (key, value)\n", | |
"\n", | |
"# partial state update blocks\n", | |
"psub = [\n", | |
" {\n", | |
" 'policies': {\n", | |
" },\n", | |
" 'variables': {\n", | |
" 'a': func_a,\n", | |
" 'b': func_b,\n", | |
" }\n", | |
" }\n", | |
"]\n", | |
"\n", | |
"# create sim_config\n", | |
"sim_config = config_sim (\n", | |
" {\n", | |
" 'N': 2, \n", | |
" 'T': range(1), # number of timesteps\n", | |
" 'M': params,\n", | |
" }\n", | |
")\n", | |
"# append configs\n", | |
"append_configs(\n", | |
" sim_configs=sim_config,\n", | |
" initial_state=genesis,\n", | |
" partial_state_update_blocks=psub\n", | |
")\n", | |
"\n", | |
"from copy import deepcopy\n", | |
"from cadCAD import configs" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"At this point, `configs` contains a list of `Configuration` objects..." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"[<cadCAD.configuration.Configuration at 0x11aec7fd0>,\n", | |
" <cadCAD.configuration.Configuration at 0x1117b39d0>,\n", | |
" <cadCAD.configuration.Configuration at 0x11af6bc90>]" | |
] | |
}, | |
"execution_count": 2, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"configs" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"...each with its own set of parameters..." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"[{'N': 2,\n", | |
" 'T': range(0, 1),\n", | |
" 'M': {'node_param_i': 1, 'node_param_j': 4, 'b': 100, 'r': 1}},\n", | |
" {'N': 2,\n", | |
" 'T': range(0, 1),\n", | |
" 'M': {'node_param_i': 2, 'node_param_j': 5, 'b': 200, 'r': 2}},\n", | |
" {'N': 2,\n", | |
" 'T': range(0, 1),\n", | |
" 'M': {'node_param_i': 3, 'node_param_j': 6, 'b': 300, 'r': 3}}]" | |
] | |
}, | |
"execution_count": 3, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"[c.sim_config for c in configs]" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"...but they all share the same initial state" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"See how all 3 network variables point to the same instance of DiGraph (same address in memory)\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"[{'network': <networkx.classes.digraph.DiGraph at 0x1117b3950>,\n", | |
" 'a': 0,\n", | |
" 'b': 0},\n", | |
" {'network': <networkx.classes.digraph.DiGraph at 0x1117b3950>,\n", | |
" 'a': 0,\n", | |
" 'b': 0},\n", | |
" {'network': <networkx.classes.digraph.DiGraph at 0x1117b3950>,\n", | |
" 'a': 0,\n", | |
" 'b': 0}]" | |
] | |
}, | |
"execution_count": 4, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"print(\"See how all 3 network variables point to the same instance of DiGraph (same address in memory)\")\n", | |
"[c.initial_state for c in configs]" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The following script updates the `initial_state` of each `Configuration` object so that the value of the state variable `b` is set to the value of the parameter `b` in the parameter dictionary" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"[{'network': <networkx.classes.digraph.DiGraph at 0x1117b35d0>,\n", | |
" 'a': 0,\n", | |
" 'b': 100},\n", | |
" {'network': <networkx.classes.digraph.DiGraph at 0x1117b3690>,\n", | |
" 'a': 0,\n", | |
" 'b': 200},\n", | |
" {'network': <networkx.classes.digraph.DiGraph at 0x1117b3710>,\n", | |
" 'a': 0,\n", | |
" 'b': 300}]" | |
] | |
}, | |
"execution_count": 5, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"for c in configs: # for each configuration object\n", | |
" c.initial_state = deepcopy(c.initial_state) # make a deepcopy of the initial state dict (it's shared across configs by default)\n", | |
" for k in c.initial_state: # for each state variable\n", | |
" if k in c.sim_config['M']: # if there is a param with the same name in the params dict\n", | |
" c.initial_state[k] = c.sim_config['M'][k] # assign the param value to the initial value of the state variable\n", | |
"\n", | |
"# check result\n", | |
"[c.initial_state for c in configs]" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The following script updates the networkx object in the `initial_state` of each `Configuration` object so that they point to their own unique instance of a networkx object, modified according to the `init_network` function we defined above" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"See how each network now points to a different object (different address in memory)\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"[{'network': <networkx.classes.digraph.DiGraph at 0x111706690>,\n", | |
" 'a': 0,\n", | |
" 'b': 100},\n", | |
" {'network': <networkx.classes.digraph.DiGraph at 0x1227ac490>,\n", | |
" 'a': 0,\n", | |
" 'b': 200},\n", | |
" {'network': <networkx.classes.digraph.DiGraph at 0x1228831d0>,\n", | |
" 'a': 0,\n", | |
" 'b': 300}]" | |
] | |
}, | |
"execution_count": 6, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# network initializer:\n", | |
"# given a networkx object and a cadCAD params dictionary, \n", | |
"# modify attributes of the networkx object\n", | |
"def init_network(n, params):\n", | |
" n.nodes['i']['param'] = params['node_param_i']\n", | |
" n.nodes['j']['param'] = params['node_param_j']\n", | |
" return n\n", | |
"\n", | |
"for c in configs: # for each configuration object\n", | |
" c.initial_state = deepcopy(c.initial_state) # make a deepcopy of the initial state dict (it's shared across configs by default)\n", | |
" c.initial_state['network'] = init_network(c.initial_state['network'], c.sim_config['M'])\n", | |
"\n", | |
"# check result\n", | |
"print(\"See how each network now points to a different object (different address in memory)\")\n", | |
"[c.initial_state for c in configs]" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Now just run the simulation and look at the results" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from cadCAD.engine import ExecutionMode, ExecutionContext, Executor\n", | |
"import pandas as pd\n", | |
"\n", | |
"def run(drop_midsteps=True):\n", | |
" exec_mode = ExecutionMode()\n", | |
" multi_proc_ctx = ExecutionContext(context=exec_mode.multi_proc)\n", | |
" run = Executor(exec_context=multi_proc_ctx, configs=configs)\n", | |
" results = pd.DataFrame()\n", | |
" i = 0\n", | |
" for raw_result, _ in run.execute():\n", | |
" params = configs[i].sim_config['M']\n", | |
" result_record = pd.DataFrame.from_records([tuple([i for i in params.values()])], columns=list(params.keys()))\n", | |
"\n", | |
" df = pd.DataFrame(raw_result)\n", | |
" # keep only last substep of each timestep\n", | |
" if drop_midsteps:\n", | |
" max_substep = max(df.substep)\n", | |
" is_droppable = (df.substep!=max_substep)&(df.substep!=0)\n", | |
" df.drop(df[is_droppable].index, inplace=True)\n", | |
"\n", | |
" result_record['dataset'] = [df]\n", | |
" results = results.append(result_record)\n", | |
" i += 1\n", | |
" return results.reset_index()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"%%capture\n", | |
"experiments = run()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 31, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Experiment 0\n", | |
"-------------\n", | |
"Parameters:\n", | |
" - node_param_i = 1\n", | |
" - node_param_j = 4\n", | |
" - b = 100\n", | |
" - r = 1\n", | |
"Dataset:\n", | |
" run timestep a b\n", | |
"0 1 0 0 100\n", | |
"1 1 1 5 100\n", | |
"2 2 0 0 100\n", | |
"3 2 1 5 100\n", | |
"=======================================================\n", | |
"Experiment 1\n", | |
"-------------\n", | |
"Parameters:\n", | |
" - node_param_i = 2\n", | |
" - node_param_j = 5\n", | |
" - b = 200\n", | |
" - r = 2\n", | |
"Dataset:\n", | |
" run timestep a b\n", | |
"0 1 0 0 200\n", | |
"1 1 1 7 400\n", | |
"2 2 0 0 200\n", | |
"3 2 1 7 400\n", | |
"=======================================================\n", | |
"Experiment 2\n", | |
"-------------\n", | |
"Parameters:\n", | |
" - node_param_i = 3\n", | |
" - node_param_j = 6\n", | |
" - b = 300\n", | |
" - r = 3\n", | |
"Dataset:\n", | |
" run timestep a b\n", | |
"0 1 0 0 300\n", | |
"1 1 1 9 900\n", | |
"2 2 0 0 300\n", | |
"3 2 1 9 900\n", | |
"=======================================================\n" | |
] | |
} | |
], | |
"source": [ | |
"for i,r in experiments.iterrows():\n", | |
" print(f'Experiment {i}')\n", | |
" print('-------------')\n", | |
" print('Parameters:')\n", | |
" for k in list(params.keys()):\n", | |
" print(f' - {k} = {r[k]}')\n", | |
" print('Dataset:')\n", | |
" print(r.dataset[['run','timestep','a','b']])\n", | |
" print('=======================================================')" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"As intended, the initial value of `b` is different for each one of the experiments (same value as defined in the parameters dictionary that we swept).\n", | |
"\n", | |
"Also, each one of the experiments was executed based on a different initial `network`, as we can infer from the different values of `a` in each experiment (remember `a` is computed from attributes of the underlying `network`)" | |
] | |
} | |
], | |
"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.5" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment