diff --git a/SimCAD/configuration/utils/__init__.py b/SimCAD/configuration/utils/__init__.py index ff1bade..4a6cba6 100644 --- a/SimCAD/configuration/utils/__init__.py +++ b/SimCAD/configuration/utils/__init__.py @@ -143,11 +143,71 @@ 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) + the_len = len(next(it)) + same_len_ind = all(len(l) == the_len for l in it) + count_ind = len(sweep_lists) >= 2 + if same_len_ind == True and count_ind == True: + return list(map(lambda x: list(x), list(zip(*sweep_lists)))) + elif same_len_ind == False or count_ind == False: + return sweep_lists + else: + raise ValueError('lists have different lengths!') + + +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) + for f_dict in f_lists: + if state_type_ind == 'mechs': + updates = list(f_dict.values()).pop() + functs = list(updates.values()).pop() + + mech = list(f_dict.keys()).pop() + update_type = list(updates.keys()).pop() + sk = list(functs.keys()).pop() + vf = list(functs.values()).pop() + + new_states_dict[mech][update_type][sk] = vf + elif state_type_ind == 'exo_proc': + sk = list(f_dict.keys()).pop() + vf = list(f_dict.values()).pop() + + new_states_dict[sk] = vf + else: + raise ValueError("Incorrect \'state_type_ind\'") + + configs.append(new_states_dict) + del new_states_dict + + return configs + + +def parameterize_states(exo_states): + sweep_lists = [] + for sk, vfs in exo_states.items(): + id_sweep_lists = [] + if isinstance(vfs, list): + for vf in vfs: + id_sweep_lists.append({sk: vf}) + if len(id_sweep_lists) != 0: + sweep_lists.append(id_sweep_lists) + + if len(sweep_lists) == 0: + return [exo_states] + + zipped_sweep_lists = zip_sweep_functions(sweep_lists) + states_configs = create_sweep_config_list(zipped_sweep_lists, exo_states, "exo_proc") + + return states_configs + def parameterize_mechanism(mechanisms): sweep_lists = [] - new_mechanisms = deepcopy(mechanisms) - for mech, update_types in new_mechanisms.items(): + for mech, update_types in mechanisms.items(): for update_type, fkv in update_types.items(): for sk, vfs in fkv.items(): id_sweep_lists = [] @@ -157,36 +217,11 @@ def parameterize_mechanism(mechanisms): if len(id_sweep_lists) != 0: sweep_lists.append(id_sweep_lists) - zipped_sweep_lists = [] - it = iter(sweep_lists) - the_len = len(next(it)) - if all(len(l) == the_len for l in it): - zipped_sweep_lists = list(map(lambda x: list(x), list(zip(*sweep_lists)))) - else: - raise ValueError('lists have different lengths!') - if len(sweep_lists) == 0: return [mechanisms] - mechanisms_configs = [] - for f_list in zipped_sweep_lists: - mechanisms_copy = deepcopy(mechanisms) - for f_dict in f_list: - updates = list(f_dict.values()).pop() - functs = list(updates.values()).pop() - - mech = list(f_dict.keys()).pop() - update_type = list(updates.keys()).pop() - sk = list(functs.keys()).pop() - vf = list(functs.values()).pop() - mechanisms_copy[mech][update_type][sk] = vf - mechanisms_configs.append(mechanisms_copy) - del mechanisms_copy - - # pp.pprint(sweep_lists) - # print() - # pp.pprint(zipped_sweep_lists) - # print() + zipped_sweep_lists = zip_sweep_functions(sweep_lists) + mechanisms_configs = create_sweep_config_list(zipped_sweep_lists, mechanisms, "mechs") return mechanisms_configs diff --git a/SimCAD/engine/simulation.py b/SimCAD/engine/simulation.py index 39278c6..992ac66 100644 --- a/SimCAD/engine/simulation.py +++ b/SimCAD/engine/simulation.py @@ -11,14 +11,31 @@ 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: f(step, sL, s), funcs)) + return list(map(lambda f: self.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()): @@ -28,29 +45,22 @@ 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] _input = self.state_update_exception(self.get_behavior_input(m_step, sL, last_in_obj, behavior_funcs)) + # print(_input) # ToDo: add env_proc generator to `last_in_copy` iterator as wrapper function - # last_in_copy = dict([self.behavior_update_exception(f(m_step, sL, last_in_obj, _input)) for f in state_funcs]) # 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 + ] + ) + # print(last_in_copy) - for f in state_funcs: - print(f.__name__ + " " + str(f)) - if f.__name__[0:5] == 'sweep': - self.behavior_update_exception(f(m_step)(sL)(last_in_obj)(_input)) - else: - self.behavior_update_exception(f(m_step, sL, last_in_obj, _input)) - # print(f(m_step, sL, last_in_obj, _input)) - - print(last_in_obj) - exit() - # - # for f in state_funcs: - # print(f(1,2,3,4)) - # exit() for k in last_in_obj: if k not in last_in_copy: diff --git a/simulations/validation/config1.py b/simulations/validation/config1.py index a20189c..267f2fb 100644 --- a/simulations/validation/config1.py +++ b/simulations/validation/config1.py @@ -7,7 +7,7 @@ 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, sweep #parameterize_states + ep_time_step, parameterize_mechanism, parameterize_states, sweep #parameterize_states from copy import deepcopy @@ -16,35 +16,35 @@ 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, . . . ]) - -# ------------- +# # ------------- +# 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 = { @@ -179,37 +179,7 @@ exogenous_states = exo_update_per_ts(raw_exogenous_states) # pp.pprint(raw_exogenous_states) # print() -def parameterize_states(states_dict): - sweep_lists = [] - new_states_dict = deepcopy(states_dict) - for sk, vfs in new_states_dict.items(): - print({sk: vfs}) - print() - id_sweep_lists = [] - if isinstance(vfs, list): - for vf in vfs: - id_sweep_lists.append({sk: vf}) - if len(id_sweep_lists) != 0: - sweep_lists.append(id_sweep_lists) - zipped_sweep_lists = [] - it = iter(sweep_lists) - the_len = len(next(it)) - same_len_ind = all(len(l) == the_len for l in it) - count_ind = len(sweep_lists) >= 2 - if same_len_ind == True and count_ind == True: - zipped_sweep_lists = list(map(lambda x: list(x), list(zip(*sweep_lists)))) - elif same_len_ind == False or count_ind == False: - zipped_sweep_lists = sweep_lists - else: - raise ValueError('lists have different lengths!') - - pp.pprint(sweep_lists) - print() - pp.pprint(zipped_sweep_lists) - print() - - # return zipped_sweep_lists # pp.pprint(parameterize_states(raw_exogenous_states)) # print() @@ -270,8 +240,8 @@ 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(parameterize_mechanism(mechanisms)) +# print() # pp.pprint(mechanisms) sim_config = { @@ -280,16 +250,16 @@ sim_config = { } # for mech_configs in parameterize_mechanism(mechanisms): -# configs.append( -# Configuration( -# sim_config=sim_config, -# state_dict=genesis_states, -# seed=seed, -# exogenous_states=exogenous_states, -# env_processes=env_processes, -# mechanisms=mech_configs -# ) -# ) +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] + ) +) # # print(rename('new', b2m2).__name__) #