diff --git a/SimCAD/configuration/utils/__init__.py b/SimCAD/configuration/utils/__init__.py index 4a6cba6..b9f820f 100644 --- a/SimCAD/configuration/utils/__init__.py +++ b/SimCAD/configuration/utils/__init__.py @@ -5,8 +5,8 @@ from fn.func import curried import pandas as pd from SimCAD.utils import rename -from SimCAD.utils import groupByKey, dict_filter, contains_type -from SimCAD.utils import flatMap +from SimCAD.utils import dict_filter, contains_type, curry_pot + from funcy import curry @@ -116,24 +116,11 @@ def sweep_states(state_type, states, in_config): return configs -def param_sweep(config, raw_exogenous_states): - return flatMap( - sweep_states('environmental', config.env_processes), - flatMap( - sweep_states('exogenous', raw_exogenous_states), - flatMap( - sweep_mechs('states'), - sweep_mechs('behaviors', config) - ) - ) - ) - - def exo_update_per_ts(ep): @curried def ep_decorator(f, y, step, sL, s, _input): if s['mech_step'] + 1 == 1: - return f(step, sL, s, _input) + return curry_pot(f, step, sL, s, _input) else: return (y, s[y]) @@ -143,6 +130,7 @@ def exo_update_per_ts(ep): def sweep(params, sweep_f): return [rename("sweep_"+sweep_f.__name__+"_"+str(i), curry(sweep_f)(param)) for param, i in zip(params, range(len(params)))] + def zip_sweep_functions(sweep_lists): zipped_sweep_lists = [] it = iter(sweep_lists) @@ -157,7 +145,8 @@ def zip_sweep_functions(sweep_lists): raise ValueError('lists have different lengths!') -def create_sweep_config_list(zipped_sweep_lists, states_dict, state_type_ind = 'mechs'): +# ToDo: Not producing multiple dicts +def create_sweep_config_list(zipped_sweep_lists, states_dict, state_type_ind='mechs'): configs = [] for f_lists in zipped_sweep_lists: new_states_dict = deepcopy(states_dict) @@ -187,6 +176,8 @@ def create_sweep_config_list(zipped_sweep_lists, states_dict, state_type_ind = ' def parameterize_states(exo_states): + pp.pprint(exo_states) + print() sweep_lists = [] for sk, vfs in exo_states.items(): id_sweep_lists = [] @@ -199,6 +190,9 @@ def parameterize_states(exo_states): if len(sweep_lists) == 0: return [exo_states] + pp.pprint(sweep_lists) + print() + zipped_sweep_lists = zip_sweep_functions(sweep_lists) states_configs = create_sweep_config_list(zipped_sweep_lists, exo_states, "exo_proc") diff --git a/SimCAD/engine/simulation.py b/SimCAD/engine/simulation.py index 992ac66..3724a76 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 id_exception = engine_exception(KeyError, KeyError, None) @@ -11,31 +12,14 @@ class Executor: self.state_update_exception = state_update_exception self.behavior_update_exception = behavior_update_exception - - def curry_pot(self, f, *argv): - sweep_ind = f.__name__[0:5] == 'sweep' - arg_len = len(argv) - if sweep_ind == True and arg_len == 4: - return f(argv[0])(argv[1])(argv[2])(argv[3]) - elif sweep_ind == False and arg_len == 4: - return f(argv[0], argv[1], argv[2], argv[3]) - elif sweep_ind == True and arg_len == 3: - return f(argv[0])(argv[1])(argv[2]) - elif sweep_ind == False and arg_len == 3: - return f(argv[0], argv[1], argv[2]) - else: - raise TypeError('curry_pot() needs 3 or 4 positional arguments') - - def get_behavior_input(self, step, sL, s, funcs): ops = self.behavior_ops[::-1] def get_col_results(step, sL, s, funcs): - return list(map(lambda f: self.curry_pot(f, step, sL, s), funcs)) + return list(map(lambda f: curry_pot(f, step, sL, s), funcs)) return foldr(call, get_col_results(step, sL, s, funcs))(ops) - def apply_env_proc(self, env_processes, state_dict, step): for state in state_dict.keys(): if state in list(env_processes.keys()): @@ -45,7 +29,6 @@ class Executor: else: state_dict[state] = env_state(state_dict[state]) - def mech_step(self, m_step, sL, state_funcs, behavior_funcs, env_processes, t_step, run): last_in_obj = sL[-1] @@ -53,14 +36,11 @@ class Executor: # print(_input) # ToDo: add env_proc generator to `last_in_copy` iterator as wrapper function - # last_in_copy = [self.behavior_update_exception(f(m_step, sL, last_in_obj, _input)) for f in state_funcs] last_in_copy = dict( [ - self.behavior_update_exception(self.curry_pot(f, m_step, sL, last_in_obj, _input)) for f in state_funcs + self.behavior_update_exception(curry_pot(f, m_step, sL, last_in_obj, _input)) for f in state_funcs ] ) - # print(last_in_copy) - for k in last_in_obj: if k not in last_in_copy: @@ -97,7 +77,6 @@ class Executor: def block_pipeline(self, states_list, configs, env_processes, time_seq, run): time_seq = [x + 1 for x in time_seq] simulation_list = [states_list] - # print(len(configs)) for time_step in time_seq: pipe_run = self.mech_pipeline(simulation_list[-1], configs, env_processes, time_step, run) _, *pipe_run = pipe_run diff --git a/SimCAD/utils/__init__.py b/SimCAD/utils/__init__.py index af0ad03..ade0424 100644 --- a/SimCAD/utils/__init__.py +++ b/SimCAD/utils/__init__.py @@ -1,6 +1,5 @@ from collections import defaultdict from itertools import product -# from fn.func import curried def pipe(x): @@ -47,14 +46,13 @@ def contains_type(_collection, type): def drop_right(l, n): - return l[:len(l)-n] + return l[:len(l) - n] def key_filter(l, keyname): return [v[keyname] for k, v in l.items()] - def groupByKey(l): d = defaultdict(list) for key, value in l: @@ -67,6 +65,21 @@ def rename(new_name, f): f.__name__ = new_name return f + +def curry_pot(f, *argv): + sweep_ind = f.__name__[0:5] == 'sweep' + arg_len = len(argv) + if sweep_ind is True and arg_len == 4: + return f(argv[0])(argv[1])(argv[2])(argv[3]) + elif sweep_ind is False and arg_len == 4: + return f(argv[0], argv[1], argv[2], argv[3]) + elif sweep_ind is True and arg_len == 3: + return f(argv[0])(argv[1])(argv[2]) + elif sweep_ind is False and arg_len == 3: + return f(argv[0], argv[1], argv[2]) + else: + raise TypeError('curry_pot() needs 3 or 4 positional arguments') + # def rename(newname): # def decorator(f): # f.__name__ = newname diff --git a/simulations/example_run.py b/simulations/example_run.py index d41d8da..e80c2de 100644 --- a/simulations/example_run.py +++ b/simulations/example_run.py @@ -8,28 +8,28 @@ from SimCAD import configs exec_mode = ExecutionMode() -print("Simulation Execution 1") -print() -first_config = [configs[0]] # from config1 -single_proc_ctx = ExecutionContext(context=exec_mode.single_proc) -run1 = Executor(exec_context=single_proc_ctx, configs=first_config) -run1_raw_result, tensor_field = run1.main() -result = pd.DataFrame(run1_raw_result) -print() -print("Tensor Field:") -print(tabulate(tensor_field, headers='keys', tablefmt='psql')) -print("Output:") -print(tabulate(result, headers='keys', tablefmt='psql')) -print() +# print("Simulation Execution 1") +# print() +# first_config = [configs[0]] # from config1 +# single_proc_ctx = ExecutionContext(context=exec_mode.single_proc) +# run1 = Executor(exec_context=single_proc_ctx, configs=first_config) +# run1_raw_result, tensor_field = run1.main() +# result = pd.DataFrame(run1_raw_result) +# print() +# print("Tensor Field:") +# print(tabulate(tensor_field, headers='keys', tablefmt='psql')) +# print("Output:") +# print(tabulate(result, headers='keys', tablefmt='psql')) +# print() -# print("Simulation Execution 2: Pairwise Execution") -# multi_proc_ctx = ExecutionContext(context=exec_mode.multi_proc) -# run2 = Executor(exec_context=multi_proc_ctx, configs=configs) -# for raw_result, tensor_field in run2.main(): -# result = pd.DataFrame(raw_result) -# print() -# print("Tensor Field:") -# print(tabulate(tensor_field, headers='keys', tablefmt='psql')) -# print("Output:") -# print(tabulate(result, headers='keys', tablefmt='psql')) -# print() +print("Simulation Execution 2: Pairwise Execution") +multi_proc_ctx = ExecutionContext(context=exec_mode.multi_proc) +run2 = Executor(exec_context=multi_proc_ctx, configs=configs) +for raw_result, tensor_field in run2.main(): + result = pd.DataFrame(raw_result) + print() + print("Tensor Field:") + print(tabulate(tensor_field, headers='keys', tablefmt='psql')) + print("Output:") + print(tabulate(result, headers='keys', tablefmt='psql')) + print() diff --git a/simulations/validation/config1.py b/simulations/validation/config1.py index 267f2fb..cab014c 100644 --- a/simulations/validation/config1.py +++ b/simulations/validation/config1.py @@ -1,52 +1,18 @@ from decimal import Decimal import numpy as np from datetime import timedelta -from fn.func import curried import pprint + from SimCAD import configs -from SimCAD.utils import flatMap, rename from SimCAD.configuration import Configuration from SimCAD.configuration.utils import exo_update_per_ts, proc_trigger, bound_norm_random, \ - ep_time_step, parameterize_mechanism, parameterize_states, sweep #parameterize_states - -from copy import deepcopy + ep_time_step, parameterize_mechanism, parameterize_states, sweep pp = pprint.PrettyPrinter(indent=4) # ToDo: handle single param sweep beta = [Decimal(1), Decimal(2)] -# # ------------- -# var_a = [1,2,3] -# var_b = [1,2,3] -# -# -# # Internal States per Mechanism -# def s1m1(step, sL, s, _input): -# # __assumed__ = var_a -# # __handler__ = f -# y = 's1' -# x = _input['param1'] + 1 + var_a -# # example = [_input['param1'], 1, assumed].reduceLeft(_ + _) -# -# return (y, x) -# -# def s2m1(assumed, step, sL, s, _input): -# y = 's2' -# x = _input['param2'] + assumed -# return (y, x) -# -# def s1m3(unused_wildcard, step, sL, s, _input): -# y = 's1' -# x = _input['param1'] -# return (y, x) -# -# -# middleware(beta, [s1m1, s2m2, b1m3, . . . ]) -# -# # ------------- - - seed = { 'z': np.random.RandomState(1), 'a': np.random.RandomState(2), @@ -60,46 +26,35 @@ def b1m1(step, sL, s): return {'param1': 1} def b2m1(step, sL, s): return {'param2': 4} - # @curried def b1m2(param, step, sL, s): return {'param1': 'a', 'param2': param} -# -# def b1m2(step, sL, s): -# return {'param1': 'a', 'param2': 2} def b2m2(step, sL, s): - return {'param1': 'b', 'param2': 4} + return {'param1': 'b', 'param2': 0} def b1m3(step, sL, s): - return {'param1': ['c'], 'param2': np.array([10, 100])} + return {'param1': np.array([10, 100])} def b2m3(step, sL, s): - return {'param1': ['d'], 'param2': np.array([20, 200])} + return {'param1': np.array([20, 200])} # Internal States per Mechanism def s1m1(step, sL, s, _input): y = 's1' - x = _input['param1'] + x = 0 return (y, x) - -# param = Decimal(11.0) -# def s2m1(step, sL, s, _input): -# y = 's2' -# x = _input['param2'] + param -# return (y, x) - # @curried def s2m1(param, step, sL, s, _input): y = 's2' - x = _input['param2'] + param + x = param return (y, x) def s1m2(step, sL, s, _input): y = 's1' - x = _input['param1'] + x = _input['param2'] return (y, x) def s2m2(step, sL, s, _input): y = 's2' @@ -108,22 +63,17 @@ def s2m2(step, sL, s, _input): def s1m3(step, sL, s, _input): y = 's1' - x = _input['param1'] + x = 0 return (y, x) def s2m3(step, sL, s, _input): y = 's2' - x = _input['param2'] + x = 0 return (y, x) # Exogenous States proc_one_coef_A = 0.7 proc_one_coef_B = 1.3 -# -# def es3p1(step, sL, s, _input): -# y = 's3' -# x = s['s3'] * bound_norm_random(seed['a'], proc_one_coef_A, proc_one_coef_B) -# return (y, x) # @curried def es3p1(param, step, sL, s, _input): @@ -146,14 +96,10 @@ def es5p2(step, sL, s, _input): # Environment States # @curried -# def env_a(param, x): -# return x + param -def env_a(x): - return x +def env_a(param, x): + return x + param def env_b(x): return 10 -# def what_ever(x): -# return x + 1 # Genesis States @@ -165,9 +111,6 @@ genesis_states = { 'timestamp': '2018-10-01 15:16:24' } -# print(sweep(beta, es3p1)) -# print() - # remove `exo_update_per_ts` to update every ts raw_exogenous_states = { @@ -175,25 +118,22 @@ raw_exogenous_states = { "s4": sweep(beta, es4p2), "timestamp": es5p2 } -exogenous_states = exo_update_per_ts(raw_exogenous_states) -# pp.pprint(raw_exogenous_states) -# print() - - - -# pp.pprint(parameterize_states(raw_exogenous_states)) -# print() -# exogenous_states['s3'] = rename('parameterized', es3p1) +# exogenous_states_list = list(map(exo_update_per_ts, parameterize_states(raw_exogenous_states))) # ToDo: make env proc trigger field agnostic # ToDo: input json into function renaming __name__ triggered_env_b = proc_trigger('2018-10-01 15:16:25', env_b) + env_processes = { - "s3": env_a, #sweep(beta, env_a, 'env_a'), + "s3": 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 enteren in sweep should be the # of config objs created, # not dependent on the # of times the sweep is applied @@ -212,12 +152,12 @@ mechanisms = { }, "states": { "s1": s1m1, - "s2": sweep(beta, s2m1) #rename('parameterized', s2m1) #s2m1(1) #sweep(beta, s2m1) + "s2": sweep(beta, s2m1) #s2m1(1) #sweep(beta, s2m1) } }, "m2": { "behaviors": { - "b1": sweep(beta, b1m2), #rename('parameterized', b1m2), #b1m2(1) #sweep(beta, b1m2), + "b1": sweep(beta, b1m2), #b1m2(1) #sweep(beta, b1m2), "b2": b2m2 }, "states": { @@ -236,119 +176,21 @@ mechanisms = { } } } - - - -# list(map(lambda x: list(map(lambda y: list(y.keys()).pop(), x)), zipped_sweep_lists)) -# pp.pprint(parameterize_mechanism(mechanisms)) -# print() -# pp.pprint(mechanisms) +parameterized_mechanism = parameterize_mechanism(mechanisms) sim_config = { "N": 2, "T": range(5) } -# for mech_configs in parameterize_mechanism(mechanisms): -configs.append( - Configuration( - sim_config=sim_config, - state_dict=genesis_states, - seed=seed, - exogenous_states=parameterize_states(raw_exogenous_states)[1], - env_processes=env_processes, - mechanisms=parameterize_mechanism(mechanisms)[1] +for mechanisms, env_processes, exogenous_states in zip(parameterized_mechanism, parameterized_env_processes, exogenous_states_list): + configs.append( + Configuration( + sim_config=sim_config, + state_dict=genesis_states, + seed=seed, + exogenous_states=exogenous_states, #parameterize_states(raw_exogenous_states)[1], + env_processes=env_processes, + mechanisms=mechanisms #parameterize_mechanism(mechanisms)[1] + ) ) -) - -# # print(rename('new', b2m2).__name__) -# -# def parameterize_mechanism(mechanisms, param): -# new_mechanisms = deepcopy(mechanisms) -# for mech, update_types in new_mechanisms.items(): -# for update_type, fkv in update_types.items(): -# for sk, vf in fkv.items(): -# if vf.__name__ == 'parameterized': -# # print(vf.__name__) -# new_mechanisms[mech][update_type][sk] = vf(param) -# -# del mechanisms -# return new_mechanisms -# -# def parameterize_states(states_dict, param): -# new_states_dict = deepcopy(states_dict) -# for sk, vf in new_states_dict.items(): -# if vf.__name__ == 'parameterized': -# print(vf.__name__) -# new_states_dict[sk] = vf(param) -# -# del states_dict -# return new_states_dict -# -# # parameterize_mechanism(mechanisms, beta) -# @curried -# def s2m1(param, a, b, c, d): -# y = a -# x = b, + c + d + param -# return (y, x) - -# print(s2m1(1)(1)) -# pp.pprint(mechanisms) -# pp.pprint(parameterize_mechanism(mechanisms, 1)) -# print(sweep(beta, s2m1)) - -# pp.pprint(parameterize_states(raw_exogenous_states, 1)) -# pp.pprint(parameterize_states(env_processes, 1)) - - -# configs.append( -# Configuration( -# sim_config=sim_config, -# state_dict=genesis_states, -# seed=seed, -# exogenous_states=exogenous_states, -# env_processes=env_processes, -# mechanisms=parameterize_mechanism(mechanisms, 1) -# ) -# ) - -# def sweep_config(config, params): -# new_config = deepcopy(config) -# configs = [] -# for param in params: -# new_config.mechanisms = parameterize_mechanism(config.mechanisms, param) -# # new_config.raw_exogenous_states = parameterize_states(config.exogenous_states, param) -# # new_config.env_processes = parameterize_states(config.env_processes, param) -# configs.append(new_config) -# del config -# return configs - - -# print(sweep_config(c, beta)) -# -# for config in sweep_config(c, beta): -# configs.append(config) - -# for config in param_sweep(c, raw_exogenous_states): -# configs.append(config) - - - -# # configs = configs + -# # -# print() -# print(len(configs)) -# print() - - - -# for g in configs: -# print() -# print('Configuration') -# print() -# pp.pprint(g.env_processes) -# print() -# pp.pprint(g.exogenous_states) -# print() -# pp.pprint(g.mechanisms) -# print()