def check(self): from dolang.symbolic import remove_timing, parse_string, str_expression p = self.data.get("projection") if p is None: raise AggregateException("Missing 'projection section'.") else: exo = self.model.symbols["exogenous"] proj = [] eqs = parse_string(p, start="assignment_block") for eq in eqs.children: lhs, _ = eq.children lhs = remove_timing(lhs) lhs = str_expression(lhs) proj.append(lhs) exo_in_proj = [e for e in exo if e in proj] diff = set(proj).difference(set(exo_in_proj)) if diff: raise AggregateException( f"Some projected values were not defined as exogenous in the agent's program: {', '.join(diff)}." ) t = self.data.get("transition") states = self.symbols.get("states") if t is not None and states is None: raise AggregateException( f"Aggregate transition equations are defined, whereas no aggregate state is filled in." ) elif t is None and states is not None: raise AggregateException( f"Aggregate states are defined, whereas no transition equation is filled in." ) elif t is not None and states is not None: trans = [] eqs = parse_string(t, start="assignment_block") for eq in eqs.children: lhs, _ = eq.children lhs = remove_timing(lhs) lhs = str_expression(lhs) trans.append(lhs) states_in_trans = [e for e in states if e in trans] trans_in_states = [e for e in trans if e in states] diff = set(trans).difference(set(states_in_trans)) if diff: raise AggregateException( f"Some variables defined in transition equations are not filled in aggregate states: {', '.join(diff)}." ) diff = set(states).difference(set(trans_in_states)) if diff: raise AggregateException( f"Some aggregate states do not have transition equations filled in: {', '.join(diff)}." )
def test_remove_timing(): from dolang.symbolic import parse_string, remove_timing e = parse_string("sin(a(1)+b+f(1)+f(4)+a[t+1])") assert isinstance(e, Tree) s = to_source(e) rr = remove_timing(s) assert rr == "sin(a + b + f + f + a)"
def get_calibration(self): from dolang.symbolic import remove_timing import copy calibration = dict() for k, v in self.data.get("calibration", {}).items(): if v.tag == "tag:yaml.org,2002:str": expr = parse_string(v) expr = remove_timing(expr) expr = str_expression(expr) else: expr = float(v.value) kk = remove_timing(parse_string(k)) kk = str_expression(kk) calibration[kk] = expr from dolang.triangular_solver import solve_triangular_system return solve_triangular_system(calibration)
def get_calibration(self): # if self.__calibration__ is None: from dolang.symbolic import remove_timing import copy symbols = self.symbols calibration = dict() for k, v in self.data.get("calibration", {}).items(): if v.tag == "tag:yaml.org,2002:str": expr = parse_string(v) expr = remove_timing(expr) expr = str_expression(expr) else: expr = float(v.value) kk = remove_timing(parse_string(k)) kk = str_expression(kk) calibration[kk] = expr definitions = self.definitions initial_values = { "exogenous": 0, "expectations": 0, "values": 0, "controls": float("nan"), "states": float("nan"), } # variables defined by a model equation default to using these definitions initialized_from_model = { "values": "value", "expectations": "expectation", "direct_responses": "direct_response", } for k, v in definitions.items(): kk = remove_timing(k) if kk not in calibration: if isinstance(v, str): vv = remove_timing(v) else: vv = v calibration[kk] = vv for symbol_group in symbols: if symbol_group not in initialized_from_model.keys(): if symbol_group in initial_values: default = initial_values[symbol_group] else: default = float("nan") for s in symbols[symbol_group]: if s not in calibration: calibration[s] = default from dolang.triangular_solver import solve_triangular_system return solve_triangular_system(calibration)
def definitions(self): from yaml import ScalarNode if self.__definitions__ is None: # at this stage, basic_symbols doesn't contain auxiliaries basic_symbols = self.symbols vars = sum( [ basic_symbols[k] for k in basic_symbols.keys() if k != "parameters" ], [], ) # # auxiliaries = [remove_timing(parse_string(k)) for k in self.data.get('definitions', {})] # # auxiliaries = [str_expression(e) for e in auxiliaries] # # symbols['auxiliaries'] = auxiliaries if "definitions" not in self.data: self.__definitions__ = {} # self.__symbols__['auxiliaries'] = [] elif isinstance(self.data["definitions"], ScalarNode): definitions = {} # new-style from lark import Token def_block_tree = parse_string(self.data["definitions"], start="assignment_block") def_block_tree = sanitize( def_block_tree ) # just to replace (v,) by (v,0) # TODO: remove auxiliaries = [] for eq_tree in def_block_tree.children: lhs, rhs = eq_tree.children tok_name: Token = lhs.children[0].children[0] tok_date: Token = lhs.children[1].children[0] name = tok_name.value date = int(tok_date.value) if name in vars: raise Exception( f"definitions:{tok_name.line}:{tok_name.column}: Auxiliary variable '{name}'' already defined." ) if date != 0: raise Exception( f"definitions:{tok_name.line}:{tok_name.column}: Auxiliary variable '{name}' must be defined at date 't'." ) # here we could check some stuff from dolang import list_symbols syms = list_symbols(rhs) for p in syms.parameters: if p in vars: raise Exception( f"definitions:{tok_name.line}: Symbol '{p}' is defined as a variable. Can't appear as a parameter." ) if p not in self.symbols["parameters"]: raise Exception( f"definitions:{tok_name.line}: Paremeter '{p}' must be defined as a model symbol." ) for v in syms.variables: if v[0] not in vars: raise Exception( f"definitions:{tok_name.line}: Variable '{v[0]}[t]' is not defined." ) auxiliaries.append(name) vars.append(name) definitions[str_expression(lhs)] = str_expression(rhs) self.__symbols__["auxiliaries"] = auxiliaries self.__definitions__ = definitions else: # old style from dolang.symbolic import remove_timing auxiliaries = [ remove_timing(parse_string(k)) for k in self.data.get("definitions", {}) ] auxiliaries = [str_expression(e) for e in auxiliaries] self.__symbols__["auxiliaries"] = auxiliaries vars = self.variables auxs = [] definitions = self.data["definitions"] d = dict() for i in range(len(definitions.value)): kk = definitions.value[i][0] if self.__compat__: k = parse_string(kk.value) if k.data == "symbol": # TODO: warn that definitions should be timed from dolang.grammar import create_variable k = create_variable(k.children[0].value, 0) else: k = parse_string(kk.value, start="variable") k = sanitize(k, variables=vars) assert k.children[1].children[0].value == "0" vv = definitions.value[i][1] v = parse_string(vv, start="formula") v = sanitize(v, variables=vars) v = str_expression(v) key = str_expression(k) vars.append(key) d[key] = v auxs.append(remove_timing(key)) self.__symbols__["auxiliaries"] = auxs self.__definitions__ = d return self.__definitions__