exo_proc per ts decorator & refactor mech_step

This commit is contained in:
Joshua E. Jodesty 2018-11-08 10:18:47 -05:00
parent 098fc04f3d
commit ee5f912908
5 changed files with 53 additions and 44 deletions

View File

@ -1,5 +1,5 @@
import pandas as pd import pandas as pd
from functools import partial, reduce from functools import reduce
def state_identity(k): def state_identity(k):
return lambda step, sL, s, _input: (k, s[k]) return lambda step, sL, s, _input: (k, s[k])
@ -37,9 +37,7 @@ def generate_config(state_dict, mechanisms, exo_proc):
sdf_values, bdf_values = sdf.values.tolist(), bdf.values.tolist() sdf_values, bdf_values = sdf.values.tolist(), bdf.values.tolist()
else: else:
sdf_values = sdf.values.tolist() sdf_values = sdf.values.tolist()
# print(sdf_values)
bdf_values = [ [b_identity] * len(sdf_values) for n in range(mechanisms) ] bdf_values = [ [b_identity] * len(sdf_values) for n in range(mechanisms) ]
# print(bdf_values)
return sdf_values, bdf_values return sdf_values, bdf_values
def only_ep_handler(state_dict): def only_ep_handler(state_dict):

View File

@ -1,11 +1,14 @@
from copy import deepcopy from copy import deepcopy
from fn import op, _ from fn.op import foldr, call
from fn import _
from ui.config import behavior_ops
def getColResults(step, sL, s, funcs): def getColResults(step, sL, s, funcs):
return list(map(lambda f: f(step, sL, s), funcs)) return list(map(lambda f: f(step, sL, s), funcs))
def getBehaviorInput(step, sL, s, funcs): # Data Type reduction
return op.foldr(_ + _)(getColResults(step, sL, s, funcs)) def getBehaviorInput(step, sL, s, funcs, ops = behavior_ops[::-1]):
return foldr(call, getColResults(step, sL, s, funcs))(ops)
def apply_env_proc(env_processes, state_dict, step): def apply_env_proc(env_processes, state_dict, step):
for state in state_dict.keys(): for state in state_dict.keys():
@ -21,26 +24,23 @@ def exception_handler(f, m_step, sL, last_mut_obj, _input):
def mech_step(m_step, sL, state_funcs, behavior_funcs, env_processes, t_step): def mech_step(m_step, sL, state_funcs, behavior_funcs, env_processes, t_step):
in_copy, mutatable_copy, out_copy = deepcopy(sL), deepcopy(sL), deepcopy(sL) last_in_obj = sL[-1]
last_in_obj, last_mut_obj = in_copy[-1], mutatable_copy[-1]
_input = exception_handler(getBehaviorInput, m_step, sL, last_in_obj, behavior_funcs) _input = exception_handler(getBehaviorInput, m_step, sL, last_in_obj, behavior_funcs)
# del last_in_obj
# print(len(state_funcs)) last_in_copy = dict([ exception_handler(f, m_step, sL, last_in_obj, _input) for f in state_funcs ])
# print(str(m_step) + ': ' + str(last_in_copy))
last_mut_obj = dict([ # mutating last_in_copy
exception_handler(f, m_step, sL, last_mut_obj, _input) for f in state_funcs apply_env_proc(env_processes, last_in_copy, last_in_copy['timestamp'])
])
# print(str(m_step) + ': ' + str(last_mut_obj))
apply_env_proc(env_processes, last_mut_obj, last_mut_obj['timestamp']) last_in_copy["mech_step"], last_in_copy["time_step"] = m_step, t_step
sL.append(last_in_copy)
last_mut_obj["mech_step"], last_mut_obj["time_step"] = m_step, t_step del last_in_copy
out_copy.append(last_mut_obj)
del last_in_obj, last_mut_obj, in_copy, mutatable_copy, return sL
return out_copy
def block_gen(states_list, configs, env_processes, t_step): def block_gen(states_list, configs, env_processes, t_step):
@ -68,12 +68,13 @@ def pipeline(states_list, configs, env_processes, time_seq):
simulation_list = [states_list] simulation_list = [states_list]
for time_step in time_seq: for time_step in time_seq:
pipeline_run = block_gen(simulation_list[-1], configs, env_processes, time_step) pipeline_run = block_gen(simulation_list[-1], configs, env_processes, time_step)
head, *pipeline_run = pipeline_run _, *pipeline_run = pipeline_run
simulation_list.append(pipeline_run) simulation_list.append(pipeline_run)
return simulation_list return simulation_list
# Del head
def simulation(states_list, configs, env_processes, time_seq, runs): def simulation(states_list, configs, env_processes, time_seq, runs):
pipeline_run = [] pipeline_run = []
for run in range(runs): for run in range(runs):
@ -84,7 +85,7 @@ def simulation(states_list, configs, env_processes, time_seq, runs):
pipeline_run += simulation_list pipeline_run += simulation_list
else: else:
transient_states_list = [pipeline_run[-1][-1]] transient_states_list = [pipeline_run[-1][-1]]
head, *tail = pipeline(transient_states_list, configs, env_processes, time_seq) _, *tail = pipeline(transient_states_list, configs, env_processes, time_seq)
pipeline_run += tail pipeline_run += tail
return pipeline_run return pipeline_run

View File

@ -17,7 +17,7 @@ def main():
# print(states_list) # print(states_list)
# print(configs) # print(configs)
# p = pipeline(states_list, configs, env_processes, range(10)) # p = pipeline(states_list, configs, env_processes, range(10))
T = range(5) T = sim_config['T']
N = sim_config['N'] N = sim_config['N']
# Dimensions: N x r x mechs # Dimensions: N x r x mechs

View File

@ -1,6 +1,6 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
from decimal import Decimal from decimal import Decimal
from functools import partial from fn.func import curried
flatten = lambda l: [item for sublist in l for item in sublist] flatten = lambda l: [item for sublist in l for item in sublist]
@ -35,13 +35,12 @@ def bound_norm_random(rng, low, high):
res = bound_norm_random(rng, low, high) res = bound_norm_random(rng, low, high)
return Decimal(res) return Decimal(res)
def proc_trigger(trigger_step, update_f): @curried
def step_trigger(trigger_step, update_f, step): def proc_trigger(trigger_step, update_f, step):
if step == trigger_step: if step == trigger_step:
return update_f return update_f
else: else:
return lambda x: x return lambda x: x
return partial(step_trigger, trigger_step, update_f)
# accept timedelta instead of timedelta params # 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): def time_step(dt_str, dt_format='%Y-%m-%d %H:%M:%S', days=0, minutes=0, seconds=30):
@ -56,6 +55,15 @@ def ep_time_step(s, dt_str, fromat_str='%Y-%m-%d %H:%M:%S', days=0, minutes=0, s
else: else:
return dt_str return dt_str
def exo_update_per_ts(ep):
@curried
def ep_decorator(f, y, step, sL, s, _input):
if s['mech_step'] + 1 == 1: # inside f body to reduce performance costs
return f(step, sL, s, _input)
else:
return (y, s[y])
return {es: ep_decorator(f, es) for es, f in ep.items()}
# def create_tensor_field(mechanisms, env_poc, keys=['behaviors', 'states']): # def create_tensor_field(mechanisms, env_poc, keys=['behaviors', 'states']):
# dfs = [ create_matrix_field(mechanisms, k) for k in keys ] # dfs = [ create_matrix_field(mechanisms, k) for k in keys ]
# df = pd.concat(dfs, axis=1) # df = pd.concat(dfs, axis=1)

View File

@ -1,4 +1,6 @@
from engine.utils import bound_norm_random, ep_time_step, proc_trigger from engine.utils import bound_norm_random, ep_time_step, proc_trigger, exo_update_per_ts
from fn.op import foldr
from fn import _
import numpy as np import numpy as np
from decimal import Decimal from decimal import Decimal
@ -58,27 +60,23 @@ def s2m3(step, sL, s, _input):
# Exogenous States # Exogenous States
proc_one_coef_A = 0.7 proc_one_coef_A = 0.7
proc_one_coef_B = 1.3 proc_one_coef_B = 1.3
def es3p1(step, sL, s, _input): def es3p1(step, sL, s, _input):
y = 's3' y = 's3'
if s['mech_step']+1 == 1: # inside f body to reduce performance costs x = s['s3'] * bound_norm_random(seed['a'], proc_one_coef_A, proc_one_coef_B)
x = s['s3'] * bound_norm_random(seed['a'], proc_one_coef_A, proc_one_coef_B) return (y, x)
return (y, x)
else:
return (y, s[y])
def es4p2(step, sL, s, _input): def es4p2(step, sL, s, _input):
y = 's4' y = 's4'
if s['mech_step']+1 == 1: # inside f body to reduce performance costs x = s['s4'] * bound_norm_random(seed['b'], proc_one_coef_A, proc_one_coef_B)
x = s['s4'] * bound_norm_random(seed['b'], proc_one_coef_A, proc_one_coef_B) return (y, x)
return (y, x)
else:
return (y, s[y])
def es5p2(step, sL, s, _input): # accept timedelta instead of timedelta params def es5p2(step, sL, s, _input): # accept timedelta instead of timedelta params
y = 'timestamp' y = 'timestamp'
x = ep_time_step(s, s['timestamp'], seconds=1) x = ep_time_step(s, s['timestamp'], seconds=1)
return (y, x) return (y, x)
# Environment States # Environment States
def env_a(x): def env_a(x):
return 10 return 10
@ -96,11 +94,13 @@ state_dict = {
'timestamp': '2018-10-01 15:16:24' 'timestamp': '2018-10-01 15:16:24'
} }
exogenous_states = { exogenous_states = exo_update_per_ts(
{
"s3": es3p1, "s3": es3p1,
"s4": es4p2, "s4": es4p2,
"timestamp": es5p2 "timestamp": es5p2
} }
)
env_processes = { env_processes = {
"s3": proc_trigger('2018-10-01 15:16:25', env_a), "s3": proc_trigger('2018-10-01 15:16:25', env_a),
@ -110,6 +110,7 @@ env_processes = {
# test return vs. non-return functions as lambdas # test return vs. non-return functions as lambdas
# test fully defined functions # test fully defined functions
# genesis Sites should always be there # genesis Sites should always be there
behavior_ops = [foldr(_ + _), lambda x: x + 0]
mechanisms = { mechanisms = {
"m1": { "m1": {
"behaviors": { "behaviors": {
@ -144,5 +145,6 @@ mechanisms = {
} }
sim_config = { sim_config = {
"N": 2 "N": 2,
"T": range(5)
} }