From 4870f2db927fd3a70cda08e404c2205205d1949c Mon Sep 17 00:00:00 2001 From: "Joshua E. Jodesty" Date: Fri, 31 May 2019 16:26:58 -0400 Subject: [PATCH] pre push mad stuff --- cadCAD/configuration/__init__.py | 20 +- .../config1.py | 7 - .../config2.py | 1 - simulations/regression_tests/sweep_config.py | 1 - .../config1_test.py} | 3 +- .../config2_test.py} | 3 +- .../external_ds_test.py} | 4 +- .../historical_state_access_test.py} | 1 + .../multi_config_test.py} | 5 +- .../{ => test_executions}/param_sweep_test.py | 1 - .../policy_agg_test.py} | 0 simulations/{ => test_executions}/udo_test.py | 0 .../udo_update_test.py} | 0 .../validation/conviction_system_logic_sim.py | 555 ++++++++++++++++++ 14 files changed, 567 insertions(+), 34 deletions(-) rename simulations/{validation => regression_tests}/config1.py (93%) rename simulations/{validation => regression_tests}/config2.py (99%) rename simulations/{config1_run.py => test_executions/config1_test.py} (93%) rename simulations/{config2_run.py => test_executions/config2_test.py} (93%) rename simulations/{external_ds_run.py => test_executions/external_ds_test.py} (86%) rename simulations/{validation/historical_state_access_run.py => test_executions/historical_state_access_test.py} (93%) rename simulations/{multi_config_run.py => test_executions/multi_config_test.py} (85%) rename simulations/{ => test_executions}/param_sweep_test.py (94%) rename simulations/{policy_agg_run.py => test_executions/policy_agg_test.py} (100%) rename simulations/{ => test_executions}/udo_test.py (100%) rename simulations/{udo_run.py => test_executions/udo_update_test.py} (100%) create mode 100644 simulations/validation/conviction_system_logic_sim.py diff --git a/cadCAD/configuration/__init__.py b/cadCAD/configuration/__init__.py index 120b9ad..56aae05 100644 --- a/cadCAD/configuration/__init__.py +++ b/cadCAD/configuration/__init__.py @@ -12,7 +12,6 @@ from cadCAD.configuration.utils.depreciationHandler import sanitize_partial_stat # policy_ops=[foldr(dict_elemwise_sum())] # policy_ops=[reduce, lambda a, b: {**a, **b}] - class Configuration(object): def __init__(self, sim_config={}, initial_state={}, seeds={}, env_processes={}, exogenous_states={}, partial_state_update_blocks={}, policy_ops=[lambda a, b: a + b], @@ -37,21 +36,12 @@ def append_configs(sim_configs={}, initial_state={}, seeds={}, raw_exogenous_sta else: exogenous_states = raw_exogenous_states - if isinstance(sim_configs, list): - for sim_config in sim_configs: - config = Configuration( - sim_config=sim_config, - initial_state=initial_state, - seeds=seeds, - exogenous_states=exogenous_states, - env_processes=env_processes, - partial_state_update_blocks=partial_state_update_blocks, - policy_ops=policy_ops - ) - configs.append(config) - elif isinstance(sim_configs, dict): + if isinstance(sim_configs, dict): + sim_configs = [sim_configs] + + for sim_config in sim_configs: config = Configuration( - sim_config=sim_configs, + sim_config=sim_config, initial_state=initial_state, seeds=seeds, exogenous_states=exogenous_states, diff --git a/simulations/validation/config1.py b/simulations/regression_tests/config1.py similarity index 93% rename from simulations/validation/config1.py rename to simulations/regression_tests/config1.py index 14ec2e1..33faabf 100644 --- a/simulations/validation/config1.py +++ b/simulations/regression_tests/config1.py @@ -1,18 +1,11 @@ -from decimal import Decimal -from functools import reduce - import numpy as np from datetime import timedelta -from cadCAD.configuration.utils.policyAggregation import get_base_value from cadCAD.configuration import append_configs from cadCAD.configuration.utils import env_proc_trigger, bound_norm_random, ep_time_step, config_sim, time_step, \ env_trigger -# from cadCAD.configuration.utils import timestep_trigger -from simulations.regression_tests.sweep_config import var_timestep_trigger - seeds = { 'z': np.random.RandomState(1), diff --git a/simulations/validation/config2.py b/simulations/regression_tests/config2.py similarity index 99% rename from simulations/validation/config2.py rename to simulations/regression_tests/config2.py index 5c36b46..3962f76 100644 --- a/simulations/validation/config2.py +++ b/simulations/regression_tests/config2.py @@ -139,7 +139,6 @@ sim_config = config_sim( } ) - append_configs( sim_configs=sim_config, initial_state=genesis_states, diff --git a/simulations/regression_tests/sweep_config.py b/simulations/regression_tests/sweep_config.py index c72e489..ef7885c 100644 --- a/simulations/regression_tests/sweep_config.py +++ b/simulations/regression_tests/sweep_config.py @@ -68,7 +68,6 @@ def s1m1(_g, step, sL, s, _input): psu_block['m1']["variables"]['s1'] = s1m1 def s2m1(_g, step, sL, s, _input): - print(_g) return 's2', _g['beta'] psu_block['m1']["variables"]['s2'] = s2m1 diff --git a/simulations/config1_run.py b/simulations/test_executions/config1_test.py similarity index 93% rename from simulations/config1_run.py rename to simulations/test_executions/config1_test.py index 6e6e9c4..052c602 100644 --- a/simulations/config1_run.py +++ b/simulations/test_executions/config1_test.py @@ -2,8 +2,7 @@ import pandas as pd from tabulate import tabulate # The following imports NEED to be in the exact order from cadCAD.engine import ExecutionMode, ExecutionContext, Executor -from simulations.validation import config1 - +from simulations.regression_tests import config1 from cadCAD import configs exec_mode = ExecutionMode() diff --git a/simulations/config2_run.py b/simulations/test_executions/config2_test.py similarity index 93% rename from simulations/config2_run.py rename to simulations/test_executions/config2_test.py index 890f356..e6c349e 100644 --- a/simulations/config2_run.py +++ b/simulations/test_executions/config2_test.py @@ -2,8 +2,7 @@ import pandas as pd from tabulate import tabulate # The following imports NEED to be in the exact order from cadCAD.engine import ExecutionMode, ExecutionContext, Executor -from simulations.validation import config2 - +from simulations.regression_tests import config2 from cadCAD import configs exec_mode = ExecutionMode() diff --git a/simulations/external_ds_run.py b/simulations/test_executions/external_ds_test.py similarity index 86% rename from simulations/external_ds_run.py rename to simulations/test_executions/external_ds_test.py index 7c4eec4..f5470f1 100644 --- a/simulations/external_ds_run.py +++ b/simulations/test_executions/external_ds_test.py @@ -2,9 +2,7 @@ import pandas as pd from tabulate import tabulate # The following imports NEED to be in the exact order from cadCAD.engine import ExecutionMode, ExecutionContext, Executor -# from simulations.validation import config1_test_pipe -# from simulations.validation import config1 -# from simulations.validation import externalds +from simulations.regression_tests import external_dataset from cadCAD import configs exec_mode = ExecutionMode() diff --git a/simulations/validation/historical_state_access_run.py b/simulations/test_executions/historical_state_access_test.py similarity index 93% rename from simulations/validation/historical_state_access_run.py rename to simulations/test_executions/historical_state_access_test.py index 23225e5..2b3b477 100644 --- a/simulations/validation/historical_state_access_run.py +++ b/simulations/test_executions/historical_state_access_test.py @@ -2,6 +2,7 @@ import pandas as pd from tabulate import tabulate # The following imports NEED to be in the exact order from cadCAD.engine import ExecutionMode, ExecutionContext, Executor +from simulations.regression_tests import historical_state_access from cadCAD import configs exec_mode = ExecutionMode() diff --git a/simulations/multi_config_run.py b/simulations/test_executions/multi_config_test.py similarity index 85% rename from simulations/multi_config_run.py rename to simulations/test_executions/multi_config_test.py index 045ef84..f044a50 100644 --- a/simulations/multi_config_run.py +++ b/simulations/test_executions/multi_config_test.py @@ -2,7 +2,7 @@ import pandas as pd from tabulate import tabulate # The following imports NEED to be in the exact order from cadCAD.engine import ExecutionMode, ExecutionContext, Executor -from simulations.validation import config1, config2 +from simulations.regression_tests import config1, config2 from cadCAD import configs exec_mode = ExecutionMode() @@ -11,12 +11,13 @@ print("Simulation Execution: Concurrent Execution") multi_proc_ctx = ExecutionContext(context=exec_mode.multi_proc) run = Executor(exec_context=multi_proc_ctx, configs=configs) +# print(configs) i = 0 config_names = ['config1', 'config2'] for raw_result, tensor_field in run.execute(): result = pd.DataFrame(raw_result) print() - print("Tensor Field: " + config_names[i]) + print(f"Tensor Field: {config_names[i]}") print(tabulate(tensor_field, headers='keys', tablefmt='psql')) print("Output:") print(tabulate(result, headers='keys', tablefmt='psql')) diff --git a/simulations/param_sweep_test.py b/simulations/test_executions/param_sweep_test.py similarity index 94% rename from simulations/param_sweep_test.py rename to simulations/test_executions/param_sweep_test.py index d114536..a7e736c 100644 --- a/simulations/param_sweep_test.py +++ b/simulations/test_executions/param_sweep_test.py @@ -4,7 +4,6 @@ import pandas as pd from tabulate import tabulate # The following imports NEED to be in the exact order from cadCAD.engine import ExecutionMode, ExecutionContext, Executor -# from simulations.validation import new_sweep_config from simulations.regression_tests import sweep_config from cadCAD import configs diff --git a/simulations/policy_agg_run.py b/simulations/test_executions/policy_agg_test.py similarity index 100% rename from simulations/policy_agg_run.py rename to simulations/test_executions/policy_agg_test.py diff --git a/simulations/udo_test.py b/simulations/test_executions/udo_test.py similarity index 100% rename from simulations/udo_test.py rename to simulations/test_executions/udo_test.py diff --git a/simulations/udo_run.py b/simulations/test_executions/udo_update_test.py similarity index 100% rename from simulations/udo_run.py rename to simulations/test_executions/udo_update_test.py diff --git a/simulations/validation/conviction_system_logic_sim.py b/simulations/validation/conviction_system_logic_sim.py new file mode 100644 index 0000000..85b62a0 --- /dev/null +++ b/simulations/validation/conviction_system_logic_sim.py @@ -0,0 +1,555 @@ +from pprint import pprint + +import numpy as np +from tabulate import tabulate + +from cadCAD.configuration.utils import config_sim +from simulations.validation.conviction_helpers import * +#import networkx as nx +from scipy.stats import expon, gamma + + +#functions for partial state update block 1 + +#Driving processes: arrival of participants, proposals and funds +##----------------------------------------- + + +def gen_new_participant(network, new_participant_holdings): + + i = len([node for node in network.nodes]) + + network.add_node(i) + network.nodes[i]['type']="participant" + + s_rv = np.random.rand() + network.nodes[i]['sentiment'] = s_rv + network.nodes[i]['holdings']=new_participant_holdings + + for j in get_nodes_by_type(network, 'proposal'): + network.add_edge(i, j) + + rv = np.random.rand() + a_rv = 1-4*(1-rv)*rv #polarized distribution + network.edges[(i, j)]['affinity'] = a_rv + network.edges[(i,j)]['tokens'] = a_rv*network.nodes[i]['holdings'] + network.edges[(i, j)]['conviction'] = 0 + + return network + + +scale_factor = 1000 + +def gen_new_proposal(network, funds, supply, trigger_func): + j = len([node for node in network.nodes]) + network.add_node(j) + network.nodes[j]['type']="proposal" + + network.nodes[j]['conviction']=0 + network.nodes[j]['status']='candidate' + network.nodes[j]['age']=0 + + rescale = scale_factor*funds + r_rv = gamma.rvs(3,loc=0.001, scale=rescale) + network.node[j]['funds_requested'] = r_rv + + network.nodes[j]['trigger']= trigger_func(r_rv, funds, supply) + + participants = get_nodes_by_type(network, 'participant') + proposing_participant = np.random.choice(participants) + + for i in participants: + network.add_edge(i, j) + if i==proposing_participant: + network.edges[(i, j)]['affinity']=1 + else: + rv = np.random.rand() + a_rv = 1-4*(1-rv)*rv #polarized distribution + network.edges[(i, j)]['affinity'] = a_rv + + network.edges[(i, j)]['conviction'] = 0 + network.edges[(i,j)]['tokens'] = 0 + return network + + + +def driving_process(params, step, sL, s): + + #placeholder plumbing for random processes + arrival_rate = 10/s['sentiment'] + rv1 = np.random.rand() + new_participant = bool(rv1<1/arrival_rate) + if new_participant: + h_rv = expon.rvs(loc=0.0, scale=1000) + new_participant_holdings = h_rv + else: + new_participant_holdings = 0 + + network = s['network'] + affinities = [network.edges[e]['affinity'] for e in network.edges ] + median_affinity = np.median(affinities) + + proposals = get_nodes_by_type(network, 'proposal') + fund_requests = [network.nodes[j]['funds_requested'] for j in proposals if network.nodes[j]['status']=='candidate' ] + + funds = s['funds'] + total_funds_requested = np.sum(fund_requests) + + proposal_rate = 10/median_affinity * total_funds_requested/funds + rv2 = np.random.rand() + new_proposal = bool(rv2<1/proposal_rate) + + sentiment = s['sentiment'] + funds = s['funds'] + scale_factor = 1+4000*sentiment**2 + + #this shouldn't happen but expon is throwing domain errors + if scale_factor > 1: + funds_arrival = expon.rvs(loc = 0, scale = scale_factor ) + else: + funds_arrival = 0 + + return({'new_participant':new_participant, + 'new_participant_holdings':new_participant_holdings, + 'new_proposal':new_proposal, + 'funds_arrival':funds_arrival}) + + +#Mechanisms for updating the state based on driving processes +##--- +def update_network(params, step, sL, s, _input): + + network = s['network'] + funds = s['funds'] + supply = s['supply'] + trigger_func = params['trigger_func'] + + new_participant = _input['new_participant'] #T/F + new_proposal = _input['new_proposal'] #T/F + + if new_participant: + new_participant_holdings = _input['new_participant_holdings'] + network = gen_new_participant(network, new_participant_holdings) + + if new_proposal: + network= gen_new_proposal(network,funds,supply,trigger_func ) + + #update age of the existing proposals + proposals = get_nodes_by_type(network, 'proposal') + + for j in proposals: + network.nodes[j]['age'] = network.nodes[j]['age']+1 + if network.nodes[j]['status'] == 'candidate': + requested = network.nodes[j]['funds_requested'] + network.nodes[j]['trigger'] = trigger_func(requested, funds, supply) + else: + network.nodes[j]['trigger'] = np.nan + + key = 'network' + value = network + + return (key, value) + +def increment_funds(params, step, sL, s, _input): + + funds = s['funds'] + funds_arrival = _input['funds_arrival'] + + #increment funds + funds = funds + funds_arrival + + key = 'funds' + value = funds + + return (key, value) + +def increment_supply(params, step, sL, s, _input): + + supply = s['supply'] + supply_arrival = _input['new_participant_holdings'] + + #increment funds + supply = supply + supply_arrival + + key = 'supply' + value = supply + + return (key, value) + +#functions for partial state update block 2 + +#Driving processes: completion of previously funded proposals +##----------------------------------------- + +def check_progress(params, step, sL, s): + + network = s['network'] + proposals = get_nodes_by_type(network, 'proposal') + + completed = [] + for j in proposals: + if network.nodes[j]['status'] == 'active': + grant_size = network.nodes[j]['funds_requested'] + base_completion_rate=params['base_completion_rate'] + likelihood = 1.0/(base_completion_rate+np.log(grant_size)) + if np.random.rand() < likelihood: + completed.append(j) + + return({'completed':completed}) + + +#Mechanisms for updating the state based on check progress +##--- +def complete_proposal(params, step, sL, s, _input): + + network = s['network'] + participants = get_nodes_by_type(network, 'participant') + + completed = _input['completed'] + for j in completed: + network.nodes[j]['status']='completed' + for i in participants: + force = network.edges[(i,j)]['affinity'] + sentiment = network.node[i]['sentiment'] + network.node[i]['sentiment'] = get_sentimental(sentiment, force, decay=0) + + key = 'network' + value = network + + return (key, value) + +def update_sentiment_on_completion(params, step, sL, s, _input): + + network = s['network'] + proposals = get_nodes_by_type(network, 'proposal') + completed = _input['completed'] + + grants_outstanding = np.sum([network.nodes[j]['funds_requested'] for j in proposals if network.nodes[j]['status']=='active']) + + grants_completed = np.sum([network.nodes[j]['funds_requested'] for j in completed]) + + sentiment = s['sentiment'] + + force = grants_completed/grants_outstanding + mu = params['sentiment_decay'] + if (force >=0) and (force <=1): + sentiment = get_sentimental(sentiment, force, mu) + else: + sentiment = get_sentimental(sentiment, 0, mu) + + + key = 'sentiment' + value = sentiment + + return (key, value) + +def get_sentimental(sentiment, force, decay=0): + mu = decay + sentiment = sentiment*(1-mu) + force + + if sentiment > 1: + sentiment = 1 + + return sentiment + +#functions for partial state update block 3 + +#Decision processes: trigger function policy +##----------------------------------------- + +def trigger_function(params, step, sL, s): + + network = s['network'] + funds = s['funds'] + supply = s['supply'] + proposals = get_nodes_by_type(network, 'proposal') + tmin = params['tmin'] + + accepted = [] + triggers = {} + for j in proposals: + if network.nodes[j]['status'] == 'candidate': + requested = network.nodes[j]['funds_requested'] + age = network.nodes[j]['age'] + threshold = trigger_threshold(requested, funds, supply) + if age > tmin: + conviction = network.nodes[j]['conviction'] + if conviction >threshold: + accepted.append(j) + else: + threshold = np.nan + + triggers[j] = threshold + + + + return({'accepted':accepted, 'triggers':triggers}) + +def decrement_funds(params, step, sL, s, _input): + + funds = s['funds'] + network = s['network'] + accepted = _input['accepted'] + + #decrement funds + for j in accepted: + funds = funds - network.nodes[j]['funds_requested'] + + key = 'funds' + value = funds + + return (key, value) + +def update_proposals(params, step, sL, s, _input): + + network = s['network'] + accepted = _input['accepted'] + triggers = _input['triggers'] + participants = get_nodes_by_type(network, 'participant') + proposals = get_nodes_by_type(network, 'proposals') + sensitivity = params['sensitivity'] + + for j in proposals: + network.nodes[j]['trigger'] = triggers[j] + + #bookkeeping conviction and participant sentiment + for j in accepted: + network.nodes[j]['status']='active' + network.nodes[j]['conviction']=np.nan + #change status to active + for i in participants: + + #operating on edge = (i,j) + #reset tokens assigned to other candidates + network.edges[(i,j)]['tokens']=0 + network.edges[(i,j)]['conviction'] = np.nan + + #update participants sentiments (positive or negative) + affinities = [network.edges[(i,p)]['affinity'] for p in proposals if not(p in accepted)] + if len(affinities)>1: + max_affinity = np.max(affinities) + force = network.edges[(i,j)]['affinity']-sensitivity*max_affinity + else: + force = 0 + + #based on what their affinities to the accepted proposals + network.nodes[i]['sentiment'] = get_sentimental(network.nodes[i]['sentiment'], force, False) + + + key = 'network' + value = network + + return (key, value) + +def update_sentiment_on_release(params, step, sL, s, _input): + + network = s['network'] + proposals = get_nodes_by_type(network, 'proposal') + accepted = _input['accepted'] + + proposals_outstanding = np.sum([network.nodes[j]['funds_requested'] for j in proposals if network.nodes[j]['status']=='candidate']) + + proposals_accepted = np.sum([network.nodes[j]['funds_requested'] for j in accepted]) + + sentiment = s['sentiment'] + force = proposals_accepted/proposals_outstanding + if (force >=0) and (force <=1): + sentiment = get_sentimental(sentiment, force, False) + else: + sentiment = get_sentimental(sentiment, 0, False) + + key = 'sentiment' + value = sentiment + + return (key, value) + +def participants_decisions(params, step, sL, s): + network = s['network'] + participants = get_nodes_by_type(network, 'participant') + proposals = get_nodes_by_type(network, 'proposal') + candidates = [j for j in proposals if network.nodes[j]['status']=='candidate'] + sensitivity = params['sensitivity'] + + gain = .01 + delta_holdings={} + proposals_supported ={} + for i in participants: + force = network.nodes[i]['sentiment']-sensitivity + delta_holdings[i] = network.nodes[i]['holdings']*gain*force + + support = [] + for j in candidates: + affinity = network.edges[(i, j)]['affinity'] + cutoff = sensitivity*np.max([network.edges[(i,p)]['affinity'] for p in candidates]) + if cutoff <.5: + cutoff = .5 + + if affinity > cutoff: + support.append(j) + + proposals_supported[i] = support + + return({'delta_holdings':delta_holdings, 'proposals_supported':proposals_supported}) + +def update_tokens(params, step, sL, s, _input): + + network = s['network'] + delta_holdings = _input['delta_holdings'] + proposals = get_nodes_by_type(network, 'proposal') + proposals_supported = _input['proposals_supported'] + participants = get_nodes_by_type(network, 'participant') + alpha = params['alpha'] + + for i in participants: + network.nodes[i]['holdings'] = network.nodes[i]['holdings']+delta_holdings[i] + supported = proposals_supported[i] + total_affinity = np.sum([ network.edges[(i, j)]['affinity'] for j in supported]) + for j in proposals: + if j in supported: + normalized_affinity = network.edges[(i, j)]['affinity']/total_affinity + network.edges[(i, j)]['tokens'] = normalized_affinity*network.nodes[i]['holdings'] + else: + network.edges[(i, j)]['tokens'] = 0 + + prior_conviction = network.edges[(i, j)]['conviction'] + current_tokens = network.edges[(i, j)]['tokens'] + network.edges[(i, j)]['conviction'] =current_tokens+alpha*prior_conviction + + for j in proposals: + network.nodes[j]['conviction'] = np.sum([ network.edges[(i, j)]['conviction'] for i in participants]) + + key = 'network' + value = network + + return (key, value) + +def update_supply(params, step, sL, s, _input): + + supply = s['supply'] + delta_holdings = _input['delta_holdings'] + delta_supply = np.sum([v for v in delta_holdings.values()]) + + supply = supply + delta_supply + + key = 'supply' + value = supply + + return (key, value) + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# The Partial State Update Blocks +partial_state_update_blocks = [ + { + 'policies': { + #new proposals or new participants + 'random': driving_process + }, + 'variables': { + 'network': update_network, + 'funds':increment_funds, + 'supply':increment_supply + } + }, + { + 'policies': { + 'completion': check_progress #see if any of the funded proposals completes + }, + 'variables': { # The following state variables will be updated simultaneously + 'sentiment': update_sentiment_on_completion, #note completing decays sentiment, completing bumps it + 'network': complete_proposal #book-keeping + } + }, + { + 'policies': { + 'release': trigger_function #check each proposal to see if it passes + }, + 'variables': { # The following state variables will be updated simultaneously + 'funds': decrement_funds, #funds expended + 'sentiment': update_sentiment_on_release, #releasing funds can bump sentiment + 'network': update_proposals #reset convictions, and participants sentiments + #update based on affinities + } + }, + { + 'policies': { + 'participants_act': participants_decisions, #high sentiment, high affinity =>buy + #low sentiment, low affinities => burn + #assign tokens to top affinities + }, + 'variables': { + 'supply': update_supply, + 'network': update_tokens #update everyones holdings + #and their conviction for each proposal + } + } +] + +n= 25 #initial participants +m= 3 #initial proposals + +initial_sentiment = .5 + +network, initial_funds, initial_supply, total_requested = initialize_network(n,m,total_funds_given_total_supply,trigger_threshold) + +initial_conditions = {'network':network, + 'supply': initial_supply, + 'funds':initial_funds, + 'sentiment': initial_sentiment} + +#power of 1 token forever +# conviction_capactity = [2] +# alpha = [1-1/cc for cc in conviction_capactity] +# print(alpha) + +params={ + 'sensitivity': [.75], + 'tmin': [7], #unit days; minimum periods passed before a proposal can pass + 'sentiment_decay': [.001], #termed mu in the state update function + 'alpha': [0.5], + 'base_completion_rate': [10], + 'trigger_func': [trigger_threshold] +} + + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# Settings of general simulation parameters, unrelated to the system itself +# `T` is a range with the number of discrete units of time the simulation will run for; +# `N` is the number of times the simulation will be run (Monte Carlo runs) +time_periods_per_run = 250 +monte_carlo_runs = 1 + +simulation_parameters = config_sim({ + 'T': range(time_periods_per_run), + 'N': monte_carlo_runs, + 'M': params +}) + + +from cadCAD.configuration import append_configs + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# The configurations above are then packaged into a `Configuration` object +append_configs( + initial_state=initial_conditions, #dict containing variable names and initial values + partial_state_update_blocks=partial_state_update_blocks, #dict containing state update functions + sim_configs=simulation_parameters #dict containing simulation parameters +) + +from cadCAD.engine import ExecutionMode, ExecutionContext, Executor +from cadCAD import configs +import pandas as pd + +exec_mode = ExecutionMode() +multi_proc_ctx = ExecutionContext(context=exec_mode.multi_proc) +run = Executor(exec_context=multi_proc_ctx, configs=configs) + +i = 0 +for raw_result, tensor_field in run.execute(): + result = pd.DataFrame(raw_result) + print() + print(f"Tensor Field: {type(tensor_field)}") + print(tabulate(tensor_field, headers='keys', tablefmt='psql')) + print(f"Output: {type(result)}") + print(tabulate(result, headers='keys', tablefmt='psql')) + print() + i += 1