Merge pull request #52 from BlockScience/tutorials
tutorials from cadCAD-Tutorials repo + fixed links
|
|
@ -59,7 +59,6 @@ pip3 install dist/*.whl
|
|||
***IMPORTANT NOTE:*** Tokens are issued to those with access to proprietary builds of cadCAD and BlockScience employees **ONLY**.
|
||||
Replace \<TOKEN\> with an issued token in the script below.
|
||||
```bash
|
||||
pip3 install pandas pathos fn funcy tabulate
|
||||
pip3 install cadCAD --extra-index-url https://<TOKEN>@repo.fury.io/blockscience/
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
ds1,ds2,ds3,run,substep,timestep
|
||||
0,0,1,1,0,0
|
||||
1,40,5,1,1,1
|
||||
2,40,5,1,2,1
|
||||
3,40,5,1,3,1
|
||||
4,40,5,1,1,2
|
||||
5,40,5,1,2,2
|
||||
6,40,5,1,3,2
|
||||
7,40,5,1,1,3
|
||||
8,40,5,1,2,3
|
||||
9,40,5,1,3,3
|
||||
10,40,5,1,1,4
|
||||
11,40,5,1,2,4
|
||||
12,40,5,1,3,4
|
||||
0,0,1,2,0,0
|
||||
1,40,5,2,1,1
|
||||
2,40,5,2,2,1
|
||||
3,40,5,2,3,1
|
||||
4,40,5,2,1,2
|
||||
5,40,5,2,2,2
|
||||
6,40,5,2,3,2
|
||||
7,40,5,2,1,3
|
||||
8,40,5,2,2,3
|
||||
9,40,5,2,3,3
|
||||
10,40,5,2,1,4
|
||||
11,40,5,2,2,4
|
||||
12,40,5,2,3,4
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
"\n",
|
||||
"cadCAD is a Python library that assists in the processes of designing, testing and validating complex systems through simulation. At its core, cadCAD is a differential games engine that supports parameter sweeping and Monte Carlo analyses and can be easily integrated with other scientific computing Python modules and data science workflows.\n",
|
||||
"\n",
|
||||
"To learn more about cadCAD, follow our [tutorial series](https://github.com/BlockScience/cadCAD-Tutorials/tree/master/01%20Tutorials)\n",
|
||||
"To learn more about cadCAD, follow our [tutorial series](../../tutorials)\n",
|
||||
"\n",
|
||||
"**Installing cadCAD:**\n",
|
||||
"\n",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
**Robot and Marbles Tutorial Series**
|
||||
|
||||
In this series, we introduce basic concepts of cadCAD and system modelling in general using a simple toy model.
|
||||
[Part 1](robot-marbles-part-1/robot-marbles-part-1.ipynb) - States and State Update Functions
|
||||
[Part 2](robot-marbles-part-2/robot-marbles-part-2.ipynb) - Actions and State Dependent Policies
|
||||
[Part 3](robot-marbles-part-3/robot-marbles-part-3.ipynb) - From Synchronous to Asynchronous Time
|
||||
[Part 4](robot-marbles-part-4/robot-marbles-part-4.ipynb) - Uncertainty and Stochastic Processes
|
||||
[Part 5](robot-marbles-part-5/robot-marbles-part-5.ipynb) - Using class objects as state variables
|
||||
|
||||
Check out the [videos](videos) folder for detailed walkthroughs of each one of the tutorials.
|
||||
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
|
@ -0,0 +1 @@
|
|||
(https://youtu.be/uJEiYHRWA9g)
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
# import libraries
|
||||
from decimal import Decimal
|
||||
import numpy as np
|
||||
from datetime import timedelta
|
||||
from cadCAD.configuration import append_configs
|
||||
from cadCAD.configuration.utils import bound_norm_random, ep_time_step, config_sim
|
||||
|
||||
seeds = {
|
||||
# 'z': np.random.RandomState(1),
|
||||
# 'a': np.random.RandomState(2)
|
||||
}
|
||||
|
||||
sim_config = config_sim({
|
||||
'T': range(10), #number of discrete iterations in each experiement
|
||||
'N': 1, #number of times the simulation will be run (Monte Carlo runs)
|
||||
#'M': g #parameter sweep dictionary
|
||||
})
|
||||
|
||||
|
||||
# define the time deltas for the discrete increments in the model
|
||||
# ts_format = '%Y-%m-%d %H:%M:%S'
|
||||
# t_delta = timedelta(days=0, minutes=1, seconds=0)
|
||||
# def time_model(_g, step, sL, s, _input):
|
||||
# y = 'time'
|
||||
# x = ep_time_step(s, dt_str=s['time'], fromat_str=ts_format, _timedelta=t_delta)
|
||||
# return (y, x)
|
||||
|
||||
# Behaviors
|
||||
|
||||
# Mechanisms
|
||||
def update_A(_g, step, sL, s, _input):
|
||||
y = 'box_A'
|
||||
add_to_A = 0
|
||||
if (s['box_A'] > s['box_B']):
|
||||
add_to_A = -1
|
||||
elif (s['box_A'] < s['box_B']):
|
||||
add_to_A = 1
|
||||
x = s['box_A'] + add_to_A
|
||||
return (y, x)
|
||||
|
||||
def update_B(_g, step, sL, s, _input):
|
||||
y = 'box_B'
|
||||
add_to_B = 0
|
||||
if (s['box_B'] > s['box_A']):
|
||||
add_to_B = -1
|
||||
elif (s['box_B'] < s['box_A']):
|
||||
add_to_B = 1
|
||||
x = s['box_B'] + add_to_B
|
||||
return (y, x)
|
||||
|
||||
# Initial States
|
||||
genesis_states = {
|
||||
'box_A': 10, # as per the description of the example, box_A starts out with 10 marbles in it
|
||||
'box_B': 0 # as per the description of the example, box_B starts out empty
|
||||
}
|
||||
|
||||
exogenous_states = {
|
||||
#'time': time_model
|
||||
}
|
||||
|
||||
env_processes = {
|
||||
}
|
||||
|
||||
#build mechanism dictionary to "wire up the circuit"
|
||||
mechanisms = [
|
||||
{
|
||||
'policies': {
|
||||
},
|
||||
'variables': { # The following state variables will be updated simultaneously
|
||||
'box_A': update_A,
|
||||
'box_B': update_B
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
|
||||
append_configs(
|
||||
sim_configs=sim_config,
|
||||
initial_state=genesis_states,
|
||||
seeds=seeds,
|
||||
raw_exogenous_states=exogenous_states,
|
||||
env_processes=env_processes,
|
||||
partial_state_update_blocks=mechanisms
|
||||
)
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
# import libraries
|
||||
from decimal import Decimal
|
||||
import numpy as np
|
||||
from datetime import timedelta
|
||||
from cadCAD.configuration import append_configs
|
||||
from cadCAD.configuration.utils import bound_norm_random, ep_time_step, config_sim
|
||||
|
||||
seeds = {
|
||||
# 'z': np.random.RandomState(1),
|
||||
# 'a': np.random.RandomState(2)
|
||||
}
|
||||
|
||||
sim_config = config_sim({
|
||||
'T': range(10), #number of discrete iterations in each experiement
|
||||
'N': 1, #number of times the simulation will be run (Monte Carlo runs)
|
||||
#'M': g #parameter sweep dictionary
|
||||
})
|
||||
|
||||
|
||||
# define the time deltas for the discrete increments in the model
|
||||
# ts_format = '%Y-%m-%d %H:%M:%S'
|
||||
# t_delta = timedelta(days=0, minutes=1, seconds=0)
|
||||
# def time_model(_g, step, sL, s, _input):
|
||||
# y = 'time'
|
||||
# x = ep_time_step(s, dt_str=s['time'], fromat_str=ts_format, _timedelta=t_delta)
|
||||
# return (y, x)
|
||||
|
||||
# Behaviors
|
||||
|
||||
# Mechanisms
|
||||
def update_A(_g, step, sL, s, _input):
|
||||
y = 'box_A'
|
||||
add_to_A = 0
|
||||
if (s['box_A'] > s['box_B']):
|
||||
add_to_A = -1
|
||||
elif (s['box_A'] < s['box_B']):
|
||||
add_to_A = 1
|
||||
x = s['box_A'] + add_to_A
|
||||
return (y, x)
|
||||
|
||||
def update_B(_g, step, sL, s, _input):
|
||||
y = 'box_B'
|
||||
add_to_B = 0
|
||||
if (s['box_B'] > s['box_A']):
|
||||
add_to_B = -1
|
||||
elif (s['box_B'] < s['box_A']):
|
||||
add_to_B = 1
|
||||
x = s['box_B'] + add_to_B
|
||||
return (y, x)
|
||||
|
||||
# Initial States
|
||||
genesis_states = {
|
||||
'box_A': 11, # as per the description of the example, box_A starts out with 10 marbles in it
|
||||
'box_B': 0 # as per the description of the example, box_B starts out empty
|
||||
}
|
||||
|
||||
exogenous_states = {
|
||||
#'time': time_model
|
||||
}
|
||||
|
||||
env_processes = {
|
||||
}
|
||||
|
||||
#build mechanism dictionary to "wire up the circuit"
|
||||
mechanisms = [
|
||||
{
|
||||
'policies': {
|
||||
},
|
||||
'variables': { # The following state variables will be updated simultaneously
|
||||
'box_A': update_A,
|
||||
'box_B': update_B
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
|
||||
append_configs(
|
||||
sim_configs=sim_config,
|
||||
initial_state=genesis_states,
|
||||
seeds=seeds,
|
||||
raw_exogenous_states=exogenous_states,
|
||||
env_processes=env_processes,
|
||||
partial_state_update_blocks=mechanisms
|
||||
)
|
||||
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
|
@ -0,0 +1 @@
|
|||
(https://youtu.be/Y5MzhVRQyzY)
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
# import libraries
|
||||
from decimal import Decimal
|
||||
import numpy as np
|
||||
from datetime import timedelta
|
||||
from cadCAD.configuration import append_configs
|
||||
from cadCAD.configuration.utils import bound_norm_random, ep_time_step, config_sim
|
||||
|
||||
seeds = {
|
||||
# 'z': np.random.RandomState(1),
|
||||
# 'a': np.random.RandomState(2)
|
||||
}
|
||||
|
||||
sim_config = config_sim({
|
||||
'T': range(10), #number of discrete iterations in each experiement
|
||||
'N': 1, #number of times the simulation will be run (Monte Carlo runs)
|
||||
#'M': g #parameter sweep dictionary
|
||||
})
|
||||
|
||||
|
||||
# define the time deltas for the discrete increments in the model
|
||||
# ts_format = '%Y-%m-%d %H:%M:%S'
|
||||
# t_delta = timedelta(days=0, minutes=1, seconds=0)
|
||||
# def time_model(_g, step, sL, s, _input):
|
||||
# y = 'time'
|
||||
# x = ep_time_step(s, dt_str=s['time'], fromat_str=ts_format, _timedelta=t_delta)
|
||||
# return (y, x)
|
||||
|
||||
# Behaviors
|
||||
def robot_arm(_g, step, sL, s):
|
||||
add_to_A = 0
|
||||
if (s['box_A'] > s['box_B']):
|
||||
add_to_A = -1
|
||||
elif (s['box_A'] < s['box_B']):
|
||||
add_to_A = 1
|
||||
return({'add_to_A': add_to_A, 'add_to_B': -add_to_A})
|
||||
|
||||
|
||||
|
||||
# Mechanisms
|
||||
def increment_A(_g, step, sL, s, _input):
|
||||
y = 'box_A'
|
||||
x = s['box_A'] + _input['add_to_A']
|
||||
return (y, x)
|
||||
|
||||
def increment_B(_g, step, sL, s, _input):
|
||||
y = 'box_B'
|
||||
x = s['box_B'] + _input['add_to_B']
|
||||
return (y, x)
|
||||
|
||||
# Initial States
|
||||
genesis_states = {
|
||||
'box_A': 10, # as per the description of the example, box_A starts out with 10 marbles in it
|
||||
'box_B': 0 # as per the description of the example, box_B starts out empty
|
||||
}
|
||||
|
||||
exogenous_states = {
|
||||
#'time': time_model
|
||||
}
|
||||
|
||||
env_processes = {
|
||||
}
|
||||
|
||||
#build mechanism dictionary to "wire up the circuit"
|
||||
mechanisms = [
|
||||
{
|
||||
'policies': { # The following policy functions will be evaluated and their returns will be passed to the state update functions
|
||||
'robot_arm': robot_arm
|
||||
},
|
||||
'states': { # The following state variables will be updated simultaneously
|
||||
'box_A': increment_A,
|
||||
'box_B': increment_B
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
|
||||
append_configs(
|
||||
sim_configs=sim_config,
|
||||
initial_state=genesis_states,
|
||||
seeds=seeds,
|
||||
raw_exogenous_states=exogenous_states,
|
||||
env_processes=env_processes,
|
||||
partial_state_update_blocks=mechanisms
|
||||
)
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
# import libraries
|
||||
from decimal import Decimal
|
||||
import numpy as np
|
||||
from datetime import timedelta
|
||||
from cadCAD.configuration import append_configs
|
||||
from cadCAD.configuration.utils import bound_norm_random, ep_time_step, config_sim
|
||||
|
||||
seeds = {
|
||||
# 'z': np.random.RandomState(1),
|
||||
# 'a': np.random.RandomState(2)
|
||||
}
|
||||
|
||||
sim_config = config_sim({
|
||||
'T': range(10), #number of discrete iterations in each experiement
|
||||
'N': 1, #number of times the simulation will be run (Monte Carlo runs)
|
||||
#'M': g #parameter sweep dictionary
|
||||
})
|
||||
|
||||
|
||||
# define the time deltas for the discrete increments in the model
|
||||
# ts_format = '%Y-%m-%d %H:%M:%S'
|
||||
# t_delta = timedelta(days=0, minutes=1, seconds=0)
|
||||
# def time_model(_g, step, sL, s, _input):
|
||||
# y = 'time'
|
||||
# x = ep_time_step(s, dt_str=s['time'], fromat_str=ts_format, _timedelta=t_delta)
|
||||
# return (y, x)
|
||||
|
||||
# Behaviors
|
||||
def robot_arm(_g, step, sL, s):
|
||||
add_to_A = 0
|
||||
if (s['box_A'] > s['box_B']):
|
||||
add_to_A = -1
|
||||
elif (s['box_A'] < s['box_B']):
|
||||
add_to_A = 1
|
||||
return({'add_to_A': add_to_A, 'add_to_B': -add_to_A})
|
||||
|
||||
|
||||
|
||||
# Mechanisms
|
||||
def increment_A(_g, step, sL, s, _input):
|
||||
y = 'box_A'
|
||||
x = s['box_A'] + _input['add_to_A']
|
||||
return (y, x)
|
||||
|
||||
def increment_B(_g, step, sL, s, _input):
|
||||
y = 'box_B'
|
||||
x = s['box_B'] + _input['add_to_B']
|
||||
return (y, x)
|
||||
|
||||
# Initial States
|
||||
genesis_states = {
|
||||
'box_A': 10, # as per the description of the example, box_A starts out with 10 marbles in it
|
||||
'box_B': 0 # as per the description of the example, box_B starts out empty
|
||||
}
|
||||
|
||||
exogenous_states = {
|
||||
#'time': time_model
|
||||
}
|
||||
|
||||
env_processes = {
|
||||
}
|
||||
|
||||
#build mechanism dictionary to "wire up the circuit"
|
||||
mechanisms = [
|
||||
{
|
||||
'policies': { # The following policy functions will be evaluated and their returns will be passed to the state update functions
|
||||
'robot_arm_1': robot_arm,
|
||||
'robot_arm_2': robot_arm
|
||||
},
|
||||
|
||||
'states': { # The following state variables will be updated simultaneously
|
||||
'box_A': increment_A,
|
||||
'box_B': increment_B
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
|
||||
append_configs(
|
||||
sim_configs=sim_config,
|
||||
initial_state=genesis_states,
|
||||
seeds=seeds,
|
||||
raw_exogenous_states=exogenous_states,
|
||||
env_processes=env_processes,
|
||||
partial_state_update_blocks=mechanisms
|
||||
)
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
# import libraries
|
||||
from decimal import Decimal
|
||||
import numpy as np
|
||||
from datetime import timedelta
|
||||
from cadCAD.configuration import append_configs
|
||||
from cadCAD.configuration.utils import bound_norm_random, ep_time_step, config_sim
|
||||
|
||||
seeds = {
|
||||
}
|
||||
|
||||
sim_config = config_sim({
|
||||
'T': range(10),
|
||||
'N': 1
|
||||
})
|
||||
|
||||
# Behaviors
|
||||
def robot_arm(_g, step, sL, s):
|
||||
add_to_A = 0
|
||||
if (s['box_A'] > s['box_B']):
|
||||
add_to_A = -1
|
||||
elif (s['box_A'] < s['box_B']):
|
||||
add_to_A = 1
|
||||
return({'add_to_A': add_to_A, 'add_to_B': -add_to_A})
|
||||
|
||||
|
||||
# Mechanisms
|
||||
def increment_A(_g, step, sL, s, _input):
|
||||
y = 'box_A'
|
||||
x = s['box_A'] + _input['add_to_A']
|
||||
return (y, x)
|
||||
|
||||
def increment_B(_g, step, sL, s, _input):
|
||||
y = 'box_B'
|
||||
x = s['box_B'] + _input['add_to_B']
|
||||
return (y, x)
|
||||
|
||||
# Initial States
|
||||
genesis_states = {
|
||||
'box_A': 10,
|
||||
'box_B': 0
|
||||
}
|
||||
|
||||
exogenous_states = {
|
||||
}
|
||||
|
||||
|
||||
env_processes = {
|
||||
}
|
||||
|
||||
|
||||
mechanisms = [
|
||||
{
|
||||
'policies': {
|
||||
'robot_arm': robot_arm
|
||||
},
|
||||
'states': {
|
||||
'box_A': increment_A,
|
||||
'box_B': increment_B
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
append_configs(
|
||||
sim_configs=sim_config,
|
||||
initial_state=genesis_states,
|
||||
seeds=seeds,
|
||||
raw_exogenous_states=exogenous_states,
|
||||
env_processes=env_processes,
|
||||
partial_state_update_blocks=mechanisms
|
||||
)
|
||||
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
|
@ -0,0 +1 @@
|
|||
(https://youtu.be/wF539-K0qXs)
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
# import libraries
|
||||
from decimal import Decimal
|
||||
import numpy as np
|
||||
from datetime import timedelta
|
||||
from cadCAD.configuration import append_configs
|
||||
from cadCAD.configuration.utils import bound_norm_random, ep_time_step, config_sim
|
||||
|
||||
seeds = {
|
||||
# 'z': np.random.RandomState(1),
|
||||
# 'a': np.random.RandomState(2)
|
||||
}
|
||||
|
||||
sim_config = config_sim({
|
||||
'T': range(10), #number of discrete iterations in each experiement
|
||||
'N': 1, #number of times the simulation will be run (Monte Carlo runs)
|
||||
#'M': g #parameter sweep dictionary
|
||||
})
|
||||
|
||||
|
||||
# define the time deltas for the discrete increments in the model
|
||||
# ts_format = '%Y-%m-%d %H:%M:%S'
|
||||
# t_delta = timedelta(days=0, minutes=1, seconds=0)
|
||||
# def time_model(_g, step, sL, s, _input):
|
||||
# y = 'time'
|
||||
# x = ep_time_step(s, dt_str=s['time'], fromat_str=ts_format, _timedelta=t_delta)
|
||||
# return (y, x)
|
||||
|
||||
# Behaviors
|
||||
def robot_arm(_g, step, sL, s):
|
||||
add_to_A = 0
|
||||
if (s['box_A'] > s['box_B']):
|
||||
add_to_A = -1
|
||||
elif (s['box_A'] < s['box_B']):
|
||||
add_to_A = 1
|
||||
return({'add_to_A': add_to_A, 'add_to_B': -add_to_A})
|
||||
|
||||
robots_periods = [2,3] # Robot 1 acts once every 2 timesteps; Robot 2 acts once every 3 timesteps
|
||||
|
||||
def get_current_timestep(cur_substep, s):
|
||||
if cur_substep == 1:
|
||||
return s['timestep']+1
|
||||
return s['timestep']
|
||||
|
||||
def robot_arm_1(_g, step, sL, s):
|
||||
_robotId = 1
|
||||
if get_current_timestep(step, s)%robots_periods[_robotId-1]==0: # on timesteps that are multiple of 2, Robot 1 acts
|
||||
return robot_arm(_g, step, sL, s)
|
||||
else:
|
||||
return({'add_to_A': 0, 'add_to_B': 0}) # for all other timesteps, Robot 1 doesn't interfere with the system
|
||||
|
||||
def robot_arm_2(_g, step, sL, s):
|
||||
_robotId = 2
|
||||
if get_current_timestep(step, s)%robots_periods[_robotId-1]==0: # on timesteps that are multiple of 3, Robot 2 acts
|
||||
return robot_arm(_g, step, sL, s)
|
||||
else:
|
||||
return({'add_to_A': 0, 'add_to_B': 0}) # for all other timesteps, Robot 2 doesn't interfere with the system
|
||||
|
||||
|
||||
|
||||
# Mechanisms
|
||||
def increment_A(_g, step, sL, s, _input):
|
||||
y = 'box_A'
|
||||
x = s['box_A'] + _input['add_to_A']
|
||||
return (y, x)
|
||||
|
||||
def increment_B(_g, step, sL, s, _input):
|
||||
y = 'box_B'
|
||||
x = s['box_B'] + _input['add_to_B']
|
||||
return (y, x)
|
||||
|
||||
# Initial States
|
||||
genesis_states = {
|
||||
'box_A': 10, # as per the description of the example, box_A starts out with 10 marbles in it
|
||||
'box_B': 0 # as per the description of the example, box_B starts out empty
|
||||
}
|
||||
|
||||
exogenous_states = {
|
||||
#'time': time_model
|
||||
}
|
||||
|
||||
env_processes = {
|
||||
}
|
||||
|
||||
#build mechanism dictionary to "wire up the circuit"
|
||||
mechanisms = [
|
||||
{
|
||||
'policies': { # The following policy functions will be evaluated and their returns will be passed to the state update functions
|
||||
'robot_arm_1': robot_arm_1,
|
||||
'robot_arm_2': robot_arm_2
|
||||
},
|
||||
|
||||
'states': { # The following state variables will be updated simultaneously
|
||||
'box_A': increment_A,
|
||||
'box_B': increment_B
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
|
||||
append_configs(
|
||||
sim_configs=sim_config,
|
||||
initial_state=genesis_states,
|
||||
seeds=seeds,
|
||||
raw_exogenous_states=exogenous_states,
|
||||
env_processes=env_processes,
|
||||
partial_state_update_blocks=mechanisms
|
||||
)
|
||||
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
|
@ -0,0 +1 @@
|
|||
(https://youtu.be/MLNTqqX47Ew)
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
# import libraries
|
||||
from decimal import Decimal
|
||||
import numpy as np
|
||||
from datetime import timedelta
|
||||
from cadCAD.configuration import append_configs
|
||||
from cadCAD.configuration.utils import bound_norm_random, ep_time_step, config_sim
|
||||
|
||||
seeds = {
|
||||
# 'z': np.random.RandomState(1),
|
||||
# 'a': np.random.RandomState(2)
|
||||
}
|
||||
|
||||
sim_config = config_sim({
|
||||
'T': range(10), #number of discrete iterations in each experiement
|
||||
'N': 1, #number of times the simulation will be run (Monte Carlo runs)
|
||||
#'M': g #parameter sweep dictionary
|
||||
})
|
||||
|
||||
|
||||
# define the time deltas for the discrete increments in the model
|
||||
# ts_format = '%Y-%m-%d %H:%M:%S'
|
||||
# t_delta = timedelta(days=0, minutes=1, seconds=0)
|
||||
# def time_model(_g, step, sL, s, _input):
|
||||
# y = 'time'
|
||||
# x = ep_time_step(s, dt_str=s['time'], fromat_str=ts_format, _timedelta=t_delta)
|
||||
# return (y, x)
|
||||
|
||||
# Behaviors
|
||||
def robot_arm(_g, step, sL, s):
|
||||
add_to_A = 0
|
||||
if (s['box_A'] > s['box_B']):
|
||||
add_to_A = -1
|
||||
elif (s['box_A'] < s['box_B']):
|
||||
add_to_A = 1
|
||||
return({'add_to_A': add_to_A, 'add_to_B': -add_to_A})
|
||||
|
||||
robots_probabilities = [0.5,1/3] # Robot 1 acts with a 50% probability; Robot 2, 33.33%
|
||||
|
||||
def robot_arm_1(_g, step, sL, s):
|
||||
_robotId = 1
|
||||
if np.random.rand()<robots_probabilities[_robotId-1]: # draw a random number between 0 and 1; if it's smaller than the robot's parameter, it acts
|
||||
return robot_arm(_g, step, sL, s)
|
||||
else:
|
||||
return({'add_to_A': 0, 'add_to_B': 0}) # otherwise, the robot doesn't interfere with the system
|
||||
|
||||
def robot_arm_2(_g, step, sL, s):
|
||||
_robotId = 2
|
||||
if np.random.rand()<robots_probabilities[_robotId-1]: # draw a random number between 0 and 1; if it's smaller than the robot's parameter, it acts
|
||||
return robot_arm(_g, step, sL, s)
|
||||
else:
|
||||
return({'add_to_A': 0, 'add_to_B': 0}) # otherwise, the robot doesn't interfere with the system
|
||||
|
||||
|
||||
|
||||
# Mechanisms
|
||||
def increment_A(_g, step, sL, s, _input):
|
||||
y = 'box_A'
|
||||
x = s['box_A'] + _input['add_to_A']
|
||||
return (y, x)
|
||||
|
||||
def increment_B(_g, step, sL, s, _input):
|
||||
y = 'box_B'
|
||||
x = s['box_B'] + _input['add_to_B']
|
||||
return (y, x)
|
||||
|
||||
# Initial States
|
||||
genesis_states = {
|
||||
'box_A': 10, # as per the description of the example, box_A starts out with 10 marbles in it
|
||||
'box_B': 0 # as per the description of the example, box_B starts out empty
|
||||
}
|
||||
|
||||
exogenous_states = {
|
||||
#'time': time_model
|
||||
}
|
||||
|
||||
env_processes = {
|
||||
}
|
||||
|
||||
#build mechanism dictionary to "wire up the circuit"
|
||||
mechanisms = [
|
||||
{
|
||||
'policies': { # The following policy functions will be evaluated and their returns will be passed to the state update functions
|
||||
'robot_arm_1': robot_arm_1,
|
||||
'robot_arm_2': robot_arm_2
|
||||
},
|
||||
|
||||
'states': { # The following state variables will be updated simultaneously
|
||||
'box_A': increment_A,
|
||||
'box_B': increment_B
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
|
||||
append_configs(
|
||||
sim_configs=sim_config,
|
||||
initial_state=genesis_states,
|
||||
seeds=seeds,
|
||||
raw_exogenous_states=exogenous_states,
|
||||
env_processes=env_processes,
|
||||
partial_state_update_blocks=mechanisms
|
||||
)
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
# import libraries
|
||||
from decimal import Decimal
|
||||
import numpy as np
|
||||
from datetime import timedelta
|
||||
from cadCAD.configuration import append_configs
|
||||
from cadCAD.configuration.utils import bound_norm_random, ep_time_step, config_sim
|
||||
|
||||
seeds = {
|
||||
# 'z': np.random.RandomState(1),
|
||||
# 'a': np.random.RandomState(2)
|
||||
}
|
||||
|
||||
sim_config = config_sim({
|
||||
'T': range(10), #number of discrete iterations in each experiement
|
||||
'N': 50, #number of times the simulation will be run (Monte Carlo runs)
|
||||
#'M': g #parameter sweep dictionary
|
||||
})
|
||||
|
||||
|
||||
# define the time deltas for the discrete increments in the model
|
||||
# ts_format = '%Y-%m-%d %H:%M:%S'
|
||||
# t_delta = timedelta(days=0, minutes=1, seconds=0)
|
||||
# def time_model(_g, step, sL, s, _input):
|
||||
# y = 'time'
|
||||
# x = ep_time_step(s, dt_str=s['time'], fromat_str=ts_format, _timedelta=t_delta)
|
||||
# return (y, x)
|
||||
|
||||
# Behaviors
|
||||
def robot_arm(_g, step, sL, s):
|
||||
add_to_A = 0
|
||||
if (s['box_A'] > s['box_B']):
|
||||
add_to_A = -1
|
||||
elif (s['box_A'] < s['box_B']):
|
||||
add_to_A = 1
|
||||
return({'add_to_A': add_to_A, 'add_to_B': -add_to_A})
|
||||
|
||||
robots_probabilities = [0.5,1/3] # Robot 1 acts with a 50% probability; Robot 2, 33.33%
|
||||
|
||||
def robot_arm_1(_g, step, sL, s):
|
||||
_robotId = 1
|
||||
if np.random.rand()<robots_probabilities[_robotId-1]: # draw a random number between 0 and 1; if it's smaller than the robot's parameter, it acts
|
||||
return robot_arm(_g, step, sL, s)
|
||||
else:
|
||||
return({'add_to_A': 0, 'add_to_B': 0}) # otherwise, the robot doesn't interfere with the system
|
||||
|
||||
def robot_arm_2(_g, step, sL, s):
|
||||
_robotId = 2
|
||||
if np.random.rand()<robots_probabilities[_robotId-1]: # draw a random number between 0 and 1; if it's smaller than the robot's parameter, it acts
|
||||
return robot_arm(_g, step, sL, s)
|
||||
else:
|
||||
return({'add_to_A': 0, 'add_to_B': 0}) # otherwise, the robot doesn't interfere with the system
|
||||
|
||||
|
||||
|
||||
# Mechanisms
|
||||
def increment_A(_g, step, sL, s, _input):
|
||||
y = 'box_A'
|
||||
x = s['box_A'] + _input['add_to_A']
|
||||
return (y, x)
|
||||
|
||||
def increment_B(_g, step, sL, s, _input):
|
||||
y = 'box_B'
|
||||
x = s['box_B'] + _input['add_to_B']
|
||||
return (y, x)
|
||||
|
||||
# Initial States
|
||||
genesis_states = {
|
||||
'box_A': 10, # as per the description of the example, box_A starts out with 10 marbles in it
|
||||
'box_B': 0 # as per the description of the example, box_B starts out empty
|
||||
}
|
||||
|
||||
exogenous_states = {
|
||||
#'time': time_model
|
||||
}
|
||||
|
||||
env_processes = {
|
||||
}
|
||||
|
||||
#build mechanism dictionary to "wire up the circuit"
|
||||
mechanisms = [
|
||||
{
|
||||
'policies': { # The following policy functions will be evaluated and their returns will be passed to the state update functions
|
||||
'robot_arm_1': robot_arm_1,
|
||||
'robot_arm_2': robot_arm_2
|
||||
},
|
||||
|
||||
'states': { # The following state variables will be updated simultaneously
|
||||
'box_A': increment_A,
|
||||
'box_B': increment_B
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
|
||||
append_configs(
|
||||
sim_configs=sim_config,
|
||||
initial_state=genesis_states,
|
||||
seeds=seeds,
|
||||
raw_exogenous_states=exogenous_states,
|
||||
env_processes=env_processes,
|
||||
partial_state_update_blocks=mechanisms
|
||||
)
|
||||
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
|
@ -0,0 +1 @@
|
|||
https://www.youtube.com/watch?v=I0mSQppibLs&feature=youtu.be
|
||||
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 21 KiB |