os refactor pt 1

This commit is contained in:
Joshua E. Jodesty 2019-08-21 14:27:31 -04:00
parent 67c46cfe09
commit 747ec36e50
10 changed files with 27 additions and 169 deletions

View File

@ -9,8 +9,6 @@ from cadCAD.configuration.utils import exo_update_per_ts
from cadCAD.configuration.utils.policyAggregation import dict_elemwise_sum from cadCAD.configuration.utils.policyAggregation import dict_elemwise_sum
from cadCAD.configuration.utils.depreciationHandler import sanitize_partial_state_updates, sanitize_config from cadCAD.configuration.utils.depreciationHandler import sanitize_partial_state_updates, sanitize_config
# policy_ops=[foldr(dict_elemwise_sum())]
# policy_ops=[reduce, lambda a, b: {**a, **b}]
class Configuration(object): class Configuration(object):
def __init__(self, sim_config={}, initial_state={}, seeds={}, env_processes={}, def __init__(self, sim_config={}, initial_state={}, seeds={}, env_processes={},
@ -28,7 +26,7 @@ class Configuration(object):
sanitize_config(self) sanitize_config(self)
# ToDo: Remove Seeds
def append_configs(sim_configs={}, initial_state={}, seeds={}, raw_exogenous_states={}, env_processes={}, def append_configs(sim_configs={}, initial_state={}, seeds={}, raw_exogenous_states={}, env_processes={},
partial_state_update_blocks={}, policy_ops=[lambda a, b: a + b], _exo_update_per_ts: bool = True) -> None: partial_state_update_blocks={}, policy_ops=[lambda a, b: a + b], _exo_update_per_ts: bool = True) -> None:
if _exo_update_per_ts is True: if _exo_update_per_ts is True:

View File

@ -5,12 +5,10 @@ from fn.func import curried
from funcy import curry from funcy import curry
import pandas as pd import pandas as pd
# Temporary
from cadCAD.configuration.utils.depreciationHandler import sanitize_partial_state_updates from cadCAD.configuration.utils.depreciationHandler import sanitize_partial_state_updates
from cadCAD.utils import dict_filter, contains_type, flatten_tabulated_dict, tabulate_dict from cadCAD.utils import dict_filter, contains_type, flatten_tabulated_dict, tabulate_dict
# ToDo: Fix - Returns empty when partial_state_update is missing in Configuration
class TensorFieldReport: class TensorFieldReport:
def __init__(self, config_proc): def __init__(self, config_proc):
self.config_proc = config_proc self.config_proc = config_proc
@ -56,7 +54,6 @@ def time_step(dt_str, dt_format='%Y-%m-%d %H:%M:%S', _timedelta = tstep_delta):
return t.strftime(dt_format) return t.strftime(dt_format)
# ToDo: Inject in first elem of last PSUB from Historical state
ep_t_delta = timedelta(days=0, minutes=0, seconds=1) ep_t_delta = timedelta(days=0, minutes=0, seconds=1)
def ep_time_step(s_condition, dt_str, fromat_str='%Y-%m-%d %H:%M:%S', _timedelta = ep_t_delta): def ep_time_step(s_condition, dt_str, fromat_str='%Y-%m-%d %H:%M:%S', _timedelta = ep_t_delta):
# print(dt_str) # print(dt_str)
@ -65,7 +62,7 @@ def ep_time_step(s_condition, dt_str, fromat_str='%Y-%m-%d %H:%M:%S', _timedelta
else: else:
return dt_str return dt_str
# mech_sweep_filter
def partial_state_sweep_filter(state_field, partial_state_updates): def partial_state_sweep_filter(state_field, partial_state_updates):
partial_state_dict = dict([(k, v[state_field]) for k, v in partial_state_updates.items()]) partial_state_dict = dict([(k, v[state_field]) for k, v in partial_state_updates.items()])
return dict([ return dict([
@ -77,7 +74,7 @@ def partial_state_sweep_filter(state_field, partial_state_updates):
def state_sweep_filter(raw_exogenous_states): def state_sweep_filter(raw_exogenous_states):
return dict([(k, v) for k, v in raw_exogenous_states.items() if isinstance(v, list)]) return dict([(k, v) for k, v in raw_exogenous_states.items() if isinstance(v, list)])
# sweep_mech_states
@curried @curried
def sweep_partial_states(_type, in_config): def sweep_partial_states(_type, in_config):
configs = [] configs = []
@ -129,16 +126,19 @@ def exo_update_per_ts(ep):
return {es: ep_decorator(f, es) for es, f in ep.items()} return {es: ep_decorator(f, es) for es, f in ep.items()}
def trigger_condition(s, pre_conditions, cond_opp): def trigger_condition(s, pre_conditions, cond_opp):
condition_bools = [s[field] in precondition_values for field, precondition_values in pre_conditions.items()] condition_bools = [s[field] in precondition_values for field, precondition_values in pre_conditions.items()]
return reduce(cond_opp, condition_bools) return reduce(cond_opp, condition_bools)
def apply_state_condition(pre_conditions, cond_opp, y, f, _g, step, sL, s, _input): def apply_state_condition(pre_conditions, cond_opp, y, f, _g, step, sL, s, _input):
if trigger_condition(s, pre_conditions, cond_opp): if trigger_condition(s, pre_conditions, cond_opp):
return f(_g, step, sL, s, _input) return f(_g, step, sL, s, _input)
else: else:
return y, s[y] return y, s[y]
def var_trigger(y, f, pre_conditions, cond_op): def var_trigger(y, f, pre_conditions, cond_op):
return lambda _g, step, sL, s, _input: apply_state_condition(pre_conditions, cond_op, y, f, _g, step, sL, s, _input) return lambda _g, step, sL, s, _input: apply_state_condition(pre_conditions, cond_op, y, f, _g, step, sL, s, _input)
@ -173,7 +173,6 @@ def env_trigger(end_substep):
curry(trigger)(end_substep)(trigger_field)(trigger_vals)(funct_list) curry(trigger)(end_substep)(trigger_field)(trigger_vals)(funct_list)
# param sweep enabling middleware
def config_sim(d): def config_sim(d):
def process_variables(d): def process_variables(d):
return flatten_tabulated_dict(tabulate_dict(d)) return flatten_tabulated_dict(tabulate_dict(d))
@ -184,15 +183,18 @@ def config_sim(d):
d["M"] = [{}] d["M"] = [{}]
return d return d
def psub_list(psu_block, psu_steps): def psub_list(psu_block, psu_steps):
return [psu_block[psu] for psu in psu_steps] return [psu_block[psu] for psu in psu_steps]
def psub(policies, state_updates): def psub(policies, state_updates):
return { return {
'policies': policies, 'policies': policies,
'states': state_updates 'states': state_updates
} }
def genereate_psubs(policy_grid, states_grid, policies, state_updates): def genereate_psubs(policy_grid, states_grid, policies, state_updates):
PSUBS = [] PSUBS = []
for policy_ids, state_list in zip(policy_grid, states_grid): for policy_ids, state_list in zip(policy_grid, states_grid):
@ -202,7 +204,7 @@ def genereate_psubs(policy_grid, states_grid, policies, state_updates):
return PSUBS return PSUBS
# ToDo: DO NOT filter sH for every state/policy update. Requires a consumable sH (new sH)
def access_block(state_history, target_field, psu_block_offset, exculsion_list=[]): def access_block(state_history, target_field, psu_block_offset, exculsion_list=[]):
exculsion_list += [target_field] exculsion_list += [target_field]
def filter_history(key_list, sH): def filter_history(key_list, sH):

View File

@ -2,8 +2,6 @@ from copy import deepcopy
def sanitize_config(config): def sanitize_config(config):
# for backwards compatibility, we accept old arguments via **kwargs
# TODO: raise specific deprecation warnings for key == 'state_dict', key == 'seed', key == 'mechanisms'
for key, value in config.kwargs.items(): for key, value in config.kwargs.items():
if key == 'state_dict': if key == 'state_dict':
config.initial_state = value config.initial_state = value
@ -18,8 +16,6 @@ def sanitize_config(config):
def sanitize_partial_state_updates(partial_state_updates): def sanitize_partial_state_updates(partial_state_updates):
new_partial_state_updates = deepcopy(partial_state_updates) new_partial_state_updates = deepcopy(partial_state_updates)
# for backwards compatibility we accept the old keys
# ('behaviors' and 'states') and rename them
def rename_keys(d): def rename_keys(d):
if 'behaviors' in d: if 'behaviors' in d:
d['policies'] = d.pop('behaviors') d['policies'] = d.pop('behaviors')
@ -28,8 +24,6 @@ def sanitize_partial_state_updates(partial_state_updates):
d['variables'] = d.pop('states') d['variables'] = d.pop('states')
# Also for backwards compatibility, we accept partial state update blocks both as list or dict
# No need for a deprecation warning as it's already raised by cadCAD.utils.key_filter
if isinstance(new_partial_state_updates, list): if isinstance(new_partial_state_updates, list):
for v in new_partial_state_updates: for v in new_partial_state_updates:
rename_keys(v) rename_keys(v)

View File

@ -1,6 +1,7 @@
from fn.op import foldr from fn.op import foldr
from fn.func import curried from fn.func import curried
def get_base_value(x): def get_base_value(x):
if isinstance(x, str): if isinstance(x, str):
return '' return ''
@ -17,7 +18,7 @@ def policy_to_dict(v):
add = lambda a, b: a + b add = lambda a, b: a + b
# df_union = lambda a, b: ...
@curried @curried
def foldr_dict_vals(f, d): def foldr_dict_vals(f, d):

View File

@ -1,23 +1,22 @@
from collections import namedtuple from collections import namedtuple
from copy import deepcopy
from inspect import getmembers, ismethod from inspect import getmembers, ismethod
from pandas.core.frame import DataFrame from pandas.core.frame import DataFrame
from cadCAD.utils import SilentDF from cadCAD.utils import SilentDF
def val_switch(v): def val_switch(v):
if isinstance(v, DataFrame) is True: if isinstance(v, DataFrame) is True:
return SilentDF(v) return SilentDF(v)
else: else:
return v return v
class udcView(object): class udcView(object):
def __init__(self, d, masked_members): def __init__(self, d, masked_members):
self.__dict__ = d self.__dict__ = d
self.masked_members = masked_members self.masked_members = masked_members
# returns dict to dataframe
def __repr__(self): def __repr__(self):
members = {} members = {}
variables = { variables = {
@ -27,17 +26,7 @@ class udcView(object):
members['methods'] = [k for k, v in self.__dict__.items() if str(type(v)) == "<class 'method'>"] members['methods'] = [k for k, v in self.__dict__.items() if str(type(v)) == "<class 'method'>"]
members.update(variables) members.update(variables)
return f"{members}" #[1:-1] return f"{members}"
# def __repr__(self):
# members = {}
# variables = {
# k: val_switch(v) for k, v in self.__dict__.items()
# if str(type(v)) != "<class 'method'>" and k not in self.masked_members and k == 'x' # and isinstance(v, DataFrame) is not True
# }
#
# members.update(variables)
# return f"{members}" #[1:-1]
class udcBroker(object): class udcBroker(object):

View File

@ -93,7 +93,6 @@ class Executor:
final_result = None final_result = None
if self.exec_context == ExecutionMode.single_proc: if self.exec_context == ExecutionMode.single_proc:
# ToDO: Deprication Handler - "sanitize" in appropriate place
tensor_field = create_tensor_field(partial_state_updates.pop(), eps.pop()) tensor_field = create_tensor_field(partial_state_updates.pop(), eps.pop())
result = self.exec_method(simulation_execs, var_dict_list, states_lists, configs_structs, env_processes_list, Ts, Ns) result = self.exec_method(simulation_execs, var_dict_list, states_lists, configs_structs, env_processes_list, Ts, Ns)
final_result = result, tensor_field final_result = result, tensor_field

View File

@ -63,9 +63,6 @@ class Executor:
) for k, val_list in new_dict.items() ) for k, val_list in new_dict.items()
} }
# [f1] = ops
# return {k: reduce(f1, val_list) for k, val_list in new_dict.items()}
# return foldr(call, col_results)(ops)
def apply_env_proc( def apply_env_proc(
self, self,
@ -98,7 +95,6 @@ class Executor:
return state_dict return state_dict
# ToDo: Redifined as a function that applies the tensor field to a set og last conditions
# mech_step # mech_step
def partial_state_update( def partial_state_update(
self, self,
@ -119,8 +115,6 @@ class Executor:
) )
# ToDo: add env_proc generator to `last_in_copy` iterator as wrapper function
# ToDo: Can be multithreaded ??
def generate_record(state_funcs): def generate_record(state_funcs):
for f in state_funcs: for f in state_funcs:
yield self.state_update_exception(f(sweep_dict, sub_step, sH, last_in_obj, _input)) yield self.state_update_exception(f(sweep_dict, sub_step, sH, last_in_obj, _input))
@ -134,7 +128,6 @@ class Executor:
last_in_copy: Dict[str, Any] = transfer_missing_fields(last_in_obj, dict(generate_record(state_funcs))) last_in_copy: Dict[str, Any] = transfer_missing_fields(last_in_obj, dict(generate_record(state_funcs)))
last_in_copy: Dict[str, Any] = self.apply_env_proc(sweep_dict, env_processes, last_in_copy) last_in_copy: Dict[str, Any] = self.apply_env_proc(sweep_dict, env_processes, last_in_copy)
# ToDo: make 'substep' & 'timestep' reserve fields
last_in_copy['substep'], last_in_copy['timestep'], last_in_copy['run'] = sub_step, time_step, run last_in_copy['substep'], last_in_copy['timestep'], last_in_copy['run'] = sub_step, time_step, run
sL.append(last_in_copy) sL.append(last_in_copy)
@ -155,7 +148,6 @@ class Executor:
sub_step = 0 sub_step = 0
states_list_copy: List[Dict[str, Any]] = deepcopy(simulation_list[-1]) states_list_copy: List[Dict[str, Any]] = deepcopy(simulation_list[-1])
# ToDo: Causes Substep repeats in sL:
genesis_states: Dict[str, Any] = states_list_copy[-1] genesis_states: Dict[str, Any] = states_list_copy[-1]
if len(states_list_copy) == 1: if len(states_list_copy) == 1:
@ -167,7 +159,6 @@ class Executor:
del states_list_copy del states_list_copy
states_list: List[Dict[str, Any]] = [genesis_states] states_list: List[Dict[str, Any]] = [genesis_states]
# ToDo: Was causing Substep repeats in sL, use for yield
sub_step += 1 sub_step += 1
for [s_conf, p_conf] in configs: # tensor field for [s_conf, p_conf] in configs: # tensor field
@ -196,7 +187,6 @@ class Executor:
) -> List[List[Dict[str, Any]]]: ) -> List[List[Dict[str, Any]]]:
time_seq: List[int] = [x + 1 for x in time_seq] time_seq: List[int] = [x + 1 for x in time_seq]
# ToDo: simulation_list should be a Tensor that is generated throughout the Executor
simulation_list: List[List[Dict[str, Any]]] = [states_list] simulation_list: List[List[Dict[str, Any]]] = [states_list]
for time_step in time_seq: for time_step in time_seq:
@ -209,8 +199,6 @@ class Executor:
return simulation_list return simulation_list
# ToDo: Below can be recieved from a tensor field
# configs: List[Tuple[List[Callable], List[Callable]]]
def simulation( def simulation(
self, self,
sweep_dict: Dict[str, List[Any]], sweep_dict: Dict[str, List[Any]],

View File

@ -24,8 +24,6 @@ def retrieve_state(l, offset):
return l[last_index(l) + offset + 1] return l[last_index(l) + offset + 1]
# exception_function = f(sub_step, sL, sL[-2], _input)
# try_function = f(sub_step, sL, last_mut_obj, _input)
@curried @curried
def engine_exception(ErrorType, error_message, exception_function, try_function): def engine_exception(ErrorType, error_message, exception_function, try_function):
try: try:
@ -38,5 +36,3 @@ def engine_exception(ErrorType, error_message, exception_function, try_function)
@curried @curried
def fit_param(param, x): def fit_param(param, x):
return x + param return x + param
# fit_param = lambda param: lambda x: x + param

View File

@ -11,15 +11,11 @@ class SilentDF(DataFrame):
def __repr__(self): def __repr__(self):
return str(hex(id(DataFrame))) #"pandas.core.frame.DataFrame" return str(hex(id(DataFrame))) #"pandas.core.frame.DataFrame"
def append_dict(dict, new_dict): def append_dict(dict, new_dict):
dict.update(new_dict) dict.update(new_dict)
return dict return dict
# def val_switch(v):
# if isinstance(v, DataFrame) is True or isinstance(v, SilentDF) is True:
# return SilentDF(v)
# else:
# return v.x
class IndexCounter: class IndexCounter:
def __init__(self): def __init__(self):
@ -29,8 +25,6 @@ class IndexCounter:
self.i += 1 self.i += 1
return self.i return self.i
# def compose(*functions):
# return reduce(lambda f, g: lambda x: f(g(x)), functions, lambda x: x)
def compose(*functions): def compose(*functions):
return reduce(lambda f, g: lambda x: f(g(x)), functions, lambda x: x) return reduce(lambda f, g: lambda x: f(g(x)), functions, lambda x: x)
@ -108,8 +102,7 @@ def contains_type(_collection, type):
def drop_right(l, n): def drop_right(l, n):
return l[:len(l) - n] return l[:len(l) - n]
# backwards compatibility
# ToDo: Encapsulate in function
def key_filter(l, keyname): def key_filter(l, keyname):
if (type(l) == list): if (type(l) == list):
return [v[keyname] for v in l] return [v[keyname] for v in l]
@ -147,23 +140,3 @@ def curry_pot(f, *argv):
return f(argv[0], argv[1], argv[2]) return f(argv[0], argv[1], argv[2])
else: else:
raise TypeError('curry_pot() needs 3 or 4 positional arguments') raise TypeError('curry_pot() needs 3 or 4 positional arguments')
# def curry_pot(f, *argv):
# sweep_ind = f.__name__[0:5] == 'sweep'
# arg_len = len(argv)
# if sweep_ind is True and arg_len == 4:
# return f(argv[0])(argv[1])(argv[2])(argv[3])
# elif sweep_ind is False and arg_len == 4:
# return f(argv[0])(argv[1])(argv[2])(argv[3])
# elif sweep_ind is True and arg_len == 3:
# return f(argv[0])(argv[1])(argv[2])
# elif sweep_ind is 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 rename(newname):
# def decorator(f):
# f.__name__ = newname
# return f
# return decorator

View File

@ -1,37 +1,46 @@
from funcy import curry from funcy import curry
from cadCAD.configuration.utils import ep_time_step, time_step from cadCAD.configuration.utils import ep_time_step, time_step
def increment(y, incr_by): def increment(y, incr_by):
return lambda _g, step, sL, s, _input: (y, s[y] + incr_by) return lambda _g, step, sL, s, _input: (y, s[y] + incr_by)
def track(y): def track(y):
return lambda _g, step, sL, s, _input: (y, s[y].x) return lambda _g, step, sL, s, _input: (y, s[y].x)
def simple_state_update(y, x): def simple_state_update(y, x):
return lambda _g, step, sH, s, _input: (y, x) return lambda _g, step, sH, s, _input: (y, x)
def simple_policy_update(y): def simple_policy_update(y):
return lambda _g, step, sH, s: y return lambda _g, step, sH, s: y
def update_timestamp(y, timedelta, format): def update_timestamp(y, timedelta, format):
return lambda _g, step, sL, s, _input: ( return lambda _g, step, sL, s, _input: (
y, y,
ep_time_step(s, dt_str=s[y], fromat_str=format, _timedelta=timedelta) ep_time_step(s, dt_str=s[y], fromat_str=format, _timedelta=timedelta)
) )
def apply(f, y: str, incr_by: int): def apply(f, y: str, incr_by: int):
return lambda _g, step, sL, s, _input: (y, curry(f)(s[y])(incr_by)) return lambda _g, step, sL, s, _input: (y, curry(f)(s[y])(incr_by))
def add(y: str, incr_by): def add(y: str, incr_by):
return apply(lambda a, b: a + b, y, incr_by) return apply(lambda a, b: a + b, y, incr_by)
def increment_state_by_int(y: str, incr_by: int): def increment_state_by_int(y: str, incr_by: int):
return lambda _g, step, sL, s, _input: (y, s[y] + incr_by) return lambda _g, step, sL, s, _input: (y, s[y] + incr_by)
def s(y, x): def s(y, x):
return lambda _g, step, sH, s, _input: (y, x) return lambda _g, step, sH, s, _input: (y, x)
def time_model(y, substeps, time_delta, ts_format='%Y-%m-%d %H:%M:%S'): def time_model(y, substeps, time_delta, ts_format='%Y-%m-%d %H:%M:%S'):
def apply_incriment_condition(s): def apply_incriment_condition(s):
if s['substep'] == 0 or s['substep'] == substeps: if s['substep'] == 0 or s['substep'] == substeps:
@ -40,94 +49,3 @@ def time_model(y, substeps, time_delta, ts_format='%Y-%m-%d %H:%M:%S'):
return y, s[y] return y, s[y]
return lambda _g, step, sL, s, _input: apply_incriment_condition(s) return lambda _g, step, sL, s, _input: apply_incriment_condition(s)
# ToDo: Impliment Matrix reduction
#
# [
# {'conditions': [123], 'opp': lambda a, b: a and b},
# {'conditions': [123], 'opp': lambda a, b: a and b}
# ]
# def trigger_condition2(s, conditions, cond_opp):
# # print(conditions)
# condition_bools = [s[field] in precondition_values for field, precondition_values in conditions.items()]
# return reduce(cond_opp, condition_bools)
#
# def trigger_multi_conditions(s, multi_conditions, multi_cond_opp):
# # print([(d['conditions'], d['reduction_opp']) for d in multi_conditions])
# condition_bools = [
# trigger_condition2(s, conditions, opp) for conditions, opp in [
# (d['conditions'], d['reduction_opp']) for d in multi_conditions
# ]
# ]
# return reduce(multi_cond_opp, condition_bools)
#
# def apply_state_condition2(multi_conditions, multi_cond_opp, y, f, _g, step, sL, s, _input):
# if trigger_multi_conditions(s, multi_conditions, multi_cond_opp):
# return f(_g, step, sL, s, _input)
# else:
# return y, s[y]
#
# def proc_trigger2(y, f, multi_conditions, multi_cond_opp):
# return lambda _g, step, sL, s, _input: apply_state_condition2(multi_conditions, multi_cond_opp, y, f, _g, step, sL, s, _input)
#
# def timestep_trigger2(end_substep, y, f):
# multi_conditions = [
# {
# 'condition': {
# 'substep': [0, end_substep]
# },
# 'reduction_opp': lambda a, b: a and b
# }
# ]
# multi_cond_opp = lambda a, b: a and b
# return proc_trigger2(y, f, multi_conditions, multi_cond_opp)
#
# @curried
# print(env_trigger(3).__module__)
# pp.pprint(dir(env_trigger))
# @curried
# def env_proc_trigger(trigger_time, update_f, time):
# if time == trigger_time:
# return update_f
# else:
# return lambda x: x
# def p1m1(_g, step, sL, s):
# return {'param1': 1}
#
# def apply_policy_condition(policies, policy_id, f, conditions, _g, step, sL, s):
# if trigger_condition(s, conditions):
# policies[policy_id] = f(_g, step, sL, s)
# return policies
# else:
# return policies
#
# def proc_trigger2(policies, conditions, policy_id, f):
# return lambda _g, step, sL, s: apply_policy_condition(policies, policy_id, f, conditions,_g, step, sL, s)
# policies_updates = {"p1": udo_policyA, "p2": udo_policyB}
# @curried
# def proc_trigger(trigger_time, update_f, time):
# if time == trigger_time:
# return update_f
# else:
# return lambda x: x
# def repr(_g, step, sL, s, _input):
# y = 'z'
# x = s['state_udo'].__repr__()
# return (y, x)