fefactored env_process
This commit is contained in:
parent
1c89d28ab5
commit
2de989db0a
|
|
@ -1,4 +1,4 @@
|
|||
.idea
|
||||
jupyter notebook.idea
|
||||
.ipynb_checkpoints
|
||||
.DS_Store
|
||||
.idea
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class Configuration(object):
|
|||
|
||||
sanitize_config(self)
|
||||
|
||||
|
||||
# ToDo: Remove Seeds
|
||||
def append_configs(sim_configs={}, initial_state={}, seeds={}, raw_exogenous_states={}, env_processes={},
|
||||
partial_state_update_blocks={}, policy_ops=[lambda a, b: a + b], _exo_update_per_ts: bool = True) -> None:
|
||||
if _exo_update_per_ts is True:
|
||||
|
|
|
|||
|
|
@ -134,20 +134,43 @@ def trigger_condition(s, conditions, cond_opp):
|
|||
condition_bools = [s[field] in precondition_values for field, precondition_values in conditions.items()]
|
||||
return reduce(cond_opp, condition_bools)
|
||||
|
||||
def apply_state_condition(conditions, cond_opp, y, f, _g, step, sL, s, _input):
|
||||
if trigger_condition(s, conditions, cond_opp):
|
||||
def apply_state_condition(pre_conditions, cond_opp, y, f, _g, step, sL, s, _input):
|
||||
if trigger_condition(s, pre_conditions, cond_opp):
|
||||
return f(_g, step, sL, s, _input)
|
||||
else:
|
||||
return y, s[y]
|
||||
|
||||
def proc_trigger(y, f, conditions, cond_op):
|
||||
return lambda _g, step, sL, s, _input: apply_state_condition(conditions, cond_op, y, f, _g, step, sL, s, _input)
|
||||
def var_trigger(y, f, pre_conditions, cond_op):
|
||||
return lambda _g, step, sL, s, _input: apply_state_condition(pre_conditions, cond_op, y, f, _g, step, sL, s, _input)
|
||||
|
||||
|
||||
def timestep_trigger(end_substep, y, f):
|
||||
conditions = {'substep': [0, end_substep]}
|
||||
cond_opp = lambda a, b: a and b
|
||||
return proc_trigger(y, f, conditions, cond_opp)
|
||||
def var_substep_trigger(substeps):
|
||||
def trigger(end_substep, y, f):
|
||||
pre_conditions = {'substep': substeps}
|
||||
cond_opp = lambda a, b: a and b
|
||||
return var_trigger(y, f, pre_conditions, cond_opp)
|
||||
return lambda y, f: curry(trigger)(substeps)(y)(f)
|
||||
|
||||
|
||||
def env_trigger(end_substep):
|
||||
def trigger(end_substep, trigger_field, trigger_vals, funct_list):
|
||||
def env_update(state_dict, target_value):
|
||||
state_dict_copy = deepcopy(state_dict)
|
||||
# Use supstep to simulate current sysMetrics
|
||||
if state_dict_copy['substep'] == end_substep:
|
||||
state_dict_copy['timestep'] = state_dict_copy['timestep'] + 1
|
||||
|
||||
if state_dict_copy[trigger_field] in trigger_vals:
|
||||
for g in funct_list:
|
||||
target_value = g(target_value)
|
||||
|
||||
del state_dict_copy
|
||||
return target_value
|
||||
|
||||
return env_update
|
||||
|
||||
return lambda trigger_field, trigger_vals, funct_list: \
|
||||
curry(trigger)(end_substep)(trigger_field)(trigger_vals)(funct_list)
|
||||
|
||||
# trigger = curry(_trigger)
|
||||
# print(timestep_trigger)
|
||||
|
|
@ -157,19 +180,15 @@ def timestep_trigger(end_substep, y, f):
|
|||
def config_sim(d):
|
||||
def process_variables(d):
|
||||
return flatten_tabulated_dict(tabulate_dict(d))
|
||||
|
||||
if "M" in d:
|
||||
return [
|
||||
{
|
||||
"N": d["N"],
|
||||
"T": d["T"],
|
||||
"M": M
|
||||
}
|
||||
for M in process_variables(d["M"])
|
||||
]
|
||||
return [{"N": d["N"], "T": d["T"], "M": M} for M in process_variables(d["M"])]
|
||||
else:
|
||||
d["M"] = [{}]
|
||||
return d
|
||||
|
||||
def psub_list(psu_block, psu_steps):
|
||||
return [psu_block[psu] for psu in psu_steps]
|
||||
|
||||
def psub(policies, state_updates):
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class udcView(object):
|
|||
}
|
||||
members['methods'] = [k for k, v in self.__dict__.items() if str(type(v)) == "<class 'method'>"]
|
||||
members.update(variables)
|
||||
return f"{members}"
|
||||
return f"{members}" #[1:-1]
|
||||
|
||||
|
||||
class udcBroker(object):
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ from typing import Any, Callable, Dict, List, Tuple
|
|||
from pathos.pools import ThreadPool as TPool
|
||||
from copy import deepcopy
|
||||
from functools import reduce
|
||||
from funcy import compose
|
||||
|
||||
from cadCAD.engine.utils import engine_exception
|
||||
from cadCAD.utils import flatten
|
||||
|
|
@ -72,19 +73,48 @@ class Executor:
|
|||
# return {k: reduce(f1, val_list) for k, val_list in new_dict.items()}
|
||||
# return foldr(call, col_results)(ops)
|
||||
|
||||
# def apply_env_proc(
|
||||
# self,
|
||||
# env_processes: Dict[str, Callable],
|
||||
# state_dict: Dict[str, Any],
|
||||
# time_step: int
|
||||
# ) -> Dict[str, Any]:
|
||||
# for state in state_dict.keys():
|
||||
# if state in list(env_processes.keys()):
|
||||
# env_state: Callable = env_processes[state]
|
||||
# if (env_state.__name__ == '_curried') or (env_state.__name__ == 'proc_trigger'):
|
||||
# state_dict[state] = env_state(sub_step)(state_dict[state])
|
||||
# else:
|
||||
# state_dict[state] = env_state(state_dict[state])
|
||||
#
|
||||
# return state_dict
|
||||
|
||||
def apply_env_proc(
|
||||
self,
|
||||
env_processes: Dict[str, Callable],
|
||||
state_dict: Dict[str, Any],
|
||||
sub_step: int
|
||||
) -> Dict[str, Any]:
|
||||
for state in state_dict.keys():
|
||||
if state in list(env_processes.keys()):
|
||||
env_state: Callable = env_processes[state]
|
||||
if (env_state.__name__ == '_curried') or (env_state.__name__ == 'proc_trigger'):
|
||||
state_dict[state] = env_state(sub_step)(state_dict[state])
|
||||
else:
|
||||
state_dict[state] = env_state(state_dict[state])
|
||||
|
||||
def env_composition(target_field, state_dict, target_value):
|
||||
function_type = type(lambda x: x)
|
||||
env_update = env_processes[target_field]
|
||||
if isinstance(env_update, list):
|
||||
target_value = compose(*env_update[::-1])(target_value)
|
||||
elif isinstance(env_update, function_type):
|
||||
target_value = env_update(state_dict, target_value)
|
||||
else:
|
||||
target_value = env_update
|
||||
|
||||
return target_value
|
||||
|
||||
filtered_state_dict = {k: v for k, v in state_dict.items() if k in env_processes.keys()}
|
||||
env_proc_dict = {
|
||||
target_field: env_composition(target_field, state_dict, target_value)
|
||||
for target_field, target_value in filtered_state_dict.items()
|
||||
}
|
||||
|
||||
for k, v in env_proc_dict.items():
|
||||
state_dict[k] = v
|
||||
|
||||
return state_dict
|
||||
|
||||
|
|
@ -137,7 +167,10 @@ class Executor:
|
|||
|
||||
last_in_copy: Dict[str, Any] = transfer_missing_fields(last_in_obj, dict(generate_record(state_funcs)))
|
||||
# ToDo: Remove
|
||||
last_in_copy: Dict[str, Any] = self.apply_env_proc(env_processes, last_in_copy, last_in_copy['timestep'])
|
||||
# last_in_copy: Dict[str, Any] = self.apply_env_proc(env_processes, last_in_copy, last_in_copy['timestep'])
|
||||
last_in_copy: Dict[str, Any] = self.apply_env_proc(env_processes, last_in_copy)
|
||||
|
||||
|
||||
# ToDo: make 'substep' & 'timestep' reserve fields
|
||||
last_in_copy['substep'], last_in_copy['timestep'], last_in_copy['run'] = sub_step, time_step, run
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
from copy import deepcopy
|
||||
|
||||
from fn.func import curried
|
||||
|
||||
from cadCAD.configuration.utils import ep_time_step, time_step
|
||||
from funcy import curry
|
||||
import pprint as pp
|
||||
# from fn import _
|
||||
from functools import reduce
|
||||
|
||||
|
|
@ -25,7 +30,7 @@ def update_timestamp(y, timedelta, format):
|
|||
def apply(f, y: str, incr_by: int):
|
||||
return lambda _g, step, sL, s, _input: (y, curry(f)(s[y])(incr_by))
|
||||
|
||||
def add(y: str, incr_by: int):
|
||||
def add(y: str, incr_by):
|
||||
return apply(lambda a, b: a + b, y, incr_by)
|
||||
|
||||
def increment_state_by_int(y: str, incr_by: int):
|
||||
|
|
@ -85,15 +90,22 @@ def time_model(y, substeps, time_delta, ts_format='%Y-%m-%d %H:%M:%S'):
|
|||
# multi_cond_opp = lambda a, b: a and b
|
||||
# return proc_trigger2(y, f, multi_conditions, multi_cond_opp)
|
||||
|
||||
#
|
||||
# @curried
|
||||
|
||||
|
||||
def env_trigger(trigger_field, trigger_val, input, funct_list):
|
||||
y, x = input
|
||||
if trigger_field == trigger_val:
|
||||
i = 0
|
||||
for g in funct_list:
|
||||
x = g(x)
|
||||
return y, x
|
||||
|
||||
# print(env_trigger(3).__module__)
|
||||
# pp.pprint(dir(env_trigger))
|
||||
|
||||
|
||||
|
||||
# @curried
|
||||
# def env_proc_trigger(trigger_time, update_f, time):
|
||||
# if time == trigger_time:
|
||||
# return update_f
|
||||
# else:
|
||||
# return lambda x: x
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -3,3 +3,4 @@ wheel
|
|||
pathos
|
||||
fn
|
||||
tabulate
|
||||
funcy
|
||||
|
|
@ -16,7 +16,6 @@ run = Executor(exec_context=single_proc_ctx, configs=first_config)
|
|||
raw_result, tensor_field = run.main()
|
||||
result = pd.DataFrame(raw_result)
|
||||
def delSH(d):
|
||||
print(d)
|
||||
if 'sh' in d.keys():
|
||||
del d['sh']
|
||||
return d
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ import pandas as pd
|
|||
from tabulate import tabulate
|
||||
# The following imports NEED to be in the exact order
|
||||
from cadCAD.engine import ExecutionMode, ExecutionContext, Executor
|
||||
from simulations.validation import new_sweep_config
|
||||
# from simulations.validation import new_sweep_config
|
||||
from simulations.regression_tests import sweep_config
|
||||
from cadCAD import configs
|
||||
|
||||
exec_mode = ExecutionMode()
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
from decimal import Decimal
|
||||
import numpy as np
|
||||
from datetime import timedelta
|
||||
from funcy import compose
|
||||
import pprint
|
||||
|
||||
from cadCAD.configuration import append_configs
|
||||
from cadCAD.configuration.utils import proc_trigger, ep_time_step, config_sim
|
||||
from cadCAD.configuration.utils import proc_trigger, env_trigger, var_substep_trigger, config_sim, env_proc_trigger, \
|
||||
time_step, psub_list
|
||||
|
||||
from typing import Dict, List
|
||||
|
||||
|
|
@ -25,74 +27,95 @@ g: Dict[str, List[int]] = {
|
|||
'omega': [7]
|
||||
}
|
||||
|
||||
psu_steps = ['m1', 'm2', 'm3']
|
||||
system_substeps = len(psu_steps)
|
||||
var_timestep_trigger = var_substep_trigger(system_substeps)
|
||||
env_timestep_trigger = env_trigger(system_substeps)
|
||||
env_process = {}
|
||||
psu_block = {k: {"policies": {}, "variables": {}} for k in psu_steps}
|
||||
|
||||
# ['s1', 's2', 's3', 's4']
|
||||
# Policies per Mechanism
|
||||
def p1m1(_g, step, sL, s):
|
||||
return {'param1': 1}
|
||||
psu_block['m1']['policies']['p1'] = p1m1
|
||||
|
||||
def p2m1(_g, step, sL, s):
|
||||
return {'param2': 4}
|
||||
psu_block['m1']['policies']['p2'] = p2m1
|
||||
|
||||
def p1m2(_g, step, sL, s):
|
||||
return {'param1': 'a', 'param2': _g['beta']}
|
||||
psu_block['m2']['policies']['p1'] = p1m2
|
||||
|
||||
def p2m2(_g, step, sL, s):
|
||||
return {'param1': 'b', 'param2': 0}
|
||||
psu_block['m2']['policies']['p2'] = p2m2
|
||||
|
||||
def p1m3(_g, step, sL, s):
|
||||
return {'param1': np.array([10, 100])}
|
||||
psu_block['m3']['policies']['p1'] = p1m3
|
||||
|
||||
def p2m3(_g, step, sL, s):
|
||||
return {'param1': np.array([20, 200])}
|
||||
psu_block['m3']['policies']['p2'] = p2m3
|
||||
|
||||
|
||||
# Internal States per Mechanism
|
||||
def s1m1(_g, step, sL, s, _input):
|
||||
return 's1', 0
|
||||
psu_block['m1']["variables"]['s1'] = s1m1
|
||||
|
||||
def s2m1(_g, step, sL, s, _input):
|
||||
return 's2', _g['beta']
|
||||
psu_block['m1']["variables"]['s2'] = s2m1
|
||||
|
||||
def s1m2(_g, step, sL, s, _input):
|
||||
return 's1', _input['param2']
|
||||
psu_block['m2']["variables"]['s1'] = s1m2
|
||||
|
||||
def s2m2(_g, step, sL, s, _input):
|
||||
return 's2', _input['param2']
|
||||
psu_block['m2']["variables"]['s2'] = s2m2
|
||||
|
||||
def s1m3(_g, step, sL, s, _input):
|
||||
return 's1', 0
|
||||
psu_block['m3']["variables"]['s1'] = s1m3
|
||||
|
||||
def s2m3(_g, step, sL, s, _input):
|
||||
return 's2', 0
|
||||
psu_block['m3']["variables"]['s2'] = s2m3
|
||||
|
||||
|
||||
# Exogenous States
|
||||
def update_timestamp(_g, step, sL, s, _input):
|
||||
y = 'timestamp'
|
||||
return y, time_step(dt_str=s[y], dt_format='%Y-%m-%d %H:%M:%S', _timedelta=timedelta(days=0, minutes=0, seconds=1))
|
||||
for m in ['m1','m2','m3']:
|
||||
# psu_block[m]["variables"]['timestamp'] = update_timestamp
|
||||
psu_block[m]["variables"]['timestamp'] = var_timestep_trigger(y='timestamp', f=update_timestamp)
|
||||
# psu_block[m]["variables"]['timestamp'] = proc_trigger(
|
||||
# y='timestamp', f=update_timestamp, pre_conditions={'substep': [0, system_substeps]}, cond_op=lambda a, b: a and b
|
||||
# )
|
||||
|
||||
proc_one_coef_A = 0.7
|
||||
proc_one_coef_B = 1.3
|
||||
|
||||
|
||||
def es3p1(_g, step, sL, s, _input):
|
||||
return 's3', _g['gamma']
|
||||
# @curried
|
||||
return 's3', s['s3']
|
||||
# use `timestep_trigger` to update every ts
|
||||
for m in ['m1','m2','m3']:
|
||||
psu_block[m]["variables"]['s3'] = var_timestep_trigger(y='s3', f=es3p1)
|
||||
|
||||
proc_one_coef_B = 1.3
|
||||
def es4p2(_g, step, sL, s, _input):
|
||||
return 's4', _g['gamma']
|
||||
|
||||
ts_format = '%Y-%m-%d %H:%M:%S'
|
||||
t_delta = timedelta(days=0, minutes=0, seconds=1)
|
||||
def es5p2(_g, step, sL, s, _input):
|
||||
y = 'timestep'
|
||||
x = ep_time_step(s, dt_str=s['timestep'], fromat_str=ts_format, _timedelta=t_delta)
|
||||
return (y, x)
|
||||
return 's4', s['s4'] #+ 4 #g['gamma'] + proc_one_coef_B
|
||||
for m in ['m1','m2','m3']:
|
||||
psu_block[m]["variables"]['s4'] = var_timestep_trigger(y='s4', f=es4p2)
|
||||
|
||||
|
||||
# Environment States
|
||||
# @curried
|
||||
# def env_a(param, x):
|
||||
# return x + param
|
||||
def env_a(x):
|
||||
return x
|
||||
def env_b(x):
|
||||
return 10
|
||||
|
||||
# ToDo: The number of values entered in sweep should be the # of config objs created,
|
||||
# not dependent on the # of times the sweep is applied
|
||||
# sweep exo_state func and point to exo-state in every other funtion
|
||||
# param sweep on genesis states
|
||||
|
||||
# Genesis States
|
||||
genesis_states = {
|
||||
|
|
@ -100,83 +123,37 @@ genesis_states = {
|
|||
's2': Decimal(0.0),
|
||||
's3': Decimal(1.0),
|
||||
's4': Decimal(1.0),
|
||||
# 'timestep': '2018-10-01 15:16:24'
|
||||
'timestamp': '2018-10-01 15:16:24'
|
||||
}
|
||||
# Environment Process
|
||||
# ToDo: Validate - make env proc trigger field agnostic
|
||||
env_process["s3"] = [lambda x: x + 1, lambda x: x + 1]
|
||||
env_process["s4"] = env_timestep_trigger(trigger_field='timestep', trigger_vals=[5], funct_list=[lambda x: 1, lambda x: x + 2])
|
||||
|
||||
|
||||
# remove `exo_update_per_ts` to update every ts
|
||||
raw_exogenous_states = {
|
||||
"s3": es3p1,
|
||||
"s4": es4p2,
|
||||
# "timestep": es5p2
|
||||
}
|
||||
|
||||
|
||||
# ToDo: make env proc trigger field agnostic
|
||||
# ToDo: input json into function renaming __name__
|
||||
triggered_env_b = proc_trigger(1, env_b)
|
||||
env_processes = {
|
||||
"s3": env_a, #sweep(beta, env_a),
|
||||
"s4": triggered_env_b #rename('parameterized', triggered_env_b) #sweep(beta, triggered_env_b)
|
||||
}
|
||||
# parameterized_env_processes = parameterize_states(env_processes)
|
||||
#
|
||||
# pp.pprint(parameterized_env_processes)
|
||||
# exit()
|
||||
|
||||
# ToDo: The number of values entered in sweep should be the # of config objs created,
|
||||
# not dependent on the # of times the sweep is applied
|
||||
# sweep exo_state func and point to exo-state in every other funtion
|
||||
# param sweep on genesis states
|
||||
|
||||
partial_state_update_block = {
|
||||
"m1": {
|
||||
"policies": {
|
||||
"b1": p1m1,
|
||||
"b2": p2m1
|
||||
},
|
||||
"variables": {
|
||||
"s1": s1m1,
|
||||
"s2": s2m1
|
||||
}
|
||||
},
|
||||
"m2": {
|
||||
"policies": {
|
||||
"b1": p1m2,
|
||||
"b2": p2m2,
|
||||
},
|
||||
"variables": {
|
||||
"s1": s1m2,
|
||||
"s2": s2m2
|
||||
}
|
||||
},
|
||||
"m3": {
|
||||
"policies": {
|
||||
"b1": p1m3,
|
||||
"b2": p2m3
|
||||
},
|
||||
"variables": {
|
||||
"s1": s1m3,
|
||||
"s2": s2m3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# config_sim Necessary
|
||||
sim_config = config_sim(
|
||||
{
|
||||
"N": 2,
|
||||
"T": range(5),
|
||||
"M": g # Optional
|
||||
"M": g, # Optional
|
||||
}
|
||||
)
|
||||
|
||||
# New Convention
|
||||
partial_state_update_blocks = psub_list(psu_block, psu_steps)
|
||||
append_configs(
|
||||
sim_configs=sim_config,
|
||||
initial_state=genesis_states,
|
||||
seeds=seeds,
|
||||
raw_exogenous_states=raw_exogenous_states,
|
||||
env_processes=env_processes,
|
||||
partial_state_update_blocks=partial_state_update_block
|
||||
env_processes=env_process,
|
||||
partial_state_update_blocks=partial_state_update_blocks
|
||||
)
|
||||
|
||||
|
||||
print()
|
||||
print("Policie State Update Block:")
|
||||
pp.pprint(partial_state_update_blocks)
|
||||
print()
|
||||
print()
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ from functools import reduce
|
|||
|
||||
from cadCAD.utils import SilentDF #, val_switch
|
||||
from cadCAD.configuration import append_configs
|
||||
from cadCAD.configuration.utils import time_step, config_sim, proc_trigger, timestep_trigger, genereate_psubs
|
||||
from cadCAD.configuration.utils import time_step, config_sim, var_trigger, var_substep_trigger, genereate_psubs, \
|
||||
env_trigger, psub_list
|
||||
from cadCAD.configuration.utils.userDefinedObject import udoPipe, UDO
|
||||
import pandas as pd
|
||||
|
||||
|
|
@ -69,32 +70,36 @@ state_dict = {
|
|||
'timestamp': '2019-01-01 00:00:00'
|
||||
}
|
||||
|
||||
policies, state_updates = {}, {}
|
||||
#
|
||||
# def assign_udo_policy(udo):
|
||||
# def policy(_g, step, sL, s):
|
||||
# s['udo_policies'][udo].updateX()
|
||||
# return {udo: udoPipe(s['udo_policies'][udo])}
|
||||
# return policy
|
||||
# policies_updates = {p: assign_udo_policy(udo) for p, udo in zip(['p1', 'p2'], ['udo_A', 'udo_B'])}
|
||||
psu_steps = ['m1', 'm2', 'm3']
|
||||
system_substeps = len(psu_steps)
|
||||
var_timestep_trigger = var_substep_trigger([0, system_substeps])
|
||||
env_timestep_trigger = env_trigger(system_substeps)
|
||||
psu_block = {k: {"policies": {}, "variables": {}} for k in psu_steps}
|
||||
|
||||
def udo_policyA(_g, step, sL, s):
|
||||
s['udo_policies']['udo_A'].updateX()
|
||||
return {'udo_A': udoPipe(s['udo_policies']['udo_A'])}
|
||||
policies['a'] = udo_policyA
|
||||
# policies['a'] = udo_policyA
|
||||
for m in psu_steps:
|
||||
psu_block[m]['policies']['a'] = udo_policyA
|
||||
|
||||
def udo_policyB(_g, step, sL, s):
|
||||
s['udo_policies']['udo_B'].updateX()
|
||||
return {'udo_B': udoPipe(s['udo_policies']['udo_B'])}
|
||||
policies['b'] = udo_policyB
|
||||
# policies['b'] = udo_policyB
|
||||
for m in psu_steps:
|
||||
psu_block[m]['policies']['b'] = udo_policyB
|
||||
|
||||
|
||||
# policies = {"p1": udo_policyA, "p2": udo_policyB}
|
||||
# policies = {"A": udo_policyA, "B": udo_policyB}
|
||||
|
||||
# def increment_state_by_int(y: str, incr_by: int):
|
||||
# return lambda _g, step, sL, s, _input: (y, s[y] + incr_by)
|
||||
state_updates['increment'] = add('increment', 1)
|
||||
def add(y: str, added_val):
|
||||
return lambda _g, step, sL, s, _input: (y, s[y] + added_val)
|
||||
# state_updates['increment'] = add('increment', 1)
|
||||
for m in psu_steps:
|
||||
psu_block[m]["variables"]['increment'] = add('increment', 1)
|
||||
|
||||
|
||||
@curried
|
||||
def perceive(s, self):
|
||||
|
|
@ -110,12 +115,15 @@ def state_udo_update(_g, step, sL, s, _input):
|
|||
s['state_udo'].updateX().perceive(s)
|
||||
x = udoPipe(s['state_udo'])
|
||||
return y, x
|
||||
state_updates['state_udo'] = state_udo_update
|
||||
for m in psu_steps:
|
||||
psu_block[m]["variables"]['state_udo'] = state_udo_update
|
||||
|
||||
|
||||
def track(destination, source):
|
||||
return lambda _g, step, sL, s, _input: (destination, s[source].x)
|
||||
state_updates['state_udo_tracker'] = track('state_udo_tracker', 'state_udo')
|
||||
state_udo_tracker = track('state_udo_tracker', 'state_udo')
|
||||
for m in psu_steps:
|
||||
psu_block[m]["variables"]['state_udo_tracker'] = state_udo_tracker
|
||||
|
||||
|
||||
def track_state_udo_perception(destination, source):
|
||||
|
|
@ -125,12 +133,15 @@ def track_state_udo_perception(destination, source):
|
|||
else:
|
||||
return past_perception
|
||||
return lambda _g, step, sL, s, _input: (destination, id(s[source].perception))
|
||||
state_updates['state_udo_perception_tracker'] = track_state_udo_perception('state_udo_perception_tracker', 'state_udo')
|
||||
state_udo_perception_tracker = track_state_udo_perception('state_udo_perception_tracker', 'state_udo')
|
||||
for m in psu_steps:
|
||||
psu_block[m]["variables"]['state_udo_perception_tracker'] = state_udo_perception_tracker
|
||||
|
||||
|
||||
def view_udo_policy(_g, step, sL, s, _input):
|
||||
return 'udo_policies', _input
|
||||
state_updates['udo_policies'] = view_udo_policy
|
||||
for m in psu_steps:
|
||||
psu_block[m]["variables"]['udo_policies'] = view_udo_policy
|
||||
|
||||
|
||||
def track_udo_policy(destination, source):
|
||||
|
|
@ -140,56 +151,32 @@ def track_udo_policy(destination, source):
|
|||
else:
|
||||
return v.x
|
||||
return lambda _g, step, sL, s, _input: (destination, tuple(val_switch(v) for _, v in s[source].items()))
|
||||
state_updates['udo_policy_tracker'] = track_udo_policy('udo_policy_tracker', 'udo_policies')
|
||||
udo_policy_tracker = track_udo_policy('udo_policy_tracker', 'udo_policies')
|
||||
for m in psu_steps:
|
||||
psu_block[m]["variables"]['udo_policy_tracker'] = udo_policy_tracker
|
||||
|
||||
|
||||
def update_timestamp(_g, step, sL, s, _input):
|
||||
y = 'timestamp'
|
||||
return y, time_step(dt_str=s[y], dt_format='%Y-%m-%d %H:%M:%S', _timedelta=timedelta(days=0, minutes=0, seconds=1))
|
||||
for m in psu_steps:
|
||||
psu_block[m]["variables"]['timestamp'] = var_timestep_trigger(y='timestamp', f=update_timestamp)
|
||||
# psu_block[m]["variables"]['timestamp'] = var_trigger(
|
||||
# y='timestamp', f=update_timestamp,
|
||||
# pre_conditions={'substep': [0, system_substeps]}, cond_op=lambda a, b: a and b
|
||||
# )
|
||||
# psu_block[m]["variables"]['timestamp'] = update_timestamp
|
||||
|
||||
|
||||
system_substeps = 3
|
||||
# state_updates['timestamp'] = update_timestamp
|
||||
state_updates['timestamp'] = timestep_trigger(end_substep=system_substeps, y='timestamp', f=update_timestamp)
|
||||
# state_updates['timestamp'] = proc_trigger(y='timestamp', f=update_timestamp, conditions={'substep': [0, substeps]}, cond_op=lambda a, b: a and b)
|
||||
|
||||
print()
|
||||
print("State Updates:")
|
||||
pp.pprint(state_updates)
|
||||
print()
|
||||
print("Policies:")
|
||||
pp.pprint(policies)
|
||||
print()
|
||||
|
||||
filter_out = lambda remove_list, state_list: list(filter(lambda state: state not in remove_list, state_list))
|
||||
|
||||
states = list(state_updates.keys())
|
||||
# states_noTS = filter_out(['timestamp'], states)
|
||||
# states_grid = [states,states_noTS,states_noTS]
|
||||
|
||||
# states_grid = [states] * system_substeps #
|
||||
states_grid = [states,states,states]
|
||||
policy_grid = [['a', 'b'], ['a', 'b'], ['a', 'b']]
|
||||
|
||||
|
||||
PSUBS = genereate_psubs(policy_grid, states_grid, policies, state_updates)
|
||||
pp.pprint(PSUBS)
|
||||
# ToDo: Bug without specifying parameters
|
||||
# New Convention
|
||||
partial_state_update_blocks = psub_list(psu_block, psu_steps)
|
||||
append_configs(
|
||||
sim_configs=sim_config,
|
||||
initial_state=state_dict,
|
||||
seeds={},
|
||||
raw_exogenous_states={},
|
||||
env_processes={},
|
||||
partial_state_update_blocks=PSUBS,
|
||||
# policy_ops=[lambda a, b: {**a, **b}]
|
||||
partial_state_update_blocks=partial_state_update_blocks
|
||||
)
|
||||
|
||||
# pp.pprint(partial_state_update_blocks)
|
||||
|
||||
# PSUB = {
|
||||
# 'policies': policies,
|
||||
# 'states': state_updates
|
||||
# }
|
||||
# partial_state_update_blocks = [PSUB] * substeps
|
||||
|
||||
|
||||
print()
|
||||
print("State Updates:")
|
||||
pp.pprint(partial_state_update_blocks)
|
||||
print()
|
||||
|
|
@ -5,7 +5,7 @@ from cadCAD.configuration import append_configs
|
|||
from cadCAD.configuration.utils import time_step, ep_time_step, config_sim
|
||||
from cadCAD.configuration.utils.userDefinedObject import udoPipe, UDO
|
||||
import pandas as pd
|
||||
|
||||
import pprint as pp
|
||||
from fn.func import curried
|
||||
|
||||
DF = SilentDF(pd.read_csv('/Users/jjodesty/Projects/DiffyQ-SimCAD/simulations/external_data/output.csv'))
|
||||
|
|
@ -161,3 +161,8 @@ append_configs(
|
|||
partial_state_update_blocks=partial_state_update_blocks,
|
||||
# policy_ops=[lambda a, b: {**a, **b}]
|
||||
)
|
||||
|
||||
print()
|
||||
print("State Updates:")
|
||||
pp.pprint(partial_state_update_blocks)
|
||||
print()
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
from cadCAD.configuration import append_configs
|
||||
from cadCAD.configuration.utils.userDefinedObject import udoPipe, UDO
|
||||
import networkx as nx
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
|
@ -21,11 +22,98 @@ for node in G.nodes:
|
|||
scale=100
|
||||
nx.draw_kamada_kawai(G, node_size=balls*scale,labels=nx.get_node_attributes(G,'initial_balls'))
|
||||
|
||||
initial_conditions = {'balls': balls, 'network': G}
|
||||
def greedy_robot(src_balls, dst_balls):
|
||||
# robot wishes to accumlate balls at its source
|
||||
# takes half of its neighbors balls
|
||||
if src_balls < dst_balls:
|
||||
return -np.floor(dst_balls / 2)
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
def fair_robot(src_balls, dst_balls):
|
||||
# robot follows the simple balancing rule
|
||||
return np.sign(src_balls - dst_balls)
|
||||
|
||||
|
||||
def giving_robot(src_balls, dst_balls):
|
||||
# robot wishes to gice away balls one at a time
|
||||
if src_balls > 0:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
robot_strategies = [greedy_robot,fair_robot, giving_robot]
|
||||
|
||||
for node in G.nodes:
|
||||
nstrats = len(robot_strategies)
|
||||
rv = np.random.randint(0,nstrats)
|
||||
G.nodes[node]['strat'] = robot_strategies[rv]
|
||||
|
||||
for e in G.edges:
|
||||
owner_node = e[0]
|
||||
G.edges[e]['strat'] = G.nodes[owner_node]['strat']
|
||||
|
||||
default_policy = {'nodes': [], 'edges': {}, 'quantity': {}, 'node_strats': {}, 'edge_strats': {}, 'delta': {}}
|
||||
class robot(object):
|
||||
def __init__(self, graph, balls, internal_policy=default_policy):
|
||||
self.mem_id = str(hex(id(self)))
|
||||
self.internal_policy = internal_policy
|
||||
self.graph = graph
|
||||
self.balls = balls
|
||||
|
||||
|
||||
def robotic_network(self, graph, balls): # move balls
|
||||
self.graph, self.balls = graph, balls
|
||||
delta_balls = {}
|
||||
for e in self.graph.edges:
|
||||
src = e[0]
|
||||
src_balls = self.balls[src]
|
||||
dst = e[1]
|
||||
dst_balls = self.balls[dst]
|
||||
|
||||
# transfer balls according to specific robot strat
|
||||
strat = self.graph.edges[e]['strat']
|
||||
delta_balls[e] = strat(src_balls, dst_balls)
|
||||
|
||||
self.internal_policy = {'nodes': [], 'edges': {}, 'quantity': {}, 'node_strats': {}, 'edge_strats': {}, 'delta': delta_balls}
|
||||
return self
|
||||
|
||||
def agent_arrival(self, graph, balls): # add node
|
||||
self.graph, self.balls = graph, balls
|
||||
node = len(self.graph.nodes)
|
||||
edge_list = self.graph.edges
|
||||
|
||||
# choose a m random edges without replacement
|
||||
# new = np.random.choose(edgelist,m)
|
||||
new = [0, 1] # tester
|
||||
|
||||
nodes = [node]
|
||||
edges = [(node, new_node) for new_node in new]
|
||||
|
||||
initial_balls = {node: np.random.randint(1, 25)}
|
||||
|
||||
rv = np.random.randint(0, nstrats)
|
||||
node_strat = {node: robot_strategies[rv]}
|
||||
|
||||
edge_strats = {e: robot_strategies[rv] for e in edges}
|
||||
|
||||
self.internal_policy = {'nodes': nodes,
|
||||
'edges': edges,
|
||||
'quantity': initial_balls,
|
||||
'node_strats': node_strat,
|
||||
'edge_strats': edge_strats,
|
||||
'delta': np.zeros(node + 1)
|
||||
}
|
||||
|
||||
return self
|
||||
|
||||
robot_udo = UDO(udo=robot(G, balls), masked_members=['obj'])
|
||||
initial_conditions = {'balls': balls, 'network': G, 'robot': robot_udo}
|
||||
|
||||
|
||||
def update_balls(params, step, sL, s, _input):
|
||||
delta_balls = _input['delta']
|
||||
delta_balls = _input['robot'].internal_policy['delta']
|
||||
new_balls = s['balls']
|
||||
for e in G.edges:
|
||||
move_ball = delta_balls[e]
|
||||
|
|
@ -42,20 +130,20 @@ def update_balls(params, step, sL, s, _input):
|
|||
|
||||
|
||||
def update_network(params, step, sL, s, _input):
|
||||
new_nodes = _input['nodes']
|
||||
new_edges = _input['edges']
|
||||
new_balls = _input['quantity']
|
||||
new_nodes = _input['robot'].internal_policy['nodes']
|
||||
new_edges = _input['robot'].internal_policy['edges']
|
||||
new_balls = _input['robot'].internal_policy['quantity']
|
||||
|
||||
graph = s['network']
|
||||
|
||||
for node in new_nodes:
|
||||
graph.add_node(node)
|
||||
graph.nodes[node]['initial_balls'] = new_balls[node]
|
||||
graph.nodes[node]['strat'] = _input['node_strats'][node]
|
||||
graph.nodes[node]['strat'] = _input['robot'].internal_policy['node_strats'][node]
|
||||
|
||||
for edge in new_edges:
|
||||
graph.add_edge(edge[0], edge[1])
|
||||
graph.edges[edge]['strat'] = _input['edge_strats'][edge]
|
||||
graph.edges[edge]['strat'] = _input['robot'].internal_policy['edge_strats'][edge]
|
||||
|
||||
key = 'network'
|
||||
value = graph
|
||||
|
|
@ -63,8 +151,8 @@ def update_network(params, step, sL, s, _input):
|
|||
|
||||
|
||||
def update_network_balls(params, step, sL, s, _input):
|
||||
new_nodes = _input['nodes']
|
||||
new_balls = _input['quantity']
|
||||
new_nodes = _input['robot'].internal_policy['nodes']
|
||||
new_balls = _input['robot'].internal_policy['quantity']
|
||||
balls = np.zeros(len(s['balls']) + len(new_nodes))
|
||||
|
||||
for node in s['network'].nodes:
|
||||
|
|
@ -79,91 +167,17 @@ def update_network_balls(params, step, sL, s, _input):
|
|||
return (key, value)
|
||||
|
||||
|
||||
def greedy_robot(src_balls, dst_balls):
|
||||
# robot wishes to accumlate balls at its source
|
||||
# takes half of its neighbors balls
|
||||
if src_balls < dst_balls:
|
||||
delta = -np.floor(dst_balls / 2)
|
||||
else:
|
||||
delta = 0
|
||||
|
||||
return delta
|
||||
|
||||
|
||||
def fair_robot(src_balls, dst_balls):
|
||||
# robot follows the simple balancing rule
|
||||
delta = np.sign(src_balls - dst_balls)
|
||||
|
||||
return delta
|
||||
|
||||
|
||||
def giving_robot(src_balls, dst_balls):
|
||||
# robot wishes to gice away balls one at a time
|
||||
if src_balls > 0:
|
||||
delta = 1
|
||||
else:
|
||||
delta = 0
|
||||
|
||||
return delta
|
||||
|
||||
robot_strategies = [greedy_robot,fair_robot, giving_robot]
|
||||
|
||||
for node in G.nodes:
|
||||
nstrats = len(robot_strategies)
|
||||
rv = np.random.randint(0,nstrats)
|
||||
G.nodes[node]['strat'] = robot_strategies[rv]
|
||||
|
||||
for e in G.edges:
|
||||
owner_node = e[0]
|
||||
G.edges[e]['strat'] = G.nodes[owner_node]['strat']
|
||||
|
||||
|
||||
def robotic_network(params, step, sL, s):
|
||||
graph = s['network']
|
||||
|
||||
delta_balls = {}
|
||||
for e in graph.edges:
|
||||
src = e[0]
|
||||
src_balls = s['balls'][src]
|
||||
dst = e[1]
|
||||
dst_balls = s['balls'][dst]
|
||||
|
||||
# transfer balls according to specific robot strat
|
||||
strat = graph.edges[e]['strat']
|
||||
delta_balls[e] = strat(src_balls, dst_balls)
|
||||
|
||||
return_dict = {'nodes': [], 'edges': {}, 'quantity': {}, 'node_strats': {}, 'edge_strats': {}, 'delta': delta_balls}
|
||||
|
||||
return (return_dict)
|
||||
s['robot'].robotic_network(s['network'], s['balls'])
|
||||
return {'robot': udoPipe(s['robot'])}
|
||||
|
||||
|
||||
def agent_arrival(params, step, sL, s):
|
||||
node = len(s['network'].nodes)
|
||||
edge_list = s['network'].edges
|
||||
|
||||
# choose a m random edges without replacement
|
||||
# new = np.random.choose(edgelist,m)
|
||||
new = [0, 1] # tester
|
||||
|
||||
nodes = [node]
|
||||
edges = [(node, new_node) for new_node in new]
|
||||
|
||||
initial_balls = {node: np.random.randint(1, 25)}
|
||||
|
||||
rv = np.random.randint(0, nstrats)
|
||||
node_strat = {node: robot_strategies[rv]}
|
||||
|
||||
edge_strats = {e: robot_strategies[rv] for e in edges}
|
||||
|
||||
return_dict = {'nodes': nodes,
|
||||
'edges': edges,
|
||||
'quantity': initial_balls,
|
||||
'node_strats': node_strat,
|
||||
'edge_strats': edge_strats,
|
||||
'delta': np.zeros(node + 1)
|
||||
}
|
||||
return (return_dict)
|
||||
s['robot'].agent_arrival(s['network'], s['balls'])
|
||||
return {'robot': udoPipe(s['robot'])}
|
||||
|
||||
def get_robot(params, step, sL, s, _input):
|
||||
return 'robot', _input['robot']
|
||||
|
||||
partial_state_update_blocks = [
|
||||
{
|
||||
|
|
@ -172,7 +186,8 @@ partial_state_update_blocks = [
|
|||
'p1': robotic_network
|
||||
},
|
||||
'variables': { # The following state variables will be updated simultaneously
|
||||
'balls': update_balls
|
||||
'balls': update_balls,
|
||||
'robot': get_robot
|
||||
|
||||
}
|
||||
},
|
||||
|
|
@ -183,7 +198,8 @@ partial_state_update_blocks = [
|
|||
},
|
||||
'variables': { # The following state variables will be updated simultaneously
|
||||
'network': update_network,
|
||||
'balls': update_network_balls
|
||||
'balls': update_network_balls,
|
||||
'robot': get_robot
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -2,7 +2,6 @@ import pandas as pd
|
|||
from tabulate import tabulate
|
||||
# The following imports NEED to be in the exact order
|
||||
from cadCAD.engine import ExecutionMode, ExecutionContext, Executor
|
||||
from simulations.validation import marbles2
|
||||
from cadCAD import configs
|
||||
|
||||
exec_mode = ExecutionMode()
|
||||
|
|
@ -20,6 +19,7 @@ print("Tensor Field: config1")
|
|||
print(tabulate(tensor_field, headers='keys', tablefmt='psql'))
|
||||
print("Output:")
|
||||
print(tabulate(result, headers='keys', tablefmt='psql'))
|
||||
print(result[['network']])
|
||||
print()
|
||||
|
||||
print(result[['network', 'substep']])
|
||||
|
|
@ -2,10 +2,9 @@ import pandas as pd
|
|||
from tabulate import tabulate
|
||||
# The following imports NEED to be in the exact order
|
||||
from cadCAD.engine import ExecutionMode, ExecutionContext, Executor
|
||||
from simulations.validation import udo
|
||||
from simulations.regression_tests import udo_inter_substep_update
|
||||
from cadCAD import configs
|
||||
|
||||
|
||||
exec_mode = ExecutionMode()
|
||||
|
||||
print("Simulation Execution: Single Configuration")
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ from cadCAD.engine import ExecutionMode, ExecutionContext, Executor
|
|||
from simulations.regression_tests import udo
|
||||
from cadCAD import configs
|
||||
|
||||
|
||||
exec_mode = ExecutionMode()
|
||||
|
||||
print("Simulation Execution: Single Configuration")
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
from cadCAD.configuration import append_configs
|
||||
from cadCAD.configuration.utils import config_sim
|
||||
|
||||
# Policies per Mechanism
|
||||
# def p(_g, substep, sH, s):
|
||||
# return {'last_update_block': sH[-1]}
|
||||
|
||||
# def policies(_g, substep, sH, s, _input):
|
||||
# y = 'policies'
|
||||
# x = _input
|
||||
# return (y, x)
|
||||
|
||||
# policies = {"p1": p, "p2": p}
|
||||
|
||||
|
||||
# last_partial_state_update_block
|
||||
def last_update_block(_g, substep, sH, s, _input):
|
||||
return 'sh', sH[-1]
|
||||
|
||||
|
||||
# Policies per Mechanism
|
||||
def p(_g, substep, sH, s):
|
||||
return {'last_update_block': sH[-1]}
|
||||
|
||||
def add(y, x):
|
||||
return lambda _g, substep, sH, s, _input: (y, s[y] + x)
|
||||
|
||||
def policies(_g, substep, sH, s, _input):
|
||||
y = 'policies'
|
||||
x = _input
|
||||
return (y, x)
|
||||
|
||||
policies = {"p1": p, "p2": p}
|
||||
|
||||
genesis_states = {
|
||||
's': 0,
|
||||
'sh': [{}], # {[], {}}
|
||||
|
|
@ -34,7 +34,7 @@ variables = {
|
|||
|
||||
|
||||
PSUB = {
|
||||
"policies": policies,
|
||||
"policies": {}, #policies,
|
||||
"variables": variables
|
||||
}
|
||||
|
||||
|
|
@ -58,6 +58,5 @@ append_configs(
|
|||
seeds={},
|
||||
raw_exogenous_states={},
|
||||
env_processes={},
|
||||
partial_state_update_blocks=partial_state_update_block,
|
||||
policy_ops=[lambda a, b: a + b]
|
||||
partial_state_update_blocks=partial_state_update_block
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue