def __init__(self, values, model=None): from dolang.symbolic import sanitize, stringify exogenous = model.symbols['exogenous'] states = model.symbols['states'] controls = model.symbols['controls'] parameters = model.symbols['parameters'] preamble = dict([(s, values[s]) for s in values.keys() if s not in controls]) equations = [values[s] for s in controls] variables = exogenous + states + controls + [*preamble.keys()] preamble_str = dict() for k in [*preamble.keys()]: v = preamble[k] if '(' not in k: vv = f'{k}(0)' else: vv = k preamble_str[stringify(vv)] = stringify(sanitize(v, variables)) # let's reorder the preamble from dolang.triangular_solver import get_incidence, triangular_solver incidence = get_incidence(preamble_str) sol = triangular_solver(incidence) kk = [*preamble_str.keys()] preamble_str = dict([(kk[k], preamble_str[kk[k]]) for k in sol]) equations = [ dolang.symbolic.sanitize(eq, variables) for eq in equations ] equations_strings = [ dolang.stringify(eq, variables) for eq in equations ] args = dict([('m', [(e, 0) for e in exogenous]), ('s', [(e, 0) for e in states]), ('p', [e for e in parameters])]) args = dict([(k, [stringify_symbol(e) for e in v]) for k, v in args.items()]) targets = [stringify_symbol((e, 0)) for e in controls] eqs = dict([(targets[i], eq) for i, eq in enumerate(equations_strings)]) fff = FlatFunctionFactory(preamble_str, eqs, args, 'custom_dr') fun, gufun = make_method_from_factory(fff) self.p = model.calibration['parameters'] self.exo_grid = model.exogenous.discretize() # this is never used self.endo_grid = model.get_grid() self.gufun = gufun
def ℰ(self): if self.__equilibrium__ is None: if self.features["with-aggregate-states"]: arguments_ = { "e": [(e, 0) for e in self.model.symbols["exogenous"]], "s": [(e, 0) for e in self.model.symbols["states"]], "x": [(e, 0) for e in self.model.symbols["controls"]], "m": [(e, 0) for e in self.symbols["exogenous"]], "S": [(e, 0) for e in self.symbols["states"]], "X": [(e, 0) for e in self.symbols["aggregate"]], "m_1": [(e, 1) for e in self.symbols["exogenous"]], "S_1": [(e, 1) for e in self.symbols["states"]], "X_1": [(e, 1) for e in self.symbols["aggregate"]], "p": self.symbols["parameters"], } else: arguments_ = { "e": [(e, 0) for e in self.model.symbols["exogenous"]], "s": [(e, 0) for e in self.model.symbols["states"]], "x": [(e, 0) for e in self.model.symbols["controls"]], "m": [(e, 0) for e in self.symbols["exogenous"]], "X": [(e, 0) for e in self.symbols["aggregate"]], "m_1": [(e, 1) for e in self.symbols["exogenous"]], "X_1": [(e, 1) for e in self.symbols["aggregate"]], "p": self.symbols["parameters"], } vars = sum([[e[0] for e in h] for h in [*arguments_.values()][:-1]], []) arguments = { k: [dolang.symbolic.stringify_symbol(e) for e in v] for k, v in arguments_.items() } preamble = {} # for now from dolang.symbolic import sanitize, stringify eqs = parse_string(self.data["equilibrium"], start="equation_block") eqs = sanitize(eqs, variables=vars) eqs = stringify(eqs) content = {} for i, eq in enumerate(eqs.children): lhs, rhs = eq.children content[f"eq_{i}"] = "({1})-({0})".format( str_expression(lhs), str_expression(rhs)) fff = FlatFunctionFactory(preamble, content, arguments, "equilibrium") _, gufun = dolang.function_compiler.make_method_from_factory( fff, debug=self.debug) from dolang.vectorize import standard_function self.__equilibrium__ = standard_function(gufun, len(content)) return self.__equilibrium__
def projection(self): # , m: 'n_e', y: "n_y", p: "n_p"): # TODO: # behaves in a very misleading way if wrong number of argument is supplied # if no aggregate states, projection(m,x) (instead of projection(m,x,p)) returns zeros if self.__projection__ is None: if self.features["with-aggregate-states"]: arguments_ = { "m": [(e, 0) for e in self.symbols["exogenous"]], "S": [(e, 0) for e in self.symbols["states"]], "X": [(e, 0) for e in self.symbols["aggregate"]], "p": self.symbols["parameters"], } else: arguments_ = { "m": [(e, 0) for e in self.symbols["exogenous"]], "X": [(e, 0) for e in self.symbols["aggregate"]], "p": self.symbols["parameters"], } vars = sum([[e[0] for e in h] for h in [*arguments_.values()][:-1]], []) arguments = { k: [dolang.symbolic.stringify_symbol(e) for e in v] for k, v in arguments_.items() } preamble = {} # for now from dolang.symbolic import sanitize, stringify eqs = parse_string(self.data["projection"], start="assignment_block") eqs = sanitize(eqs, variables=vars) eqs = stringify(eqs) content = {} for eq in eqs.children: lhs, rhs = eq.children content[str_expression(lhs)] = str_expression(rhs) fff = FlatFunctionFactory(preamble, content, arguments, "equilibrium") _, gufun = dolang.function_compiler.make_method_from_factory( fff, debug=self.debug) from dolang.vectorize import standard_function self.__projection__ = standard_function(gufun, len(content)) return self.__projection__
def 𝒢(self): if (self.__transition__ is None) and self.features["with-aggregate-states"]: arguments_ = { "m_m1": [(e, -1) for e in self.symbols["exogenous"]], "S_m1": [(e, -1) for e in self.symbols["states"]], "X_m1": [(e, -1) for e in self.symbols["aggregate"]], "m": [(e, 0) for e in self.symbols["exogenous"]], "p": self.symbols["parameters"], } vars = sum([[e[0] for e in h] for h in [*arguments_.values()][:-1]], []) arguments = { k: [dolang.symbolic.stringify_symbol(e) for e in v] for k, v in arguments_.items() } preamble = {} # for now from dolang.symbolic import ( sanitize, parse_string, str_expression, stringify, ) eqs = parse_string(self.data["transition"], start="assignment_block") eqs = sanitize(eqs, variables=vars) eqs = stringify(eqs) content = {} for i, eq in enumerate(eqs.children): lhs, rhs = eq.children content[str_expression(lhs)] = str_expression(rhs) from dolang.factory import FlatFunctionFactory fff = FlatFunctionFactory(preamble, content, arguments, "transition") _, gufun = dolang.function_compiler.make_method_from_factory( fff, debug=self.debug) from dolang.vectorize import standard_function self.__transition__ = standard_function(gufun, len(content)) return self.__transition__
def projection(self): #, m: 'n_e', y: "n_y", p: "n_p"): if self.__projection__ is None: arguments_ = { # 'e': [(e,0) for e in self.model.symbols['exogenous']], # 's': [(e,0) for e in self.model.symbols['states']], # 'x': [(e,0) for e in self.model.symbols['controls']], 'm': [(e, 0) for e in self.symbols['exogenous']], 'y': [(e, 0) for e in self.symbols['aggregate']], 'p': self.symbols['parameters'] } vars = sum([[e[0] for e in h] for h in [*arguments_.values()][:-1]], []) arguments = { k: [dolang.symbolic.stringify_symbol(e) for e in v] for k, v in arguments_.items() } preamble = {} # for now projdefs = self.data.get('projection', {}) pkeys = [*projdefs.keys()] n_p = len(pkeys) equations = [ projdefs[v] for v in self.model.symbols['exogenous'][:n_p] ] equations = [ dolang.stringify(eq, variables=vars) for eq in equations ] content = {f'{pkeys[i]}_0': eq for i, eq in enumerate(equations)} fff = FlatFunctionFactory(preamble, content, arguments, 'equilibrium') fun = dolang.function_compiler.make_method_from_factory( fff, debug=self.debug) from dolang.vectorize import standard_function self.__projection__ = standard_function(fun[1], len(equations)) return self.__projection__
def ℰ(self): if self.__equilibrium__ is None: arguments_ = { 'e': [(e, 0) for e in self.model.symbols['exogenous']], 's': [(e, 0) for e in self.model.symbols['states']], 'x': [(e, 0) for e in self.model.symbols['controls']], 'm': [(e, 0) for e in self.symbols['exogenous']], 'y': [(e, 0) for e in self.symbols['aggregate']], 'p': self.symbols['parameters'] } vars = sum([[e[0] for e in h] for h in [*arguments_.values()][:-1]], []) arguments = { k: [dolang.symbolic.stringify_symbol(e) for e in v] for k, v in arguments_.items() } preamble = {} # for now equations = [ ("{}-({})".format(*(str(eq).split('='))) if '=' in eq else eq) for eq in self.data['equilibrium'] ] equations = [ dolang.stringify(eq, variables=vars) for eq in equations ] content = {f'eq_{i}': eq for i, eq in enumerate(equations)} fff = FlatFunctionFactory(preamble, content, arguments, 'equilibrium') fun = dolang.function_compiler.make_method_from_factory( fff, debug=self.debug) from dolang.vectorize import standard_function self.__equilibrium__ = standard_function(fun[1], len(equations)) return self.__equilibrium__
def test_compiler(): from dolang.factory import FlatFunctionFactory from dolang.codegen import to_source fff = FlatFunctionFactory( dict( # preamble x="b+c*p1", y="(a+b)*c"), dict(out_1="exp(y*p1)-a*p2", out_2="x+y"), dict(g1=['a', 'b'], g2=['c'], g3=['p1', 'p2']), 'testfun') from dolang.function_compiler import make_method_from_factory fun = make_method_from_factory(fff)[0] import numpy as np out = np.array([0.3, 0.1]) fun([0.1, 0.2], [10], [0.5, 0.3], out) print(abs(out[0] - 4.45168907) < 1e-8) print(abs(out[1] - 8.2) < 1e-8)
def test_compiler(): from dolang.factory import FlatFunctionFactory from dolang.codegen import to_source fff = FlatFunctionFactory( dict(x="b+c*p1", y="(a+b)*c"), # preamble dict(out_1="exp(y*p1)-a*p2", out_2="x+y"), dict(g1=["a", "b"], g2=["c"], g3=["p1", "p2"]), "testfun", ) from dolang.function_compiler import make_method_from_factory fun = make_method_from_factory(fff)[0] import numpy as np out = np.array([0.3, 0.1]) fun(np.array([0.1, 0.2]), np.array([10]), np.array([0.5, 0.3]), out) assert abs(out[0] - 4.45168907) < 1e-8 assert abs(out[1] - 8.2) < 1e-8
def get_factory(model, eq_type: str, tshift: int = 0): from dolo.compiler.model import decode_complementarity from dolo.compiler.recipes import recipes from dolang.symbolic import stringify, stringify_symbol equations = model.equations if eq_type == "auxiliary": eqs = [('{}({})'.format(s, 0)) for s in model.symbols['auxiliaries']] specs = { 'eqs': [['exogenous', 0, 'm'], ['states', 0, 's'], ['controls', 0, 'x'], ['parameters', 0, 'p']] } else: eqs = equations[eq_type] if eq_type in ('controls_lb', 'controls_ub'): specs = { 'eqs': recipes['dtcc']['specs']['arbitrage']['complementarities'][ 'left-right'] } else: specs = recipes['dtcc']['specs'][eq_type] specs = shift_spec(specs, tshift=tshift) preamble_tshift = set([s[1] for s in specs['eqs'] if s[0] == 'states']) preamble_tshift = preamble_tshift.intersection( set([s[1] for s in specs['eqs'] if s[0] == 'controls'])) args = [] for sg in specs['eqs']: if sg[0] == 'parameters': args.append([s for s in model.symbols["parameters"]]) else: args.append([(s, sg[1]) for s in model.symbols[sg[0]]]) args = [[stringify_symbol(e) for e in vg] for vg in args] arguments = dict(zip([sg[2] for sg in specs['eqs']], args)) # temp eqs = [eq.replace("==","=").replace("=","==") for eq in eqs] if 'target' in specs: sg = specs['target'] targets = [(s, sg[1]) for s in model.symbols[sg[0]]] eqs = [eq.split('==')[1] for eq in eqs] else: eqs = [("({1})-({0})".format(*eq.split('==')) if '==' in eq else eq) for eq in eqs] targets = [('out{}'.format(i), 0) for i in range(len(eqs))] eqs = [str.strip(eq) for eq in eqs] eqs = [dolang.parse_string(eq) for eq in eqs] es = ExpressionSanitizer(model.variables) eqs = [es.visit(eq) for eq in eqs] eqs = [time_shift(eq, tshift) for eq in eqs] eqs = [stringify(eq) for eq in eqs] eqs = [dolang.to_source(eq) for eq in eqs] targets = [stringify_symbol(e) for e in targets] # sanitize defs ( should be ) defs = dict() for k in model.definitions: if '(' not in k: s = "{}(0)".format(k) val = model.definitions[k] val = es.visit(dolang.parse_string(val)) for t in preamble_tshift: s = stringify_symbol((k, t)) vv = stringify(time_shift(val, t)) defs[s] = dolang.to_source(vv) preamble = reorder_preamble(defs) eqs = dict(zip(targets, eqs)) ff = FlatFunctionFactory(preamble, eqs, arguments, eq_type) return ff
equations_strings = [dolang.stringify(eq, variables) for eq in equations] args = dict([('y_f', [(e, 1) for e in endo_vars]), ('y', [(e, 0) for e in endo_vars]), ('y_p', [(e, -1) for e in endo_vars]), ('e', [(e, 0) for e in exo_vars]), ('p', [e for e in parameters])]) args = dict([(k, [stringify_symbol(e) for e in v]) for k, v in args.items()]) from dolang.symbolic import stringify_symbol from dolang.factory import FlatFunctionFactory eqs = dict([(f"equation_{i+1}", eq) for i, eq in enumerate(equations_strings)]) fff = FlatFunctionFactory(dict(), eqs, args, 'f_dynamic') from dolang.function_compiler import make_method_from_factory fun, gufun = make_method_from_factory(fff, vectorize=True, debug=True) calibration = dict() data['modfile']['statements'] calibration = dict() for s in data['modfile']['statements']: # parameters if s['statementName'] == 'param_init': n = s['name'] v = s['value'] calibration[n] = float(v)
def get_factory(model, eq_type: str, tshift: int = 0): from dolo.compiler.model import decode_complementarity from dolo.compiler.recipes import recipes from dolang.symbolic import stringify, stringify_symbol equations = model.equations if eq_type == "auxiliary": eqs = ["{}".format(s) for s in model.symbols["auxiliaries"]] specs = { "eqs": [ ["exogenous", 0, "m"], ["states", 0, "s"], ["controls", 0, "x"], ["parameters", 0, "p"], ] } else: eqs = equations[eq_type] if eq_type in ("arbitrage_lb", "arbitrage_ub"): specs = { "eqs": recipes["dtcc"]["specs"]["arbitrage"]["complementarities"] ["left-right"] } else: specs = recipes["dtcc"]["specs"][eq_type] specs = shift_spec(specs, tshift=tshift) preamble_tshift = set([s[1] for s in specs["eqs"] if s[0] == "states"]) preamble_tshift = preamble_tshift.intersection( set([s[1] for s in specs["eqs"] if s[0] == "controls"])) args = [] for sg in specs["eqs"]: if sg[0] == "parameters": args.append([s for s in model.symbols["parameters"]]) else: args.append([(s, sg[1]) for s in model.symbols[sg[0]]]) args = [[stringify_symbol(e) for e in vg] for vg in args] arguments = dict(zip([sg[2] for sg in specs["eqs"]], args)) # temp eqs = [eq.split("⟂")[0].strip() for eq in eqs] if "target" in specs: sg = specs["target"] targets = [(s, sg[1]) for s in model.symbols[sg[0]]] eqs = [eq.split("=")[1] for eq in eqs] else: eqs = [("({1})-({0})".format(*eq.split("=")) if "=" in eq else eq) for eq in eqs] targets = [("out{}".format(i), 0) for i in range(len(eqs))] eqs = [str.strip(eq) for eq in eqs] eqs = [dolang.parse_string(eq) for eq in eqs] es = Sanitizer(variables=model.variables) eqs = [es.transform(eq) for eq in eqs] eqs = [time_shift(eq, tshift) for eq in eqs] eqs = [stringify(eq) for eq in eqs] eqs = [str_expression(eq) for eq in eqs] targets = [stringify_symbol(e) for e in targets] # sanitize defs ( should be ) defs = dict() for k in model.definitions: val = model.definitions[k] # val = es.transform(dolang.parse_string(val)) for t in preamble_tshift: s = stringify(time_shift(k, t)) if isinstance(val, str): vv = stringify(time_shift(val, t)) else: vv = str(val) defs[s] = vv preamble = reorder_preamble(defs) eqs = dict(zip(targets, eqs)) ff = FlatFunctionFactory(preamble, eqs, arguments, eq_type) return ff