Example #1
0
def parse_dynare_text(txt, add_model=True, full_output=False, debug=False):
    '''
    Imports the content of a modfile into the current interpreter scope
    '''
    # here we call "instruction group", a string finishing by a semicolon
    # an "instruction group" can have several lines
    # a line can be
    # - a comment //...
    # - an old-style tag //$...
    # - a new-style tag [key1='value1',..]
    # - macro-instruction @#...
    # A Modfile contains several blocks (in this order) :
    # - an initblock defining variables, exovariables, parameters, initialization
    #   inside the initblock the order of declaration doesn't matter
    # - a model block with two special lines (model; end;)
    # - optional blocks (like endval, shocks)
    #    seperated by free matlab instructions in any order;
    # - all other instructions are ignored

    otxt = txt
    otxt = otxt.replace("\r\n", "\n")
    otxt = otxt.replace("^", "**")

    # first, we remove end-of-line comments : they are definitely lost
    regex = re.compile("(.+)//[^#](.*)")

    def remove_end_comment(line):
        res = regex.search(line)
        if res:
            l = res.groups(1)[0]
            return (l)
        else:
            return line

    txt = str.join("\n", map(remove_end_comment, otxt.split("\n")))

    name_regex = re.compile("//\s*fname\s*=\s*'(.*)'")
    m = name_regex.search(txt)
    if m:
        fname = m.group(1)
    else:
        fname = None

    instruction_groups = [Instruction_group(s) for s in txt.split(";")]

    instructions = [ig.instruction for ig in instruction_groups]

    if debug:
        print('Elementary instructions')
        for i in instruction_groups:
            print(i)

    try:
        imodel = [
            re.compile('model(\(.*\)|)').match(e) is not None
            for e in instructions
        ]
        imodel = imodel.index(True)
        #imodel = instructions.index("model") #this doesn't work for "MODEL"
        iend = instructions.index("end")
        model_block = instruction_groups[imodel:(iend + 1)]
        init_block = instruction_groups[0:imodel]
    except:
        raise Exception('Model block could not be found.')

    next_instructions = instructions[(iend + 1):]
    next_instruction_groups = instruction_groups[(iend + 1):]

    if 'initval' in next_instructions:
        iinitval = next_instructions.index('initval')
        iend = next_instructions.index('end', iinitval)
        matlab_block_1 = next_instruction_groups[0:iinitval]
        initval_block = next_instruction_groups[iinitval:(iend + 1)]
        next_instruction_groups = next_instruction_groups[(iend + 1):]
        next_instructions = next_instructions[(iend + 1):]
    else:
        initval_block = None
        matlab_block_1 = None

    if 'endval' in next_instructions:
        iendval = next_instructions.index('endval')
        iend = next_instructions.index('end', iendval)
        matlab_block_2 = next_instruction_groups[0:iendval]
        endval_block = next_instruction_groups[iendval:(iend + 1)]
        next_instruction_groups = next_instruction_groups[(iend + 1):]
        next_instructions = next_instructions[(iend + 1):]
    else:
        endval_block = None
        matlab_block_2 = None

    # TODO : currently shocks block needs to follow initval, this restriction should be removed
    if 'shocks' in next_instructions:
        ishocks = next_instructions.index('shocks')
        iend = next_instructions.index('end', ishocks)
        matlab_block_3 = next_instruction_groups[0:ishocks]
        shocks_block = next_instruction_groups[ishocks:(iend + 1)]
        next_instruction_groups = next_instruction_groups[(iend + 1):]
        next_instructions = next_instructions[(iend + 1):]
    else:
        shocks_block = None
        matlab_block_3 = None

    try:
        init_regex = re.compile("(parameters |var |varexo |)(.*)")
        var_names = []
        varexo_names = []
        parameters_names = []
        declarations = {}
        for ig in init_block:
            if ig.instruction != '':
                m = init_regex.match(ig.instruction)
                if not m:
                    raise Exception("Unexpected instruction in init block : " +
                                    str(ig.instruction))
                if m.group(1) == '':
                    [lhs, rhs] = m.group(2).split("=")
                    lhs = lhs.strip()
                    rhs = rhs.strip()
                    declarations[lhs] = rhs
                else:
                    arg = m.group(2).replace(",", " ")
                    names = [vn.strip() for vn in arg.split()]
                    if m.group(1).strip() == 'var':
                        dest = var_names
                    elif m.group(1).strip() == 'varexo':
                        dest = varexo_names
                    elif m.group(1).strip() == 'parameters':
                        dest = parameters_names
                    for n in names:
                        if not n in dest:
                            dest.append(n)
                        else:
                            raise Exception(
                                "symbol %s has already been defined".format(n))
    except Exception as e:
        raise Exception('Init block could not be read : ' + str(e))
    # the following instruction set the variables "variables","shocks","parameters"

    variables = []
    for vn in var_names:
        v = Variable(vn)
        variables.append(v)

    shocks = []
    for vn in varexo_names:
        s = Shock(vn)
        shocks.append(s)

    parameters = []
    for vn in parameters_names:
        p = Parameter(vn)
        parameters.append(p)

    parse_dict = dict()
    for v in variables + shocks + parameters:
        parse_dict[v.name] = v

    special_symbols = [
        sympy.exp, sympy.log, sympy.sin, sympy.cos, sympy.atan, sympy.tan
    ]
    for s in special_symbols:
        parse_dict[str(s)] = s
    parse_dict['sqrt'] = sympy.sqrt

    # Read parameters values
    parameters_values = {}
    for p in declarations:
        try:
            rhs = eval(declarations[p], parse_dict)
        except Exception as e:
            Exception("Impossible to evaluate parameter value : " + str(e))
        try:
            lhs = eval(p, parse_dict)
        except Exception as e:
            # here we could declare p
            raise e
        parameters_values[lhs] = rhs

    # Now we read the model block
    model_tags = model_block[0].tags
    equations = []
    for ig in model_block[1:-1]:
        if ig.instruction != '':
            teq = ig.instruction.replace('^', "**")
            if '=' in teq:
                teqlhs, teqrhs = teq.split("=")
            else:
                teqlhs = teq
                teqrhs = '0'
            eqlhs = eval(teqlhs, parse_dict)
            eqrhs = eval(teqrhs, parse_dict)
            eq = Equation(eqlhs, eqrhs)
            eq.tags.update(ig.tags)
            #        if eq.tags.has_key('name'):
            #            eq.tags[] = ig.tags['name']
            equations.append(eq)

    # Now we read the initval block
    init_values = {}
    if initval_block != None:
        for ig in initval_block[1:-1]:
            if len(ig.instruction.strip()) > 0:
                try:
                    [lhs, rhs] = ig.instruction.split("=")
                except Exception as e:
                    print(ig.instruction)
                    raise e
                init_values[eval(lhs, parse_dict)] = eval(rhs, parse_dict)

    # Now we read the endval block
    # I don't really care about the endval block !

    end_values = {}
    if endval_block != None:
        for ig in endval_block[1:-1]:
            [lhs, rhs] = ig.instruction.split("=")
            end_values[eval(lhs)] = eval(rhs)

    # Now we read the shocks block
    covariances = None
    if shocks_block != None:
        covariances = sympy.zeros(len(shocks))
        regex1 = re.compile("var (.*?),(.*?)=(.*)|var (.*?)=(.*)")
        for ig in shocks_block[1:-1]:
            m = regex1.match(ig.instruction)
            if not m:
                raise Exception("unrecognized instruction in block shocks : " +
                                str(ig.instruction))
            if m.group(1) != None:
                varname1 = m.group(1).strip()
                varname2 = m.group(2).strip()
                value = m.group(3).strip().replace("^", "**")
            elif m.group(4) != None:
                varname1 = m.group(4).strip()
                varname2 = varname1
                value = m.group(5).strip().replace("^", "**")
            i = varexo_names.index(varname1)
            j = varexo_names.index(varname2)
            covariances[i, j] = eval(value, parse_dict)
            covariances[j, i] = eval(value, parse_dict)

    calibration = {}
    calibration.update(parameters_values)
    calibration.update(init_values)
    symbols = {
        'variables': variables,
        'shocks': shocks,
        'parameters': parameters
    }

    from dolo.symbolic.model import SModel
    model = SModel({'dynare_block': equations}, symbols, calibration,
                   covariances)
    return model
Example #2
0
    def read_model(self):

        import re
        import sympy
        from dolo.symbolic.symbolic import map_function_to_expression
        from dolo.symbolic.symbolic import Variable

        if self.__transformed_model__:
            return self.__transformed_model__

        dmodel = SModel(**self.model) # copy the model
        dmodel.check_consistency(auto_remove_variables=False)

        def_eqs = [eq for eq in dmodel.equations if eq.tags['eq_type'] in ('def', 'auxiliary')]

        def timeshift(v,n):
            if isinstance(v,Variable):
                return v(n)
            else:
                return v

        # Build substitution dict
        def_dict = {}
        for eq in def_eqs:
            v = eq.lhs
            rhs = sympy.sympify(eq.rhs)
            def_dict[v] = rhs
            def_dict[v(1)] = map_function_to_expression(lambda x: timeshift(x,1), rhs)

        new_equations = []
        tbr = []
        for i,eq in enumerate(dmodel.equations) :
            if not ('def' == eq.tags['eq_type']):
                lhs = sympy.sympify( eq.lhs ).subs(def_dict)
                rhs = sympy.sympify( eq.rhs ).subs(def_dict)
                neq = Equation(lhs,rhs).tag(**eq.tags)
                new_equations.append(neq)

        dmodel['equations'] = new_equations
        dmodel.check_consistency()

        f_eqs = [eq for eq in dmodel.equations if eq.tags['eq_type'] in ('f','arbitrage','equilibrium')]
        g_eqs = [eq for eq in dmodel.equations if eq.tags['eq_type'] in ('g','transition')]
        h_eqs = [eq for eq in dmodel.equations if eq.tags['eq_type'] in ('h','expectation')]
        hm_eqs = [eq for eq in dmodel.equations if eq.tags['eq_type'] in ('h','expectation_mult')] # Need to understand the need for 'h'
        e_eqs = [eq for eq in dmodel.equations if eq.tags['eq_type'] in ('e','equation_error')]

        states_vars = [eq.lhs for eq in g_eqs]
        exp_vars =  [eq.lhs for eq in h_eqs]
        controls = set(dmodel.variables) - set(states_vars + exp_vars)
        controls = list(controls)

        states_vars = [v for v in dmodel.variables if v in states_vars]
        exp_vars = [v for v in dmodel.variables if v in exp_vars]
        controls = [v for v in dmodel.variables if v in controls]

        # Remove the left-hand side of equations
        f_eqs = [eq.gap for eq in f_eqs]
        g_eqs = [eq.rhs for eq in g_eqs]
        h_eqs = [eq.rhs for eq in h_eqs]
        hm_eqs = [eq.rhs for eq in hm_eqs]
        e_eqs = [eq.lhs for eq in e_eqs]

        g_eqs = [map_function_to_expression(lambda x: timeshift(x,1),eq) for eq in g_eqs]
        #h_eqs = [map_function_to_expression(lambda x: timeshift(x,-1),eq) for eq in h_eqs] #no

    #    sub_list[v] = v.name

        # Read complementarity conditions
        compcond = {}
        of_eqs = [eq for eq in dmodel.equations if eq.tags['eq_type'] in ('f','arbitrage','equilibrium')]
        locals = {}
        locals['inf'] = sympy.Symbol('inf')
        locals['log'] = sympy.log
        locals['exp'] = sympy.exp

        for v in dmodel.variables + dmodel.parameters:
            locals[v.name] = v
        compregex = re.compile('(.*)<=(.*)<=(.*)')
        for eq in of_eqs:
            tg = eq.tags['complementarity']
            [lhs,mhs,rhs] = compregex.match(tg).groups()
            [lhs,mhs,rhs] = [dmodel.eval_string(x) for x in [lhs,mhs,rhs]]
            compcond[mhs] = (lhs,rhs)

        complementarities = [compcond[v] for v in controls]

        inf_bounds = [c[0] for c in complementarities]
        sup_bounds = [c[1] for c in complementarities]

        data = {'f_eqs': f_eqs,
                'g_eqs': g_eqs,
                'h_eqs': h_eqs,
                'hm_eqs': hm_eqs,
                'e_eqs':e_eqs,
                'controls': controls,
                'states_vars': states_vars,
                'exp_vars': exp_vars,
                'inf_bounds': inf_bounds,
                'sup_bounds': sup_bounds}

        self.__transformed_model__ = data # cache computation

        return data
Example #3
0
def parse_yaml_text(txt, verbose=False, compiler=None):
    '''
Imports the content of a modfile into the current interpreter scope
'''
    txt = txt.replace('..', '-')
    txt = txt.replace('--', '-')
    txt = txt.replace('^', '**')
    txt = txt.replace('equilibrium:', 'arbitrage:')
    txt = txt.replace('_|_', '|')
    raw_dict = yaml.load(txt)

    if verbose == True:
        print('YAML file successfully parsed')

    declarations = raw_dict['declarations']
    # check
    variables_groups = OrderedDict()
    for vtype in declarations.keys():
        if vtype not in ('shocks', 'parameters'):
            variables_groups[vtype] = [
                Variable(vn) for vn in declarations[vtype]
            ]
    variables_ordering = sum(variables_groups.values(), [])
    #    else:
    #        vnames = declarations['variables']
    #        variables_ordering = [Variable(vn) for vn in vnames]
    #        variables_groups = None

    parameters_ordering = [Parameter(vn) for vn in declarations['parameters']]
    shocks_ordering = [Shock(vn) for vn in declarations['shocks']]

    context = [
        (s.name, s)
        for s in variables_ordering + parameters_ordering + shocks_ordering
    ]
    context = dict(context)

    from dolo.symbolic.symbolic import timeshift as TS

    # add some common functions
    for f in [
            sympy.log, sympy.exp, sympy.sin, sympy.cos, sympy.tan, sympy.asin,
            sympy.acos, sympy.atan, sympy.sinh, sympy.cosh, sympy.tanh,
            sympy.pi, sympy.sign
    ]:
        context[str(f)] = f
    context['sqrt'] = sympy.sqrt

    context['TS'] = TS
    if 'horrible_hack' in raw_dict:
        tt = raw_dict['horrible_hack']
        exec(tt, context)

    import re
    # we recognize two kinds of equations:
    # lhs = rhs
    # lhs | comp where comp is a complementarity condition

    equations = []
    equations_groups = OrderedDict()
    raw_equations = raw_dict['equations']
    if not isinstance(raw_equations, dict):
        raw_dict['model_type'] = 'dynare'
        raw_equations = {'dynare_block': raw_equations}
    if True:  # tests whether there are groups of equations
        for groupname in raw_equations.keys():
            equations_groups[groupname] = []
            for raw_eq in raw_equations[
                    groupname]:  # Modfile is supposed to represent a global model. TODO: change it
                teqg = raw_eq.split('|')
                teq = teqg[0]
                if '=' in teq:
                    lhs, rhs = str.split(teq, '=')
                else:
                    lhs = teq
                    rhs = '0'
                try:
                    lhs = eval(lhs, context)
                    rhs = eval(rhs, context)
                except Exception as e:
                    print('Error parsing equation : ' + teq)
                    print(str(e))
                    raise e

                eq = Equation(lhs, rhs)
                eq.tag(eq_type=groupname)
                if len(teqg) > 1:
                    comp = teqg[1]
                    eq.tag(complementarity=comp)
                equations.append(eq)
                equations_groups[groupname].append(eq)
    else:
        for teq in raw_equations:
            if '=' in teq:
                lhs, rhs = str.split(teq, '=')
            else:
                lhs = teq
                rhs = '0'
            try:
                lhs = eval(lhs, context)
                rhs = eval(rhs, context)
            except Exception as e:
                print('Error parsing equations : ' + teq)
                print(str(e))
            eq = Equation(lhs, rhs)
            equations.append(eq)
        equations_groups = None

    parameters_values = {}
    init_values = {}
    covariances = None
    if 'calibration' in raw_dict:
        calibration = raw_dict['calibration']
        if 'parameters' in calibration:
            parameters_values = [
                (Parameter(k), eval(str(v), context))
                for k, v in iteritems(calibration['parameters'])
            ]
            parameters_values = dict(parameters_values)
        #steady_state = raw_dict['steady_state']
        if 'steady_state' in calibration:
            init_values = [
                (Variable(vn), eval(str(value), context))
                for vn, value in iteritems(calibration['steady_state'])
            ]
            init_values = dict(init_values)
        if 'covariances' in calibration:
            context['sympy'] = sympy
            covariances = eval(
                'sympy.Matrix({0})'.format(calibration['covariances']),
                context)
        else:
            covariances = None  # to avoid importing numpy

    symbols = variables_groups

    symbols['shocks'] = shocks_ordering
    symbols['parameters'] = parameters_ordering

    calibration_s = {}
    calibration_s.update(parameters_values)
    calibration_s.update(init_values)

    from dolo.symbolic.model import SModel

    model = SModel(equations_groups, symbols, calibration_s, covariances)
    model.__data__ = raw_dict

    return model
Example #4
0
def parse_yaml_text(txt,verbose=False, compiler=None):
    '''
Imports the content of a modfile into the current interpreter scope
'''
    txt = txt.replace('..','-')
    txt = txt.replace('--','-')
    txt = txt.replace('^','**')
    txt = txt.replace('equilibrium:','arbitrage:')
    txt = txt.replace('_|_','|')
    raw_dict = yaml.load(txt)

    if verbose == True:
        print('YAML file successfully parsed')

    declarations = raw_dict['declarations']
    # check
    variables_groups = OrderedDict()
    for vtype in declarations.keys():
        if vtype not in ('shocks','parameters'):
            variables_groups[vtype] = [Variable(vn) for vn in declarations[vtype]]
    variables_ordering = sum(variables_groups.values(),[])
#    else:
#        vnames = declarations['variables']
#        variables_ordering = [Variable(vn) for vn in vnames]
#        variables_groups = None

    parameters_ordering = [Parameter(vn) for vn in declarations['parameters']]
    shocks_ordering = [Shock(vn) for vn in declarations['shocks']]

    context = [(s.name,s) for s in variables_ordering + parameters_ordering + shocks_ordering]
    context = dict(context)

    from dolo.symbolic.symbolic import timeshift as TS


    # add some common functions
    for f in [sympy.log, sympy.exp,
              sympy.sin, sympy.cos, sympy.tan,
              sympy.asin, sympy.acos, sympy.atan,
              sympy.sinh, sympy.cosh, sympy.tanh,
              sympy.pi, sympy.sign]:
        context[str(f)] = f
    context['sqrt'] = sympy.sqrt

    context['TS'] = TS
    if 'horrible_hack' in raw_dict:
        tt = raw_dict['horrible_hack']
        exec(tt, context)


    import re
    # we recognize two kinds of equations:
    # lhs = rhs
    # lhs | comp where comp is a complementarity condition

    equations = []
    equations_groups = OrderedDict()
    raw_equations = raw_dict['equations']
    if not isinstance(raw_equations,dict):
        raw_dict['model_type'] = 'dynare'
        raw_equations = {'dynare_block': raw_equations}
    if True: # tests whether there are groups of equations
        for groupname in raw_equations.keys():
            equations_groups[groupname] = []
            for raw_eq in raw_equations[groupname]: # Modfile is supposed to represent a global model. TODO: change it
                teqg = raw_eq.split('|')
                teq = teqg[0]
                if '=' in teq:
                    lhs,rhs = str.split(teq,'=')
                else:
                    lhs = teq
                    rhs = '0'
                try:
                    lhs = eval(lhs,context)
                    rhs = eval(rhs,context)
                except Exception as e:
                    print('Error parsing equation : ' + teq)
                    print( str(e) )
                    raise e

                eq = Equation(lhs,rhs)
                eq.tag(eq_type=groupname)
                if len(teqg)>1:
                    comp = teqg[1]
                    eq.tag(complementarity=comp)
                equations.append(eq)
                equations_groups[groupname].append( eq )
    else:
        for teq in raw_equations:
            if '=' in teq:
                lhs,rhs = str.split(teq,'=')
            else:
                lhs = teq
                rhs = '0'
            try:
                lhs = eval(lhs,context)
                rhs = eval(rhs,context)
            except Exception as e:
                print('Error parsing equations : ' + teq)
                print(str(e))
            eq = Equation(lhs,rhs)
            equations.append(eq)
        equations_groups = None

    parameters_values = {}
    init_values = {}
    covariances = None
    if 'calibration' in raw_dict:
        calibration = raw_dict['calibration']
        if 'parameters' in calibration:
            parameters_values = [ (Parameter(k), eval(str(v),context)) for k,v in iteritems(calibration['parameters']) ]
            parameters_values = dict(parameters_values)
        #steady_state = raw_dict['steady_state']
        if 'steady_state' in calibration:
            init_values = [ (Variable(vn), eval(str(value),context)) for vn,value in iteritems(calibration['steady_state']) ]
            init_values = dict(init_values)
        if 'covariances' in calibration:
            context['sympy'] = sympy
            covariances = eval('sympy.Matrix({0})'.format( calibration['covariances'] ), context)
        else:
            covariances = None # to avoid importing numpy

    symbols = variables_groups

    symbols['shocks'] = shocks_ordering
    symbols['parameters'] = parameters_ordering

    calibration_s = {}
    calibration_s.update(parameters_values)
    calibration_s.update(init_values)

    from dolo.symbolic.model import SModel

    model = SModel( equations_groups, symbols, calibration_s, covariances )
    model.__data__ = raw_dict



    return model
Example #5
0
    def read_model(self):

        if self.__transformed_model__:
            return self.__transformed_model__


        dmodel = SModel(**self.model) # copy the model
        dmodel.check_consistency(auto_remove_variables=False)

        def_eqs = [eq for eq in dmodel.equations if eq.tags['eq_type'] in ('def', 'auxiliary')]

        from dolo.symbolic.symbolic import map_function_to_expression
        from dolo.symbolic.symbolic import Variable
        def timeshift(v,n):
            if isinstance(v,Variable):
                return v(n)
            else:
                return v

        import sympy

        #### build substitution dict
        def_dict = {}
        for eq in def_eqs:
            v = eq.lhs
            rhs = sympy.sympify( eq.rhs )
            def_dict[v] = rhs
            def_dict[v(1)] = map_function_to_expression( lambda x: timeshift(x,1), rhs)

        new_equations = []
        tbr = []
        for i,eq in enumerate(dmodel.equations) :
            if not ('def' == eq.tags['eq_type']):
                lhs = sympy.sympify( eq.lhs ).subs(def_dict)
                rhs = sympy.sympify( eq.rhs ).subs(def_dict)
                neq = Equation(lhs,rhs).tag(**eq.tags)
                new_equations.append( neq )

        dmodel['equations'] = new_equations
        dmodel.check_consistency()



        f_eqs = [eq for eq in dmodel.equations if eq.tags['eq_type'] in ('f','arbitrage')]
        g_eqs = [eq for eq in dmodel.equations if eq.tags['eq_type'] in ('g','transition')]
        h_eqs = [eq for eq in dmodel.equations if eq.tags['eq_type'] in ('h','expectation')]



        states_vars = [eq.lhs for eq in g_eqs]
        exp_vars =  [eq.lhs for eq in h_eqs]
        controls = set(dmodel.variables) - set(states_vars + exp_vars)
        controls = list(controls)

        states_vars = [v for v in dmodel.variables if v in states_vars]
        exp_vars = [v for v in dmodel.variables if v in exp_vars]
        controls = [v for v in dmodel.variables if v in controls]


        # now we remove the left side of equations
        f_eqs = [eq.gap for eq in f_eqs]
        g_eqs = [eq.rhs for eq in g_eqs]
        h_eqs = [eq.rhs for eq in h_eqs]

        g_eqs = [map_function_to_expression(lambda x: timeshift(x,1),eq) for eq in g_eqs]
        #h_eqs = [map_function_to_expression(lambda x: timeshift(x,-1),eq) for eq in h_eqs] #no


    #    sub_list[v] = v.name

        # read complementarity conditions
        compcond = {}
        of_eqs = [eq for eq in dmodel.equations if eq.tags['eq_type'] in ('f','arbitrage')]
        locals = {}
        import sympy
        locals['inf'] = sympy.Symbol('inf')
        locals['log'] = sympy.log # this should be more generic
        locals['exp'] = sympy.exp

        for v in dmodel.variables + dmodel.parameters:
            locals[v.name] = v
        import re
        compregex = re.compile('(.*)<=(.*)<=(.*)')
        for eq in of_eqs:
            tg = eq.tags['complementarity']
            [lhs,mhs,rhs] = compregex.match(tg).groups()
            [lhs,mhs,rhs] = [dmodel.eval_string(x) for x in [lhs,mhs,rhs] ]
            compcond[mhs] = (lhs,rhs)

        complementarities = [compcond[v] for v in controls]

        inf_bounds = [c[0] for c in complementarities]
        sup_bounds = [c[1] for c in complementarities]

        data = {
            'f_eqs': f_eqs,
            'g_eqs': g_eqs,
            'h_eqs': h_eqs,
            'controls': controls,
            'states_vars': states_vars,
            'exp_vars': exp_vars,
            'inf_bounds': inf_bounds,
            'sup_bounds': sup_bounds
        }

        self.__transformed_model__ = data # cache computation

        return data