Ejemplo n.º 1
0
    def equations(self):
        vars = self.variables + [*self.definitions.keys()]
        d = dict()
        for g, v in self.data['equations'].items():
            ll = []
            for eq in v:
                if "|" in eq:
                    eq = eq.split("|")[0]
                ll.append(sanitize(eq, variables=vars))
            d[g] = ll

        if "controls_lb" not in d:
            for ind, g in enumerate(("controls_lb", "controls_ub")):
                eqs = []
                for i, eq in enumerate(self.data['equations']['arbitrage']):
                    if "|" not in eq:
                        if ind == 0:
                            eq = "-inf"
                        else:
                            eq = "inf"
                    else:
                        comp = eq.split("|")[1]
                        v = self.symbols["controls"][i]
                        eq = decode_complementarity(comp, v)[ind]
                    eqs.append(eq)
                d[g] = eqs
        return d
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    def equations(self):
        vars = self.variables + [*self.definitions.keys()]
        d = dict()
        for g, v in self.data['equations'].items():
            ll = []
            for eq in v:
                if "|" in eq:
                    eq = eq.split("|")[0]
                ll.append(sanitize(eq, variables=vars))
            d[g] = ll

        if "controls_lb" not in d:
            for ind, g in enumerate(("controls_lb", "controls_ub")):
                eqs = []
                for i, eq in enumerate(self.data['equations']['arbitrage']):
                    if "|" not in eq:
                        if ind == 0:
                            eq = "-inf"
                        else:
                            eq = "inf"
                    else:
                        comp = eq.split("|")[1]
                        v = self.symbols["controls"][i]
                        eq = decode_complementarity(comp, v)[ind]
                    eqs.append(eq)
                d[g] = eqs
        return d
Ejemplo n.º 4
0
    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 test_sanitize():

    from dolang.symbolic import sanitize, parse_string
    from dolang.codegen import to_source

    s = 'sin(a(1)+b+a+f(-1)+f(+4)+a(1))'
    expected = "sin(a(1) + b + a(0) + f(-(1)) + f(4) + a(1))"
    e = parse_string('sin(a(1)+b+a+f(-1)+f(+4)+a(1))')
    enes = sanitize(e, variables=['a', 'f'])

    assert (to_source(enes) == expected)

    # it also works with the string directly
    assert (sanitize(s, variables=['a', 'f']) == expected)

    # we also deal with = signs, and convert to python exponents
    assert (sanitize("a(1) = a^3 + b") == "a(1) == (a) ** (3) + b")
Ejemplo n.º 6
0
    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__
Ejemplo n.º 7
0
    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__
Ejemplo n.º 8
0
    def equations(self):
        import yaml.nodes

        if self.__equations__ is None:

            vars = self.variables + [*self.definitions.keys()]

            d = dict()
            for g, v in self.data["equations"].items():

                # new style
                if isinstance(v, yaml.nodes.ScalarNode):
                    assert v.style == "|"
                    if g in ("arbitrage", ):
                        start = "complementarity_block"
                    else:
                        start = "assignment_block"
                    eqs = parse_string(v, start=start)
                    eqs = sanitize(eqs, variables=vars)
                    eq_list = eqs.children
                # old style
                else:
                    eq_list = []
                    for eq_string in v:
                        start = "equation"  # it should be assignment
                        eq = parse_string(eq_string, start=start)
                        eq = sanitize(eq, variables=vars)
                        eq_list.append(eq)

                if g in ("arbitrage", ):
                    ll = []  # List[str]
                    ll_lb = []  # List[str]
                    ll_ub = []  # List[str]
                    with_complementarity = False
                    for i, eq in enumerate(eq_list):
                        if eq.data == "double_complementarity":
                            v = eq.children[1].children[1].children[
                                0].children[0].value
                            t = int(eq.children[1].children[1].children[1].
                                    children[0].value)
                            expected = (
                                self.symbols["controls"][i],
                                0,
                            )  # TODO raise nice error message
                            if (v, t) != expected:
                                raise Exception(
                                    f"Incorrect variable in complementarity: expected {expected}. Found {(v,t)}"
                                )
                            ll_lb.append(
                                str_expression(eq.children[1].children[0]))
                            ll_ub.append(
                                str_expression(eq.children[1].children[2]))
                            eq = eq.children[0]
                            with_complementarity = True
                        else:
                            ll_lb.append("-inf")
                            ll_ub.append("inf")
                        from dolang.symbolic import list_symbols

                        # syms = list_symbols(eq)
                        ll.append(str_expression(eq))
                    d[g] = ll
                    if with_complementarity:
                        d[g + "_lb"] = ll_lb
                        d[g + "_ub"] = ll_ub
                else:
                    # TODO: we should check here that equations are well specified
                    d[g] = [str_expression(e) for e in eq_list]

            # if "controls_lb" not in d:
            #     for ind, g in enumerate(("controls_lb", "controls_ub")):
            #         eqs = []
            #         for i, eq in enumerate(d['arbitrage']):
            #             if "⟂" not in eq:
            #                 if ind == 0:
            #                     eq = "-inf"
            #                 else:
            #                     eq = "inf"
            #             else:
            #                 comp = eq.split("⟂")[1].strip()
            #                 v = self.symbols["controls"][i]
            #                 eq = decode_complementarity(comp, v+"[t]")[ind]
            #             eqs.append(eq)
            #         d[g] = eqs

            self.__equations__ = d

        return self.__equations__
Ejemplo n.º 9
0
    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__