528 lines
69 KiB
Plaintext
528 lines
69 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# SIMCad Demos: Simple Tracker"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Configuration\n",
|
|
"We begin with a simple configuration file that only defines a single exogenous state: a sinusoidal `signal`"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# SimCAD related imports\n",
|
|
"from datetime import timedelta\n",
|
|
"from SimCAD.configuration import Configuration\n",
|
|
"from SimCAD.configuration.utils import exo_update_per_ts, ep_time_step\n",
|
|
"\n",
|
|
"# System specific imports\n",
|
|
"import numpy as np\n",
|
|
"\n",
|
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
|
|
"# List of all the states in the system and their initial conditions\n",
|
|
"# In the current version of SimCAD, `timestamp` is mandatory\n",
|
|
"# The `signal` state is the exogenous state that we'll model\n",
|
|
"initial_conditions = {\n",
|
|
" 'signal': float(0),\n",
|
|
" 'timestamp': '2018-01-01 00:00:00'\n",
|
|
"}\n",
|
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
|
|
"# Definitions of functions that update the exogenous states\n",
|
|
"# Functions must return a tuple containing the name of the state being updated and its new value\n",
|
|
"# For now, ignore all the arguments passed to the function, except `s`, \n",
|
|
"# which contains a copy of the current values of all the states\n",
|
|
"\n",
|
|
"# Definition of the function that updates the `timestamp` state\n",
|
|
"# In the current version of SimCAD, `timestamp` is a mandatory state\n",
|
|
"ts_format = '%Y-%m-%d %H:%M:%S'\n",
|
|
"t_delta = timedelta(days=0, minutes=0, seconds=1) # In this example, a time_step is defined as 1 second. The user can change this\n",
|
|
"def time_model(step, sL, s, _input):\n",
|
|
" y = 'timestamp'\n",
|
|
" x = ep_time_step(s, dt_str=s['timestamp'], fromat_str=ts_format, _timedelta=t_delta)\n",
|
|
" return (y, x)\n",
|
|
"\n",
|
|
"# Definition of the function that updates the `signal` state\n",
|
|
"# It's a simple sine wave with amplitude 1 and period 50 time_steps\n",
|
|
"period = 50\n",
|
|
"def sinusoid(step, sL, s, _input):\n",
|
|
" y = 'signal'\n",
|
|
" x = s['time_step']\n",
|
|
" x = np.sin(x * 2 * np.pi / period)\n",
|
|
" return (y, x)\n",
|
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
|
|
"\n",
|
|
"\n",
|
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
|
|
"# This maps the exogenous states to their corresponding updating functions\n",
|
|
"exogenous_states = exo_update_per_ts(\n",
|
|
" {\n",
|
|
" 'signal': sinusoid, # The `signal` state is updated by the `sinusoid` function defined above\n",
|
|
" 'timestamp': time_model # The `timestamp` state is updated by the `time_model` function defined above\n",
|
|
" }\n",
|
|
")\n",
|
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
|
|
"\n",
|
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
|
|
"# Settings of general simulation parameters, unrelated to the system itself\n",
|
|
"# `T` is the number of discrete units of time the simulation will run for\n",
|
|
"# `N` is the number of times the simulation will be run\n",
|
|
"# In this example, we'll run the simulation once (N=1) and its duration will be of 50 discrete units of time\n",
|
|
"sim_config = {\n",
|
|
" 'T': range(50),\n",
|
|
" 'N': 1\n",
|
|
"}\n",
|
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
|
|
"\n",
|
|
"# We'll ignore these components of the configuration for now\n",
|
|
"env_processes = {}\n",
|
|
"seeds = {}\n",
|
|
"mechanisms = {}\n",
|
|
"\n",
|
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
|
|
"# The configurations above are then packaged into a `Configuration` object\n",
|
|
"config = Configuration(sim_config=sim_config,\n",
|
|
" state_dict=initial_conditions,\n",
|
|
" seed=seeds,\n",
|
|
" exogenous_states=exogenous_states,\n",
|
|
" env_processes=env_processes,\n",
|
|
" mechanisms=mechanisms)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Running the engine\n",
|
|
"We are now ready to run the engine with the configuration defined above. Instantiate an ExecutionMode, an ExecutionContext and an Executor objects, passing the Configuration object to the latter. Then run the `main()` method of the Executor object, which returns the results of the experiment in the first element of a tuple."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"single_proc: [<SimCAD.configuration.Configuration object at 0x1059c0e80>]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"from SimCAD.engine import ExecutionMode, ExecutionContext, Executor\n",
|
|
"exec_mode = ExecutionMode()\n",
|
|
"exec_context = ExecutionContext(exec_mode.single_proc)\n",
|
|
"executor = Executor(exec_context, [config]) # Pass the configuration object inside an array\n",
|
|
"raw_result, tensor = executor.main() # The `main()` method returns a tuple; its first elements contains the raw results"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Analyzing the results\n",
|
|
"We can now convert the raw results into a DataFrame for analysis"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"metadata": {
|
|
"scrolled": false
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"count 5.100000e+01\n",
|
|
"mean -2.493893e-17\n",
|
|
"std 7.071068e-01\n",
|
|
"min -9.980267e-01\n",
|
|
"25% -6.845471e-01\n",
|
|
"50% 0.000000e+00\n",
|
|
"75% 6.845471e-01\n",
|
|
"max 9.980267e-01\n",
|
|
"Name: signal, dtype: float64"
|
|
]
|
|
},
|
|
"execution_count": 3,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "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\n",
|
|
"text/plain": [
|
|
"<Figure size 432x288 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {
|
|
"needs_background": "light"
|
|
},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"%matplotlib inline\n",
|
|
"import pandas as pd\n",
|
|
"df = pd.DataFrame(raw_result)\n",
|
|
"df.plot('timestamp', 'signal')\n",
|
|
"df['signal'].describe()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Modelling Internal States, Mechanisms and User Behavior\n",
|
|
"Let's now suppose we want to design a system with which an agent will interact with the intent of replicating the value of the previously defined `signal` in an internal state. The agent can read the current value of the `signal` and the current value of the internal state. And they can add or subtract any amount from the internal state."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"First we redefine the `initial_conditions` object in order to add the internal state, which will call `follow`"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
|
|
"# List of all the states in the system and their initial conditions\n",
|
|
"# In the current version of SimCAD, `timestamp` is mandatory\n",
|
|
"# The `signal` state is the exogenous state that we'll model\n",
|
|
"initial_conditions = {\n",
|
|
" 'follow': float(1),\n",
|
|
" 'signal': float(0),\n",
|
|
" 'timestamp': '2018-01-01 00:00:00'\n",
|
|
"}\n",
|
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Next, define the function that updates the `follow` state. As defined above, all it does is add or subtract an amount from the state."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
|
|
"# Definitions of functions that update internal states\n",
|
|
"# These functions must return a tuple containing the name of the state being updated and its new value\n",
|
|
"# As with the exogenous state update functions, the `s` argument contains a copy of the current values of all the states\n",
|
|
"# The argument `_input` contains a dictionary of inputs passed to the mechanisms by agents interacting with it \n",
|
|
"\n",
|
|
"#momentum term limiting my following\n",
|
|
"theta = .2 \n",
|
|
"\n",
|
|
"# Definition of the function that updates the `follow` state\n",
|
|
"def add(step, sL, s, _input):\n",
|
|
" y = 'follow'\n",
|
|
" x = (s['follow'] + _input['value'])*(1-theta)+ theta*s['follow']+np.random.randn() # All the state update function does is add to the `follow` state the `value` passed to it\n",
|
|
" return (y, x)\n",
|
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"The policies of the agents that interact with the system through `mechanisms` are modelled as `BEHAVIORS`. In this example, we are modelling a simple behavior in which the agent reads the current state of the exogenous `signal` and of the internal state `follow` and compares them. The `return value` of the behavior function will be passed by the SimCAD engine as the `_input` argument of the mechanism"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
|
|
"# Definitions of the Behavioral Models (or Behaviors for short) - functions that convey some information to mechanisms\n",
|
|
"# Behaviors must return a dictionary containing whatever information they should pass to the mechanism they relate to\n",
|
|
"# As with the state update functions, the `s` argument contains a copy of the current values of all the states\n",
|
|
"\n",
|
|
"# Definition of the `tracker` behavior\n",
|
|
"def tracker(step, sL, s):\n",
|
|
" currentSignal = s['signal'] # Read the current state of the exogenous `signal`\n",
|
|
" currentFollow = s['follow'] # Read the current state of the internal state `follow`\n",
|
|
" diff = currentSignal - currentFollow # Compare the two\n",
|
|
" return {'value': diff} # Return the difference between them"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Finally, we map mechanisms to states and behaviors. In our example, we define that a mechanism called `simple_mechanism` updates the `follow` state through the `add` function, driven by the `tracker` behavior."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"mechanisms = {\n",
|
|
" 'simple_mechanism': { # The name of the mechanism; can be anything\n",
|
|
" 'behaviors': { # Dictionary of behavioral models related to this mechanism\n",
|
|
" 'behavior_group_1': tracker # The name of the behavior (key), followed by the function that defines it\n",
|
|
" },\n",
|
|
" 'states': { # Dictionary of states updated by this mechanism\n",
|
|
" 'follow': add # The name of the state (key) followed by the function that updates it\n",
|
|
" }\n",
|
|
" }\n",
|
|
"}"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Running the engine\n",
|
|
"We can now recreate the Configuration object and rerun the experiment with the expanded configurations"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"single_proc: [<SimCAD.configuration.Configuration object at 0x105a75828>]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"config = Configuration(sim_config=sim_config,\n",
|
|
" state_dict=initial_conditions,\n",
|
|
" seed=seeds,\n",
|
|
" exogenous_states=exogenous_states,\n",
|
|
" env_processes=env_processes,\n",
|
|
" mechanisms=mechanisms)\n",
|
|
"executor = Executor(exec_context, [config]) # Pass the configuration object inside an array\n",
|
|
"raw_result, tensor = executor.main() # The `main()` method returns a tuple; its first elements contains the raw results"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Analyzing the results\n",
|
|
"And again we convert the raw results into a DataFrame for analysis"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"metadata": {
|
|
"scrolled": false
|
|
},
|
|
"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>signal</th>\n",
|
|
" <th>follow</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>count</th>\n",
|
|
" <td>5.100000e+01</td>\n",
|
|
" <td>51.000000</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>mean</th>\n",
|
|
" <td>-2.493893e-17</td>\n",
|
|
" <td>-0.091071</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>std</th>\n",
|
|
" <td>7.071068e-01</td>\n",
|
|
" <td>1.038318</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>min</th>\n",
|
|
" <td>-9.980267e-01</td>\n",
|
|
" <td>-1.936328</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>25%</th>\n",
|
|
" <td>-6.845471e-01</td>\n",
|
|
" <td>-0.955494</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>50%</th>\n",
|
|
" <td>0.000000e+00</td>\n",
|
|
" <td>-0.232079</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>75%</th>\n",
|
|
" <td>6.845471e-01</td>\n",
|
|
" <td>0.862438</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>max</th>\n",
|
|
" <td>9.980267e-01</td>\n",
|
|
" <td>2.153999</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"text/plain": [
|
|
" signal follow\n",
|
|
"count 5.100000e+01 51.000000\n",
|
|
"mean -2.493893e-17 -0.091071\n",
|
|
"std 7.071068e-01 1.038318\n",
|
|
"min -9.980267e-01 -1.936328\n",
|
|
"25% -6.845471e-01 -0.955494\n",
|
|
"50% 0.000000e+00 -0.232079\n",
|
|
"75% 6.845471e-01 0.862438\n",
|
|
"max 9.980267e-01 2.153999"
|
|
]
|
|
},
|
|
"execution_count": 9,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "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\n",
|
|
"text/plain": [
|
|
"<Figure size 432x288 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {
|
|
"needs_background": "light"
|
|
},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"%matplotlib inline\n",
|
|
"import pandas as pd\n",
|
|
"df = pd.DataFrame(raw_result)\n",
|
|
"df.plot('timestamp', ['signal','follow'])\n",
|
|
"df[['signal','follow']].describe()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"df[\"error\"]= df.follow-df.signal"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 11,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"<matplotlib.axes._subplots.AxesSubplot at 0x1166b5518>"
|
|
]
|
|
},
|
|
"execution_count": 11,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "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\n",
|
|
"text/plain": [
|
|
"<Figure size 432x288 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {
|
|
"needs_background": "light"
|
|
},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"df.error.hist()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
}
|
|
],
|
|
"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
|
|
}
|