diff --git a/README.md b/README.md index 80d7c7d..fcb6392 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ import pandas as pd from tabulate import tabulate from SimCAD.engine import ExecutionMode, ExecutionContext, Executor -# from sandboxUX import config1, config2 +sandbox from SimCAD import configs # ToDo: pass ExecutionContext with execution method as ExecutionContext input diff --git a/SimCAD/engine/__init__.py b/SimCAD/engine/__init__.py index c0c5aa2..78dc6f1 100644 --- a/SimCAD/engine/__init__.py +++ b/SimCAD/engine/__init__.py @@ -19,6 +19,12 @@ class ExecutionContext: self.name = context self.method = None + def single_proc_exec(simulation_execs, states_lists, configs_structs, env_processes_list, Ts, Ns): + l = [simulation_execs, states_lists, configs_structs, env_processes_list, Ts, Ns] + simulation, states_list, config, env_processes, T, N = list(map(lambda x: x.pop(), l)) + result = simulation(states_list, config, env_processes, T, N) + return flatten(result) + def parallelize_simulations(fs, states_list, configs, env_processes, Ts, Ns): l = list(zip(fs, states_list, configs, env_processes, Ts, Ns)) with Pool(len(configs)) as p: @@ -27,7 +33,7 @@ class ExecutionContext: return results if context == 'single_proc': - self.method = None + self.method = single_proc_exec elif context == 'multi_proc': self.method = parallelize_simulations @@ -62,16 +68,7 @@ class Executor: # Dimensions: N x r x mechs - def single_proc_exec(simulation_execs, states_lists, configs_structs, env_processes_list, Ts, Ns): - l = [simulation_execs, states_lists, configs_structs, env_processes_list, Ts, Ns] - simulation, states_list, config, env_processes, T, N = list(map(lambda x: x.pop(), l)) - # print(states_list) - result = simulation(states_list, config, env_processes, T, N) - return flatten(result) - - if self.exec_context == ExecutionMode.single_proc: - return single_proc_exec(simulation_execs, states_lists, configs_structs, env_processes_list, Ts, Ns) - elif self.exec_context == ExecutionMode.multi_proc: + if self.exec_context == ExecutionMode.multi_proc: if len(self.configs) > 1: simulations = self.exec_method(simulation_execs, states_lists, configs_structs, env_processes_list, Ts, Ns) results = [] @@ -79,5 +76,5 @@ class Executor: print(tabulate(create_tensor_field(mechanism, ep), headers='keys', tablefmt='psql')) results.append(flatten(result)) return results - else: - return single_proc_exec(simulation_execs, states_lists, configs_structs, env_processes_list, Ts, Ns) \ No newline at end of file + else: + return self.exec_method(simulation_execs, states_lists, configs_structs, env_processes_list, Ts, Ns) \ No newline at end of file diff --git a/SimCAD/engine/simulation.py b/SimCAD/engine/simulation.py index ebb22c6..0249dc9 100644 --- a/SimCAD/engine/simulation.py +++ b/SimCAD/engine/simulation.py @@ -59,7 +59,7 @@ class Executor: return sL - def block_gen(self, states_list, configs, env_processes, t_step, run): + def mech_pipeline(self, states_list, configs, env_processes, t_step, run): m_step = 0 states_list_copy = deepcopy(states_list) # print(states_list_copy) @@ -80,12 +80,14 @@ class Executor: # rename pipe - def pipe(self, states_list, configs, env_processes, time_seq, run): + 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] for time_step in time_seq: # print(run) - pipe_run = self.block_gen(simulation_list[-1], configs, env_processes, time_step, run) + pipe_run = self.mech_pipeline(simulation_list[-1], configs, env_processes, time_step, run) + # pp.pprint(pipe_run) + # exit() _, *pipe_run = pipe_run simulation_list.append(pipe_run) @@ -99,11 +101,11 @@ class Executor: run += 1 # print("Run: "+str(run)) states_list_copy = deepcopy(states_list) # WHY ??? - head, *tail = self.pipe(states_list_copy, configs, env_processes, time_seq, run) + head, *tail = self.block_pipeline(states_list_copy, configs, env_processes, time_seq, run) genesis = head.pop() genesis['mech_step'], genesis['time_step'], genesis['run'] = 0, 0, run - first_timestep = [genesis] + tail.pop(0) - pipe_run += [first_timestep] + tail + first_timestep_per_run = [genesis] + tail.pop(0) + pipe_run += [first_timestep_per_run] + tail del states_list_copy return pipe_run \ No newline at end of file diff --git a/SimCAD/utils/configProcessor.py b/SimCAD/utils/configProcessor.py index c482e5b..c2d0bbe 100644 --- a/SimCAD/utils/configProcessor.py +++ b/SimCAD/utils/configProcessor.py @@ -10,7 +10,7 @@ def state_identity(k): return lambda step, sL, s, _input: (k, s[k]) -# fix +# Make returntype chosen by user. Must Classify Configs def b_identity(step, sL, s): return {'indentity': 0} diff --git a/SimCAD/utils/configuration.py b/SimCAD/utils/configuration.py index 76ba422..1b657a6 100644 --- a/SimCAD/utils/configuration.py +++ b/SimCAD/utils/configuration.py @@ -21,16 +21,18 @@ def proc_trigger(trigger_step, update_f, step): # accept timedelta instead of timedelta params -def time_step(dt_str, dt_format='%Y-%m-%d %H:%M:%S', days=0, minutes=0, seconds=30): +t_delta = timedelta(days=0, minutes=0, seconds=30) +def time_step(dt_str, dt_format='%Y-%m-%d %H:%M:%S', _timedelta = t_delta): dt = datetime.strptime(dt_str, dt_format) - t = dt + timedelta(days=days, minutes=minutes, seconds=seconds) + t = dt + _timedelta return t.strftime(dt_format) # accept timedelta instead of timedelta params -def ep_time_step(s, dt_str, fromat_str='%Y-%m-%d %H:%M:%S', days=0, minutes=0, seconds=1): +t_delta = timedelta(days=0, minutes=0, seconds=1) +def ep_time_step(s, dt_str, fromat_str='%Y-%m-%d %H:%M:%S', _timedelta = t_delta): if s['mech_step'] == 0: - return time_step(dt_str, fromat_str, days, minutes, seconds) + return time_step(dt_str, fromat_str, _timedelta) else: return dt_str diff --git a/sandboxUX/config3.py b/sandbox/barlin/config3.py similarity index 100% rename from sandboxUX/config3.py rename to sandbox/barlin/config3.py diff --git a/sandboxUX/config4.py b/sandbox/barlin/config4.py similarity index 100% rename from sandboxUX/config4.py rename to sandbox/barlin/config4.py diff --git a/sandboxUX/sim_test.py b/sandbox/sim_test.py similarity index 86% rename from sandboxUX/sim_test.py rename to sandbox/sim_test.py index 5a2dd42..93f5ed3 100644 --- a/sandboxUX/sim_test.py +++ b/sandbox/sim_test.py @@ -2,8 +2,9 @@ import pandas as pd from tabulate import tabulate from SimCAD.engine import ExecutionMode, ExecutionContext, Executor -from sandboxUX import config1, config2 -# from sandboxUX import config4 +from sandbox.validation import config1, config2 +# from sandbox import config4 +# from sandbox import config_zx from SimCAD import configs # ToDo: pass ExecutionContext with execution method as ExecutionContext input @@ -25,6 +26,7 @@ print() print("Simulation Run 2: Pairwise Execution") print() multi_proc_ctx = ExecutionContext(exec_mode.multi_proc) +# configs = [config1, config1] run2 = Executor(multi_proc_ctx, configs) run2_raw_results = run2.main() for raw_result in run2_raw_results: diff --git a/sandboxUX/config1.py b/sandbox/validation/config1.py similarity index 92% rename from sandboxUX/config1.py rename to sandbox/validation/config1.py index 1f2af9e..2e464cf 100644 --- a/sandboxUX/config1.py +++ b/sandbox/validation/config1.py @@ -1,5 +1,6 @@ from decimal import Decimal import numpy as np +from datetime import timedelta from SimCAD import Configuration, configs from SimCAD.utils.configuration import exo_update_per_ts, proc_trigger, bound_norm_random, \ @@ -72,9 +73,11 @@ def es4p2(step, sL, s, _input): x = s['s4'] * bound_norm_random(seed['b'], proc_one_coef_A, proc_one_coef_B) return (y, x) -def es5p2(step, sL, s, _input): # accept timedelta instead of timedelta params +ts_format = '%Y-%m-%d %H:%M:%S' +t_delta = timedelta(days=0, minutes=0, seconds=1) +def es5p2(step, sL, s, _input): y = 'timestamp' - x = ep_time_step(s, s['timestamp'], seconds=1) + x = ep_time_step(s, dt_str=s['timestamp'], fromat_str=ts_format, _timedelta=t_delta) return (y, x) diff --git a/sandboxUX/config2.py b/sandbox/validation/config2.py similarity index 92% rename from sandboxUX/config2.py rename to sandbox/validation/config2.py index 5f41574..c762eba 100644 --- a/sandboxUX/config2.py +++ b/sandbox/validation/config2.py @@ -1,5 +1,6 @@ from decimal import Decimal import numpy as np +from datetime import timedelta from SimCAD import Configuration, configs from SimCAD.utils.configuration import exo_update_per_ts, proc_trigger, bound_norm_random, \ @@ -74,9 +75,11 @@ def es4p2(step, sL, s, _input): x = s['s4'] * bound_norm_random(seed['b'], proc_one_coef_A, proc_one_coef_B) return (y, x) -def es5p2(step, sL, s, _input): # accept timedelta instead of timedelta params +ts_format = '%Y-%m-%d %H:%M:%S' +t_delta = timedelta(days=0, minutes=0, seconds=1) +def es5p2(step, sL, s, _input): y = 'timestamp' - x = ep_time_step(s, s['timestamp'], seconds=1) + x = ep_time_step(s, dt_str=s['timestamp'], fromat_str=ts_format, _timedelta=t_delta) return (y, x) diff --git a/sandbox/zx/config_zx.py b/sandbox/zx/config_zx.py new file mode 100644 index 0000000..cd91f75 --- /dev/null +++ b/sandbox/zx/config_zx.py @@ -0,0 +1,157 @@ +from fn.op import foldr +from fn import _ + +from decimal import Decimal +import numpy as np + +from SimCAD import Configuration, configs +from SimCAD.utils.configuration import exo_update_per_ts, proc_trigger, bound_norm_random, \ + ep_time_step + +seed = { + 'z': np.random.RandomState(1), + 'a': np.random.RandomState(2), + 'b': np.random.RandomState(3), + 'c': np.random.RandomState(3) +} + +# Behaviors per Mechanism +def b1m1(step, sL, s): + return s['s1'] + 1 +def b2m1(step, sL, s): + return s['s1'] + 1 + +def b1m2(step, sL, s): + return s['s1'] + 1 +def b2m2(step, sL, s): + return s['s1'] + 1 + +def b1m3(step, sL, s): + return s['s1'] + 1 +def b2m3(step, sL, s): + return s['s2'] + 1 + + +# Internal States per Mechanism +def s1m1(step, sL, s, _input): + y = 's1' + x = s['s1'] + _input + return (y, x) +def s2m1(step, sL, s, _input): + y = 's2' + x = s['s2'] + _input + return (y, x) + +def s1m2(step, sL, s, _input): + y = 's1' + x = s['s1'] + _input + return (y, x) +def s2m2(step, sL, s, _input): + y = 's2' + x = s['s2'] + _input + return (y, x) + +def s1m3(step, sL, s, _input): + y = 's1' + x = s['s1'] + _input + return (y, x) +def s2m3(step, sL, s, _input): + y = 's2' + x = s['s2'] + s['s3'] + _input + 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) + +def es4p2(step, sL, s, _input): + y = 's4' + x = s['s4'] * bound_norm_random(seed['b'], proc_one_coef_A, proc_one_coef_B) + return (y, x) + +def es5p2(step, sL, s, _input): # accept timedelta instead of timedelta params + y = 'timestamp' + x = ep_time_step(s, s['timestamp'], seconds=1) + return (y, x) + + +# Environment States +def env_a(x): + return 10 +def env_b(x): + return 10 +# def what_ever(x): +# return x + 1 + +# Genesis States +state_dict = { + 's1': Decimal(0.0), + 's2': Decimal(0.0), + 's3': Decimal(1.0), + 's4': Decimal(1.0), + 'timestamp': '2018-10-01 15:16:24' +} + +exogenous_states = exo_update_per_ts( + { + "s3": es3p1, + "s4": es4p2, + "timestamp": es5p2 + } +) + +env_processes = { + "s3": proc_trigger('2018-10-01 15:16:25', env_a), + "s4": proc_trigger('2018-10-01 15:16:25', env_b) +} + +# lambdas +# genesis Sites should always be there +# [1, 2] +# User Defined Aggregate Function +behavior_udaf = [ foldr(_ + _), lambda x: x + 0 ] +# need at least 1 behaviour and 1 state function for the 1st mech with behaviors +mechanisms = { + "m1": { + "behaviors": { + "b1": b1m1, # lambda step, sL, s: s['s1'] + 1, + "b2": b2m1 + }, + "states": { # exclude only. TypeError: reduce() of empty sequence with no initial value + "s1": s1m1, + "s2": s2m1 + } + }, + "m2": { + "behaviors": { + "b1": b1m2, + "b2": b2m2 + }, + "states": { + "s1": s1m2, + "s2": s2m2 + } + }, + "m3": { + "behaviors": { + "b1": b1m3, + "b2": b2m3 + }, + "states": { + "s1": s1m3, + "s2": s2m3 + } + } +} + +sim_config = { + "N": 2, + "T": range(5) +} + +configs.append(Configuration(sim_config, state_dict, seed, exogenous_states, env_processes, mechanisms, behavior_udaf)) \ No newline at end of file