diff --git a/README.md b/README.md index 6ea04c3..e32b654 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **Dependencies:** ```bash -pip install pathos pipenv fn tabulate +pip install -r requirements.txt ``` **Project:** diff --git a/SimCAD/__init__.py b/SimCAD/__init__.py index 1df2784..8ba50b2 100644 --- a/SimCAD/__init__.py +++ b/SimCAD/__init__.py @@ -1,7 +1,12 @@ +from fn.op import foldr +from SimCAD.utils.configuration import dict_elemwise_sum + + configs = [] -class Configuration(object): - def __init__(self, sim_config, state_dict, seed, exogenous_states, env_processes, behavior_ops, mechanisms): + +class Configuration: + def __init__(self, sim_config, state_dict, seed, exogenous_states, env_processes, mechanisms, behavior_ops=[foldr(dict_elemwise_sum())]): self.sim_config = sim_config self.state_dict = state_dict self.seed = seed diff --git a/SimCAD/engine/__init__.py b/SimCAD/engine/__init__.py index 534b67b..d534bca 100644 --- a/SimCAD/engine/__init__.py +++ b/SimCAD/engine/__init__.py @@ -6,28 +6,42 @@ from SimCAD.utils.ui import create_tensor_field from SimCAD.utils.configProcessor import generate_config from SimCAD.engine.simulation import Executor as SimExecutor +class ExecutionMode(object): -class ExecutionContext: - def parallelize_simulations(self, 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: - results = p.map(lambda t: t[0](t[1], t[2], t[3], t[4], t[5]), l) + single_proc = 'single_proc' + multi_proc = 'multi_proc' - return results +class ExecutionContext(object): + + def __init__(self, context=ExecutionMode.multi_proc): + self.name = context + self.method = None + 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: + results = p.map(lambda t: t[0](t[1], t[2], t[3], t[4], t[5]), l) + + return results + + if context == 'single_proc': + self.method = None + elif context == 'multi_proc': + self.method = parallelize_simulations class Executor: - def __init__(self, ExecutionContext, configs): + def __init__(self, exec_context, configs): self.SimExecutor = SimExecutor - self.ExecutionContext = ExecutionContext + self.exec_method = exec_context.method + self.exec_context = exec_context.name self.configs = configs self.main = self.execute + def execute(self): - ec = ExecutionContext() - print(self.configs) + print(self.exec_context+": "+str(self.configs)) states_lists, Ts, Ns, eps, configs_structs, env_processes_list, mechanisms, simulation_execs = \ [], [], [], [], [], [], [], [] config_idx = 0 @@ -45,15 +59,21 @@ class Executor: # Dimensions: N x r x mechs - if len(self.configs) > 1: - simulations = ec.parallelize_simulations(simulation_execs, states_lists, configs_structs, env_processes_list, Ts, Ns) - results = [] - for result, mechanism, ep in list(zip(simulations, mechanisms, eps)): - print(tabulate(create_tensor_field(mechanism, ep), headers='keys', tablefmt='psql')) - results.append(flatten(result)) - return results - else: + def single_proc_exec(simulation_execs, states_lists, configs_structs, env_processes_list, Ts, Ns): simulation, states_list, config = simulation_execs.pop(), states_lists.pop(), configs_structs.pop() env_processes, T, N = env_processes_list.pop(), Ts.pop(), Ns.pop() result = simulation(states_list, config, env_processes, T, N) - return flatten(result) \ No newline at end of file + 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 len(self.configs) > 1: + simulations = self.exec_method(simulation_execs, states_lists, configs_structs, env_processes_list, Ts, Ns) + results = [] + for result, mechanism, ep in list(zip(simulations, mechanisms, eps)): + 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 diff --git a/SimCAD/engine/simulation.py b/SimCAD/engine/simulation.py index f0f8fba..f798096 100644 --- a/SimCAD/engine/simulation.py +++ b/SimCAD/engine/simulation.py @@ -2,18 +2,15 @@ from copy import deepcopy from fn import _ from fn.op import foldr, call -class Executor(object): + +class Executor: def __init__(self, behavior_ops): self.behavior_ops = behavior_ops # Data Type reduction def getBehaviorInput(self, step, sL, s, funcs): - if len(self.behavior_ops) == 0: - ops = [foldr(_ + _)] - else: - ops = self.behavior_ops[::-1] - + ops = self.behavior_ops[::-1] def getColResults(step, sL, s, funcs): return list(map(lambda f: f(step, sL, s), funcs)) diff --git a/SimCAD/utils/configProcessor.py b/SimCAD/utils/configProcessor.py index fdbb4e4..d32a43a 100644 --- a/SimCAD/utils/configProcessor.py +++ b/SimCAD/utils/configProcessor.py @@ -69,7 +69,7 @@ def generate_config(state_dict, mechanisms, exo_proc): bdf_values = [[b_identity] * len(sdf_values)] return sdf_values, bdf_values - zipped_list = [] + # zipped_list = [] if len(mechanisms) != 0: bdf = create_matrix_field(mechanisms, 'behaviors') sdf = create_matrix_field(mechanisms, 'states') diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..a74daac --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +pathos +pipenv +fn +tabulate \ No newline at end of file diff --git a/sandboxUX/config1.py b/sandboxUX/config1.py index 364f540..c3a8e8b 100644 --- a/sandboxUX/config1.py +++ b/sandboxUX/config1.py @@ -161,4 +161,4 @@ sim_config = { "T": range(5) } -configs.append(Configuration(sim_config, state_dict, seed, exogenous_states, env_processes, behavior_ops, mechanisms)) +configs.append(Configuration(sim_config, state_dict, seed, exogenous_states, env_processes, mechanisms, behavior_ops)) \ No newline at end of file diff --git a/sandboxUX/config2.py b/sandboxUX/config2.py index 5aab54f..06c66b8 100644 --- a/sandboxUX/config2.py +++ b/sandboxUX/config2.py @@ -1,9 +1,8 @@ from decimal import Decimal import numpy as np -from fn.op import foldr from SimCAD import Configuration, configs -from SimCAD.utils.configuration import exo_update_per_ts, proc_trigger, dict_elemwise_sum, bound_norm_random, \ +from SimCAD.utils.configuration import exo_update_per_ts, proc_trigger, bound_norm_random, \ ep_time_step @@ -26,6 +25,7 @@ def b1m2(step, sL, s): def b2m2(step, sL, s): return {'param1': 'b', 'param2': 4} + def b1m3(step, sL, s): return {'param1': ['c'], 'param2': np.array([10, 100])} def b2m3(step, sL, s): @@ -120,7 +120,7 @@ env_processes = { # [1, 2] = {'b1': ['a'], 'b2', [1]} = # behavior_ops = [behavior_to_dict, print_fwd, sum_dict_values] -behavior_ops = [foldr(dict_elemwise_sum())] +# behavior_ops = [foldr(dict_elemwise_sum())] # behavior_ops = [] # need at least 1 behaviour and 1 state function for the 1st mech with behaviors @@ -163,4 +163,4 @@ sim_config = { "T": range(5) } -configs.append(Configuration(sim_config, state_dict, seed, exogenous_states, env_processes, behavior_ops, mechanisms)) \ No newline at end of file +configs.append(Configuration(sim_config, state_dict, seed, exogenous_states, env_processes, mechanisms)) \ No newline at end of file diff --git a/sandboxUX/sim_test.py b/sandboxUX/sim_test.py index 7f601fe..714a308 100644 --- a/sandboxUX/sim_test.py +++ b/sandboxUX/sim_test.py @@ -1,15 +1,19 @@ import pandas as pd from tabulate import tabulate -from SimCAD.engine import ExecutionContext, Executor +from SimCAD.engine import ExecutionMode, ExecutionContext, Executor from sandboxUX import config1, config2 +from SimCAD import configs # ToDo: pass ExecutionContext with execution method as ExecutionContext input +exec_mode = ExecutionMode() + print("Simulation Run 1") print() -single_config = [config1] -run1 = Executor(ExecutionContext, single_config) +single_config = [configs[0]] +single_proc_ctx = ExecutionContext(exec_mode.single_proc) +run1 = Executor(single_proc_ctx, single_config) run1_raw_result = run1.main() result = pd.DataFrame(run1_raw_result) print(tabulate(result, headers='keys', tablefmt='psql')) @@ -17,8 +21,8 @@ print() print("Simulation Run 2: Pairwise Execution") print() -configs = [config1, config2] -run2 = Executor(ExecutionContext, configs) +multi_proc_ctx = ExecutionContext(exec_mode.multi_proc) +run2 = Executor(multi_proc_ctx, configs) run2_raw_results = run2.main() for raw_result in run2_raw_results: result = pd.DataFrame(raw_result)