diff --git a/SimCAD/__init__.py b/SimCAD/__init__.py index 0b7fa28..b4234cb 100644 --- a/SimCAD/__init__.py +++ b/SimCAD/__init__.py @@ -1,2 +1,2 @@ name = "SimCAD" -configs = [] +configs = [] \ No newline at end of file diff --git a/SimCAD/configuration/__init__.py b/SimCAD/configuration/__init__.py index d166df3..ab9f5fd 100644 --- a/SimCAD/configuration/__init__.py +++ b/SimCAD/configuration/__init__.py @@ -1,12 +1,13 @@ from functools import reduce from fn.op import foldr import pandas as pd -from fn.func import curried + +from SimCAD import configs +from SimCAD.configuration.utils.parameterSweep import ParamSweep from SimCAD.utils import key_filter from SimCAD.configuration.utils.behaviorAggregation import dict_elemwise_sum -# class ParameterSeep: class Configuration(object): def __init__(self, sim_config=None, state_dict=None, seed=None, env_processes=None, @@ -19,6 +20,28 @@ class Configuration(object): self.mechanisms = mechanisms self.behavior_ops = behavior_ops + +def append_configs(sim_config, genesis_states, seed, raw_exogenous_states, env_processes, mechanisms, _exo_update_per_ts=True): + param_sweep = ParamSweep( + sweep_list=sim_config['M'], + mechs=mechanisms, + raw_exogenous_states=raw_exogenous_states, + _exo_update_per_ts=_exo_update_per_ts + ) + + for mechanisms, exogenous_states in zip(param_sweep.mechanisms(), param_sweep.exogenous_states()): + configs.append( + Configuration( + sim_config=sim_config, + state_dict=genesis_states, + seed=seed, + exogenous_states=exogenous_states, + env_processes=env_processes, + mechanisms=mechanisms + ) + ) + + class Identity: def __init__(self, behavior_id={'identity': 0}): self.beh_id_return_val = behavior_id diff --git a/SimCAD/configuration/utils/__init__.py b/SimCAD/configuration/utils/__init__.py index 3ad5b97..c119190 100644 --- a/SimCAD/configuration/utils/__init__.py +++ b/SimCAD/configuration/utils/__init__.py @@ -3,17 +3,11 @@ from decimal import Decimal from copy import deepcopy from fn.func import curried import pandas as pd -import inspect - -from SimCAD.utils import rename from SimCAD.utils import dict_filter, contains_type, curry_pot -from funcy import curry - -import pprint - -pp = pprint.PrettyPrinter(indent=4) +# import pprint +# pp = pprint.PrettyPrinter(indent=4) class TensorFieldReport: def __init__(self, config_proc): @@ -37,8 +31,8 @@ def state_update(y, x): def bound_norm_random(rng, low, high): - res = rng.normal((high+low)/2,(high-low)/6) - if (reshigh): + res = rng.normal((high+low)/2, (high-low)/6) + if res < low or res > high: res = bound_norm_random(rng, low, high) return Decimal(res) @@ -123,6 +117,6 @@ def exo_update_per_ts(ep): if s['mech_step'] + 1 == 1: return curry_pot(f, step, sL, s, _input) else: - return (y, s[y]) + return y, s[y] return {es: ep_decorator(f, es) for es, f in ep.items()} diff --git a/SimCAD/configuration/utils/behaviorAggregation.py b/SimCAD/configuration/utils/behaviorAggregation.py index fea80a0..a16f5e1 100644 --- a/SimCAD/configuration/utils/behaviorAggregation.py +++ b/SimCAD/configuration/utils/behaviorAggregation.py @@ -37,9 +37,6 @@ def dict_op(f, d1, d2): else: return target_dict[key] - # print(d1) - # print(d2) - # print() key_set = set(list(d1.keys()) + list(d2.keys())) return {k: f(set_base_value(d1, d2, k), set_base_value(d2, d1, k)) for k in key_set} diff --git a/SimCAD/configuration/utils/parameterSweep.py b/SimCAD/configuration/utils/parameterSweep.py index e0467b2..1c9815f 100644 --- a/SimCAD/configuration/utils/parameterSweep.py +++ b/SimCAD/configuration/utils/parameterSweep.py @@ -7,10 +7,11 @@ from SimCAD.configuration.utils import exo_update_per_ts class ParamSweep: - def __init__(self, sweep_list, mechs=None, raw_exogenous_states=None): + def __init__(self, sweep_list, mechs=None, raw_exogenous_states=None, _exo_update_per_ts=True): self.sweep_list = sweep_list self.mechs = mechs self.raw_exogenous_states = raw_exogenous_states + self._exo_update_per_ts = _exo_update_per_ts def mechanisms(self): swept_mechanisms = mech_sweep_identifier(self.sweep_list, self.mechs) @@ -18,7 +19,7 @@ class ParamSweep: def exogenous_states(self): swept_raw_exogenous_states = exo_sweep_identifier(self.sweep_list, self.raw_exogenous_states) - return parameterize_states(swept_raw_exogenous_states) + return parameterize_states(swept_raw_exogenous_states, self._exo_update_per_ts) def sweep(params, sweep_f): @@ -98,9 +99,7 @@ def create_sweep_config_list(zipped_sweep_lists, states_dict, state_type_ind='me return configs -def parameterize_states(exo_states, exo_update=exo_update_per_ts): - # pp.pprint(exo_states) - # print() +def parameterize_states(exo_states, _exo_update_per_ts): sweep_lists = [] for sk, vfs in exo_states.items(): id_sweep_lists = [] @@ -110,21 +109,16 @@ def parameterize_states(exo_states, exo_update=exo_update_per_ts): if len(id_sweep_lists) != 0: sweep_lists.append(id_sweep_lists) + def comp_exo_update(states_configs): + return [exo_update_per_ts(x) if _exo_update_per_ts is True else x for x in states_configs] + sweep_lists_len = len(sweep_lists) if sweep_lists_len != 0: zipped_sweep_lists = zip_sweep_functions(sweep_lists) states_configs = create_sweep_config_list(zipped_sweep_lists, exo_states, "exo_proc") - # pp.pprint(sweep_lists) - # print() - if exo_update == exo_update_per_ts: - return list(map(exo_update_per_ts, states_configs)) - elif exo_update != exo_update_per_ts: - return states_configs - - elif sweep_lists_len == 0 and exo_update == exo_update_per_ts: - return list(map(exo_update_per_ts, [exo_states])) - elif sweep_lists_len == 0 and exo_update != exo_update_per_ts: - return [exo_states] + return comp_exo_update(states_configs) + elif sweep_lists_len == 0: + return comp_exo_update([exo_states]) def parameterize_mechanism(mechanisms): diff --git a/SimCAD/engine/simulation.py b/SimCAD/engine/simulation.py index e03fd61..0d8de63 100644 --- a/SimCAD/engine/simulation.py +++ b/SimCAD/engine/simulation.py @@ -1,5 +1,6 @@ from copy import deepcopy from fn.op import foldr, call + from SimCAD.utils import curry_pot from SimCAD.engine.utils import engine_exception diff --git a/SimCAD/engine/utils.py b/SimCAD/engine/utils.py index be4ddfb..2e569b8 100644 --- a/SimCAD/engine/utils.py +++ b/SimCAD/engine/utils.py @@ -1,7 +1,5 @@ from datetime import datetime from fn.func import curried -from SimCAD.utils import rename -# from SimCAD.configuration.utils import s_update def datetime_range(start, end, delta, dt_format='%Y-%m-%d %H:%M:%S'): diff --git a/simulations/example_run.py b/simulations/example_run.py index 1109322..f017646 100644 --- a/simulations/example_run.py +++ b/simulations/example_run.py @@ -1,9 +1,10 @@ import pandas as pd from tabulate import tabulate - +from importlib import reload # The following imports NEED to be in the exact order from SimCAD.engine import ExecutionMode, ExecutionContext, Executor from simulations.validation import config1 #, config2 + from SimCAD import configs exec_mode = ExecutionMode() diff --git a/simulations/validation/config1.py b/simulations/validation/config1.py index abb1211..ad7630d 100644 --- a/simulations/validation/config1.py +++ b/simulations/validation/config1.py @@ -3,18 +3,11 @@ import numpy as np from datetime import timedelta import pprint -from SimCAD import configs -from SimCAD.configuration import Configuration -from SimCAD.configuration.utils import proc_trigger, bound_norm_random, \ - ep_time_step -from SimCAD.configuration.utils.parameterSweep import ParamSweep - +from SimCAD.configuration import append_configs, Configuration +from SimCAD.configuration.utils import proc_trigger, bound_norm_random, ep_time_step, exo_update_per_ts pp = pprint.PrettyPrinter(indent=4) -# ToDo: handle single param sweep -beta = [Decimal(1), Decimal(2)] - seed = { 'z': np.random.RandomState(1), 'a': np.random.RandomState(2), @@ -24,17 +17,15 @@ seed = { # Behaviors per Mechanism -# @curried def b1m1(step, sL, s): return {'param1': 1} -# @curried + def b2m1(step, sL, s): return {'param2': 4} -# @curried def b1m2(_beta, step, sL, s): return {'param1': 'a', 'param2': _beta} -# @curried + def b2m2(step, sL, s): return {'param1': 'b', 'param2': 0} # @curried @@ -44,7 +35,6 @@ def b1m3(step, sL, s): def b2m3(step, sL, s): return {'param1': np.array([20, 200])} - # Internal States per Mechanism # @curried def s1m1(step, sL, s, _input): @@ -52,33 +42,26 @@ def s1m1(step, sL, s, _input): x = 0 return (y, x) -# @curried def s2m1(sweep_param, step, sL, s, _input): y = 's2' x = sweep_param return (y, x) -# -# def s2m1(step, sL, s, _input): -# y = 's2' -# x = 0 -# return (y, x) -# @curried def s1m2(step, sL, s, _input): y = 's1' x = _input['param2'] return (y, x) -# @curried + def s2m2(step, sL, s, _input): y = 's2' x = _input['param2'] return (y, x) -# @curried + def s1m3(step, sL, s, _input): y = 's1' x = 0 return (y, x) -# @curried + def s2m3(step, sL, s, _input): y = 's2' x = 0 @@ -89,20 +72,19 @@ def s2m3(step, sL, s, _input): proc_one_coef_A = 0.7 proc_one_coef_B = 1.3 -# @curried + def es3p1(param, step, sL, s, _input): y = 's3' - x = s['s3'] + param + x = param return (y, x) # @curried def es4p2(param, step, sL, s, _input): y = 's4' - x = s['s4'] * bound_norm_random(seed['b'], proc_one_coef_A, proc_one_coef_B) + param + x = param return (y, x) ts_format = '%Y-%m-%d %H:%M:%S' t_delta = timedelta(days=0, minutes=0, seconds=1) -# @curried def es5p2(step, sL, s, _input): y = 'timestamp' x = ep_time_step(s, dt_str=s['timestamp'], fromat_str=ts_format, _timedelta=t_delta) @@ -156,9 +138,6 @@ env_processes = { # sweep exo_state func and point to exo-state in every other funtion # param sweep on genesis states -# need at least 1 behaviour and 1 state function for the 1st mech with behaviors -# mechanisms = {} - mechanisms = { "m1": { "behaviors": { @@ -192,38 +171,18 @@ mechanisms = { } } -# ToDo: inspect **** -# ToDo: code block regenerator abstracted from user: input config module with params as convention, output it not as convention, - -# ToDo: make ParamSweep a part of sim_config sim_config = { "N": 2, - "T": range(5) - # beta + "T": range(5), + "M": [Decimal(1), Decimal(2), Decimal(3)] } -# beta = [1,2] -# Test -# def(beta, a, b, c): -# return a + b + beta + beta - -# ToDo: and/or, or not working -# ToDo: Abstract ParamSweep away from user -param_sweep = ParamSweep( - sweep_list=beta, - mechs=mechanisms, - raw_exogenous_states=raw_exogenous_states +append_configs( + sim_config=sim_config, + genesis_states=genesis_states, + seed=seed, + raw_exogenous_states=raw_exogenous_states, + env_processes=env_processes, + mechanisms=mechanisms, + _exo_update_per_ts=True #Default ) - -# ToDo: Make loop standard by returning single elems from ParamSweep if sweep not specified -for mechanisms, exogenous_states in zip(param_sweep.mechanisms(), param_sweep.exogenous_states()): - configs.append( - Configuration( - sim_config=sim_config, - state_dict=genesis_states, - seed=seed, - exogenous_states=exogenous_states, - env_processes=env_processes, - mechanisms=mechanisms - ) - )