def dyn_tabify_expression(self, eq, for_matlab=False, for_c=True):
     #from dolo.misc.calculus import map_function_to_expression
     # works when all variables are expressed without lag
     subs_dict = self.dynamic_substitution_list
     res = DicPrinter(subs_dict).doprint(eq)
     #        def f(expr):
     #            if expr.__class__ in [Variable,Parameter]:
     #                    vname = subs_dict[expr]
     #                    return(Symbol(vname))
     #            else:
     #                return(expr)
     #        res = map_function_to_expression(f,eq)
     return res
    def compute_dynamic_pfile(self, max_order=1, compact_order=True, with_parameters=False):

        if with_parameters:
            DerivativesTree.symbol_type = sympy.Symbol
        else:
            DerivativesTree.symbol_type = TSymbol

        model = self.model

        if compact_order:
            var_order = model.dyn_var_order + model.shocks
        else:
            var_order = [v(1) for v in model.variables]
            var_order += model.variables
            var_order += [v(-1) for v in model.variables]
            var_order += model.shocks
        if with_parameters:
            var_order += model.parameters

        # TODO create a log system

        sols = []
        i = 0
        for eq in model.equations:
            i += 1
            ndt = DerivativesTree(eq.gap)
            ndt.compute_nth_order_children(max_order)
            sols.append(ndt)

        self.dynamic_derivatives = sols

        dyn_subs_dict = self.dynamic_substitution_list(brackets=True, compact=compact_order)
        dyn_printer = DicPrinter(dyn_subs_dict)

        txt = """def dynamic_gaps(y, x, params):
#
# Status : Computes dynamic model for Dynare
#
# Warning : this file is generated automatically by Dynare
#           from model file (.mod)

#
# Model equations
#
    it_ = 0

    import numpy as np
    from numpy import exp, log
    from numpy import arctan as atan

    g = []

    residual = np.zeros({neq});
"""
        gs = str.join(", ", [("g" + str(i)) for i in range(1, (max_order + 1))])
        txt = txt.format(gs=gs, fname=model.fname, neq=len(model.equations))

        for i in range(len(sols)):
            ndt = sols[i]
            eq = ndt.expr
            rhs = dyn_printer.doprint_matlab(eq)
            txt += "    residual[{0}] = {1};\n".format(i, rhs)

        txt += "    g.append(residual)\n"

        for current_order in range(1, (max_order + 1)):
            if current_order == 1:
                matrix_name = "Jacobian"
            elif current_order == 2:
                matrix_name = "Hessian"
            else:
                matrix_name = "{0}_th order".format(current_order)

            txt += """
#
# {matrix_name} matrix
#

""".format(
                orderr=current_order + 1, matrix_name=matrix_name
            )
            if current_order == 2:
                txt.format(matrix_name="Hessian")
            elif current_order == 1:
                txt.format(matrix_name="Jacobian")

            # nnzd = self.NNZDerivatives(current_order)

            n_cols = (len(var_order),) * current_order
            n_cols = ",".join([str(s) for s in n_cols])
            txt += "    g{order} = np.zeros( ({n_eq}, {n_cols}) );\n".format(
                order=current_order, n_eq=len(model.equations), n_cols=n_cols
            )
            for n in range(len(sols)):
                ndt = sols[n]
                l = ndt.list_nth_order_children(current_order)
                for nd in l:
                    # here we compute indices where we write the derivatives
                    indices = nd.compute_index_set(var_order)
                    rhs = dyn_printer.doprint_numpy(nd.expr)
                    i0 = indices[0]
                    i_col_s = ",".join([str(nn) for nn in i0])
                    indices.remove(i0)

                    i_col_s_ref = i_col_s
                    txt += "    g{order}[{i_eq},{i_col}] = {value}\n".format(
                        order=current_order, i_eq=n, i_col=i_col_s, value=rhs
                    )
                    for ind in indices:
                        i += 1
                        i_col_s = ",".join([str(nn) for nn in ind])
                        txt += "    g{order}[{i_eq},{i_col}] = g{order}[{i_eq},{i_col_ref}] \n".format(
                            order=current_order, i_eq=n, i_col=i_col_s, i_col_ref=i_col_s_ref
                        )

            txt += "    g.append(g{order})\n".format(order=current_order)
        txt += "    return g\n"
        txt = txt.replace("^", "**")

        fun = code_to_function(txt, "dynamic_gaps")
        return fun
def compile_multiargument_function(equations, args_list, args_names, parms, diff=False, fname='anonymous_function', default=None):
    """
    :param equations: list of sympy expressions
    :param args_list: list of lists of symbols (e.g. [[a_1,a_2], [b_1,b_2]])
    :param args_names: list of strings (['a','b']
    :param parms: list of symbols to be used as parameters
    :param fname: name of the function to be generated
    :param diff: include symbolic derivatives in generated function
    :param vectorize: arguments are vectorized (not parameters)
    :param return_function: the source of a Matlab function f(a,b,p) where p is a vector of parameters and a, b, arrays
    :return:
    """

    template = '{0}(:,{1})'

    sub_list = {}

    for i,args in enumerate(args_list):
        vec_name = args_names[i]
        for j,v in enumerate(args):
            sub_list[v] = template.format(vec_name,j+1)

    for i,p in enumerate(parms):
        sub_list[p] = '{0}({1})'.format('p',i+1)

    import sympy
    sub_list[sympy.Symbol('inf')] = 'inf'


    text = '''
function [{return_names}] = {fname}({args_names}, {param_names}, output)

    if nargin <= {nargs}
        output = zeros({nargs},1);
        for i = 1:nargout
            output(i) = 1;
        end
    end

    n = size({var},1);

{content}
end
'''

    from dolo.compiler.common import DicPrinter

    dp = DicPrinter(sub_list)

    def write_eqs(eq_l, outname='val', default=None):
        '''Format equations'''
        if default:
                eq_block = '    {0} = ' + default + '( n , {1} );\n'
                eq_block = eq_block.format(outname, len(eq_l))
        else:
                eq_block = '    {0} = zeros( n, {1} );\n'.format(outname, len(eq_l))
        for i,eq in enumerate(eq_l):
            eq_txt = dp.doprint_matlab(eq, vectorize=True)
            if eq_txt != default:
                    eq_block += '    {0}(:,{1}) = {2};\n'.format(outname, i+1, eq_txt)
        return eq_block

    def write_der_eqs(eq_l,v_l,lhs):
        '''Format Jacobians'''
        eq_block = '        {lhs} = zeros( n,{0},{1} );\n'.format(len(eq_l),len(v_l),lhs=lhs)
        eq_l_d = eqdiff(eq_l,v_l)
        for i,eqq in enumerate(eq_l_d):
            for j,eq in enumerate(eqq):
                s = dp.doprint_matlab( eq, vectorize=True )
                if s != "0":
                    eq_block += '        {lhs}(:,{0},{1}) = {2};\n'.format(i+1,j+1,s,lhs=lhs)
        return eq_block

    content = write_eqs(eq_l=equations, default=default)

    content += '''
    if nargout <= 1
        return
    end
'''

    if diff:
        for i,a_g in enumerate(args_list):
            content += "\n    % Derivatives w.r.t: {0}\n\n".format(args_names[i])
            lhs = 'val_' + args_names[i]
            content += '    if output({})\n'.format(i+2)
            content += write_der_eqs(equations, a_g, lhs)
            content += '    else\n'
            content += '        val_{} = [];\n'.format(args_names[i])
            content += '    end;\n'

    return_names = str.join(', ', ['val'] + [ 'val_'+ str(a) for a in args_names] ) if diff else 'val'
    text = text.format(
            fname = fname,
            nargs = len(args_names)+1,
            var = args_names[0],
            content = content,
            return_names = return_names,
            args_names = str.join(', ', args_names),
            param_names = 'p'
            )

#    text = text.replace('+','.+')
#    text = text.replace('-','.-')


    return text
def compile_function(equations, args, parms, max_order, return_text=False):

    """
    :param equations:
    :param args:
    :param parms:
    :param max_order:
    :param return_function:
    :return:
    """

    var_order = args

    sols = []
    for eq in equations:
        ndt = DerivativesTree(eq, ref_var_list=var_order)
        ndt.compute_nth_order_children(max_order)
        sols.append(ndt)

    dyn_subs_dict = dict()
    for i,v in enumerate(args):
        dyn_subs_dict[v] = 'x_' + str(i)

    for i,p in enumerate(parms):
        dyn_subs_dict[p] = 'p_' + str(i)

    preamble_l = ['    x_{i} = x[{i}]   # {v}'.format(i=i,v=v) for i,v in enumerate(args)]
    preamble_l += ['    p_{i} = p[{i}]    # {p}'.format(i=i,p=p) for i,p in enumerate(parms)]
    preamble = str.join('\n',preamble_l)

    dyn_printer = DicPrinter(dyn_subs_dict)

    txt = """def dynamic_function(x, p):
#
#
#
    import numpy as np
    from numpy import exp, log
    from numpy import sin, cos, tan
    from numpy import arcsin as asin
    from numpy import arccos as acos
    from numpy import arctan as atan
    from numpy import sinh, cosh, tanh
    from numpy import pi

{preamble}

    f = []

    residual = np.zeros({neq},dtype=np.float64);
"""
    gs = str.join(', ',[('f'+str(i)) for i in range(1,(max_order+1))])
    txt = txt.format(gs=gs,fname='noname',neq=len(equations), preamble=preamble)

    for i in range(len(sols)):
        ndt = sols[i]
        eq = ndt.expr
        rhs = dyn_printer.doprint_numpy(eq)
        txt += '    residual[{0}] = {1}\n'.format(i,rhs )

    txt += '    f.append(residual)\n'

    for current_order in range(1,(max_order+1)):
        if current_order == 1:
            matrix_name = "Jacobian"
        elif current_order == 2:
            matrix_name = "Hessian"
        else:
            matrix_name = "{0}_th order".format(current_order)

        txt += """
#
# {matrix_name} matrix
#

""".format(orderr=current_order+1,matrix_name=matrix_name)
        if current_order == 2:
            txt.format(matrix_name="Hessian")
        elif current_order == 1:
            txt.format(matrix_name="Jacobian")

        #nnzd = self.NNZDerivatives(current_order)

        n_cols = (len(var_order),)*current_order
        n_cols = ','.join( [str(s) for s in n_cols] )
        txt += "    f{order} = np.zeros( ({n_eq}, {n_cols}), dtype=np.float64 )\n".format(order=current_order,n_eq=len(equations), n_cols=n_cols )
        for n in range(len(sols)):
            ndt = sols[n]
            l = ndt.list_nth_order_children(current_order)
            for nd in l:
                 # here we compute indices where we write the derivatives
                indices = nd.compute_index_set(var_order)
                rhs = dyn_printer.doprint_numpy(nd.expr)
                i0 = indices[0]
                i_col_s = ','.join([str(nn) for nn in i0])
                indices.remove(i0)

                i_col_s_ref = i_col_s
                txt += '    f{order}[{i_eq},{i_col}] = {value}\n'.format(order=current_order,i_eq=n,i_col=i_col_s,value=rhs)
                for ind in indices:
                    i += 1
                    i_col_s = ','.join([str(nn) for nn in ind])
                    txt += '    f{order}[{i_eq},{i_col}] = f{order}[{i_eq},{i_col_ref}] \n'.format(order=current_order,i_eq = n,i_col=i_col_s,i_col_ref = i_col_s_ref)

        txt += "    f.append(f{order})\n".format(order=current_order)
    txt += "    return f\n"
    txt = txt.replace('^','**')

    if return_text:
        return txt
    else:
        return code_to_function(txt,'dynamic_function')
Beispiel #5
0
def compile_theano_source(values,
                          args_list,
                          args_names,
                          parms,
                          fname='anonymous_function'):
    """
    :param vars: parameters
    :param values: list of values (already triangular)


    """

    vars = ['_res_{}'.format(i) for i in range(len(values))]

    sub_dict = {}
    for e in vars:
        try:
            sn = e.safe_name()
        except Exception:
            sn = '_' + str(e)
        sub_dict[e] = sn

    from dolo.compiler.common import DicPrinter

    dec = ''

    for s in args_names:
        dec += "{} = T.matrix('{}')\n".format(s, s)

    dec += "p = T.vector('p')\n"

    for i, p in enumerate(parms):
        sn = '_' + str(p)
        sub_dict[p] = sn
        dec += '{} = p[{}]\n'.format(sn, i)

    for i, l in enumerate(args_list):
        name = args_names[i]
        for j, e in enumerate(l):
            try:
                sn = e.safe_name()
            except Exception:
                sn = '_' + str(e)
            sub_dict[e] = sn
            dec += '{} = {}[{},:]\n'.format(sn, name, j)

    dp = DicPrinter(sub_dict)
    strings = []
    for i, eq in enumerate(values):
        rhs = (dp.doprint(eq))
        lhs = vars[i]
        #        strings.append( '{} = OO + {}'.format(lhs,rhs))
        strings.append('{} = {}'.format(lhs, rhs))

    source = """

from theano import tensor as T
from theano import function
from theano.tensor import exp

{declarations}

#    OO =  T.zeros((1,s.shape[1]))

{computations}

res = T.stack({vars})

f = function([{args}], res, mode='FAST_RUN',name="{fname}"{on_unused_input})

"""

    #    print(args_names)
    source = source.format(computations=str.join('\n', strings),
                           declarations=dec,
                           vars=str.join(', ', [str(v) for v in vars]),
                           args=str.join(', ',
                                         [str(v) for v in args_names] + ['p']),
                           fname=fname,
                           on_unused_input=",on_unused_input='ignore'"
                           if not theano_less_than_6 else "")

    return source
Beispiel #6
0
    def process_output_recs(self):
        '''Main function that formats the model in recs format'''
        import sympy
        from dolo.compiler.common import DicPrinter
        from dolo.misc.matlab import value_to_mat

        data = self.read_model()
        dmodel = self.model
        model = dmodel

        f_eqs = data['f_eqs']
        g_eqs = data['g_eqs']
        h_eqs = data['h_eqs']
        hm_eqs = data['hm_eqs']
        e_eqs = data['e_eqs']
        states_vars = data['states_vars']
        controls = data['controls']
        exp_vars = data['exp_vars']
        inf_bounds = data['inf_bounds']
        sup_bounds = data['sup_bounds']

        controls_f = [v(1) for v in controls]
        states_f = [v(1) for v in states_vars]

        sub_list = dict()
        for i, v in enumerate(exp_vars):
            sub_list[v] = 'z(:,{0})'.format(i + 1)

        for i, v in enumerate(controls):
            sub_list[v] = 'x(:,{0})'.format(i + 1)
            sub_list[v(1)] = 'xnext(:,{0})'.format(i + 1)

        for i, v in enumerate(states_vars):
            sub_list[v] = 's(:,{0})'.format(i + 1)
            sub_list[v(1)] = 'snext(:,{0})'.format(i + 1)

        for i, v in enumerate(dmodel.shocks):
            sub_list[v] = 'e(:,{0})'.format(i + 1)

        for i, v in enumerate(dmodel.parameters):
            sub_list[v] = 'p({0})'.format(i + 1)

        sub_list[sympy.Symbol('inf')] = 'inf'

        # Case h(s,x,e,sn,xn)
        text = '''function [out1,out2,out3,out4,out5] = {filename}(flag,s,x,z,e,snext,xnext,p,output)

voidcell                   = cell(1,5);
[out1,out2,out3,out4,out5] = voidcell{{:}};

switch flag

  case 'b'
    n = size(s,1);
{eq_bounds_block}

  case 'f'
    n = size(s,1);
{eq_fun_block}

  case 'g'
    n = size(s,1);
{state_trans_block}

  case 'h'
    n = size(snext,1);
{exp_fun_block}

  case 'e'
    n = size(s,1);
{equation_error_block}

  case 'params'
    out1 = {model_params};

  case 'ss'
{model_ss}

  case 'J'
{jac_struc}
end'''

        # Case h(.,.,.,sn,xn)*hmult(e)
        textmult = '''function [out1,out2,out3,out4,out5,out6] = {filename}(flag,s,x,z,e,snext,xnext,p,output)

voidcell                        = cell(1,6);
[out1,out2,out3,out4,out5,out6] = voidcell{{:}};

switch flag

  case 'b'
    n = size(s,1);
{eq_bounds_block}

  case 'f'
    n = size(s,1);
{eq_fun_block}

  case 'g'
    n = size(s,1);
{state_trans_block}

  case 'h'
    n = size(snext,1);
{exp_fun_block}
{exp_exp_mult_block}

  case 'e'
    n = size(s,1);
{equation_error_block}

  case 'params'
    out1 = {model_params};

  case 'ss'
{model_ss}

  case 'J'
{jac_struc}
end'''

        dp = DicPrinter(sub_list)

        def write_eqs(eq_l, outname='out1', ntabs=0, default=None):
            '''Format equations and bounds'''
            if default:
                eq_block = '  ' * ntabs + '{0} = ' + default + '(n,{1});'
                eq_block = eq_block.format(outname, len(eq_l))
            else:
                eq_block = '  ' * ntabs + '{0} = zeros(n,{1});'.format(
                    outname, len(eq_l))
            eq_template = '\n' + '  ' * ntabs + '{0}(:,{1}) = {2};'
            for i, eq in enumerate(eq_l):
                eq_txt = dp.doprint_matlab(eq, vectorize=True)
                if eq_txt != default:
                    eq_block += eq_template.format(outname, i + 1, eq_txt)
            return eq_block

        def write_der_eqs(eq_l, v_l, lhs, ntabs=0):
            '''Format Jacobians'''
            eq_block = '  ' * ntabs + '{lhs} = zeros(n,{0},{1});'
            eq_block = eq_block.format(len(eq_l), len(v_l), lhs=lhs)
            eq_l_d = eqdiff(eq_l, v_l)
            eq_template = '\n' + '  ' * ntabs + '{lhs}(:,{0},{1}) = {2}; % d eq_{eq_n} w.r.t. {vname}'
            jac_struc = [[0 for i in range(len(v_l))]
                         for j in range(len(eq_l))]
            for i, eqq in enumerate(eq_l_d):
                for j, eq in enumerate(eqq):
                    s = dp.doprint_matlab(eq, vectorize=True)
                    if s != '0':
                        eq_block += eq_template.format(i + 1,
                                                       j + 1,
                                                       s,
                                                       lhs=lhs,
                                                       eq_n=i + 1,
                                                       vname=str(v_l[j]))
                        jac_struc[i][j] = 1
            return [eq_block, jac_struc]

        eq_bounds_block = '''
    % b
{0}

    % db/ds
    if nargout==4
{1}
{2}
    end'''
        eq_bounds_values = write_eqs(inf_bounds, ntabs=2, default='-inf')
        eq_bounds_values += '\n'
        eq_bounds_values += write_eqs(sup_bounds,
                                      'out2',
                                      ntabs=2,
                                      default='inf')

        eq_bounds_jac_inf = write_der_eqs(inf_bounds, states_vars, 'out3', 3)
        eq_bounds_jac_sup = write_der_eqs(sup_bounds, states_vars, 'out4', 3)
        eq_bounds_block = eq_bounds_block.format(eq_bounds_values,
                                                 eq_bounds_jac_inf[0],
                                                 eq_bounds_jac_sup[0])

        eq_f_block = '''
    % f
    if output.F
{0}
    end

    % df/ds
    if output.Js
{1}
    end

    % df/dx
    if output.Jx
{2}
    end

    % df/dz
    if output.Jz
{3}
    end'''
        # eq_f_block = eq_f_block.format(write_eqs(f_eqs, 'out1', 3),
        #                                write_der_eqs(f_eqs, states_vars, 'out2', 3),
        #                                write_der_eqs(f_eqs, controls, 'out3', 3),
        #                                write_der_eqs(f_eqs, exp_vars, 'out4', 3))
        df_ds = write_der_eqs(f_eqs, states_vars, 'out2', 3)
        df_dx = write_der_eqs(f_eqs, controls, 'out3', 3)
        df_dz = write_der_eqs(f_eqs, exp_vars, 'out4', 3)
        eq_f_block = eq_f_block.format(write_eqs(f_eqs, 'out1', 3), df_ds[0],
                                       df_dx[0], df_dz[0])
        jac_struc = '    out1.fs = ' + list_to_mat(df_ds[1]) + ';\n'
        jac_struc += '    out1.fx = ' + list_to_mat(df_dx[1]) + ';\n'
        jac_struc += '    out1.fz = ' + list_to_mat(df_dz[1]) + ';\n'

        eq_g_block = '''
    % g
    if output.F
{0}
    end

    if output.Js
{1}
    end

    if output.Jx
{2}
    end'''
        # eq_g_block = eq_g_block.format(write_eqs(g_eqs, 'out1', 3),
        #                                write_der_eqs(g_eqs, states_vars, 'out2', 3),
        #                                write_der_eqs(g_eqs, controls, 'out3', 3))
        dg_ds = write_der_eqs(g_eqs, states_vars, 'out2', 3)
        dg_dx = write_der_eqs(g_eqs, controls, 'out3', 3)
        eq_g_block = eq_g_block.format(write_eqs(g_eqs, 'out1', 3), dg_ds[0],
                                       dg_dx[0])
        jac_struc += '    out1.gs = ' + list_to_mat(dg_ds[1]) + ';\n'
        jac_struc += '    out1.gx = ' + list_to_mat(dg_dx[1]) + ';\n'

        eq_h_block = '''
    %h
    if output.F
{0}
    end

    if output.Js
{1}
    end

    if output.Jx
{2}
    end

    if output.Jsn
{3}
    end

    if output.Jxn
{4}
    end'''
        # eq_h_block = eq_h_block.format(write_eqs(h_eqs, 'out1', 3),
        #                                write_der_eqs(h_eqs, states_vars, 'out2', 3),
        #                                write_der_eqs(h_eqs, controls, 'out3', 3),
        #                                write_der_eqs(h_eqs, states_f, 'out4', 3),
        #                                write_der_eqs(h_eqs, controls_f, 'out5', 3))
        dh_ds = write_der_eqs(h_eqs, states_vars, 'out2', 3)
        dh_dx = write_der_eqs(h_eqs, controls, 'out3', 3)
        dh_ds_f = write_der_eqs(h_eqs, states_f, 'out4', 3)
        dh_dx_f = write_der_eqs(h_eqs, controls_f, 'out5', 3)
        eq_h_block = eq_h_block.format(write_eqs(h_eqs, 'out1', 3), dh_ds[0],
                                       dh_dx[0], dh_ds_f[0], dh_dx_f[0])
        jac_struc += '    out1.hs = ' + list_to_mat(dh_ds[1]) + ';\n'
        jac_struc += '    out1.hx = ' + list_to_mat(dh_dx[1]) + ';\n'
        jac_struc += '    out1.hsnext = ' + list_to_mat(dh_ds_f[1]) + ';\n'
        jac_struc += '    out1.hxnext = ' + list_to_mat(dh_dx_f[1]) + ';\n'

        eq_hm_block = '''
    % hmult
    if output.hmult
{0}
    end'''
        eq_hm_block = eq_hm_block.format(write_eqs(hm_eqs, 'out6', 3))

        if e_eqs:
            equation_error_block = write_eqs(e_eqs, 'out1', 3)
        else:
            equation_error_block = '''    out1 = [];'''

        # Model informations
        [y, x, params_values] = model.read_calibration()
        vvs = model.variables
        s_ss = [y[vvs.index(v)] for v in model['variables_groups']['states']]
        x_ss = [y[vvs.index(v)] for v in model['variables_groups']['controls']]

        model_ss = '''    out1 = {s_ss};
    out2 = {x_ss};'''
        model_ss = model_ss.format(s_ss=value_to_mat(s_ss).replace(';', ''),
                                   x_ss=value_to_mat(x_ss).replace(';', ''))

        if hm_eqs:
            text = textmult.format(eq_bounds_block=eq_bounds_block,
                                   filename=model.fname,
                                   eq_fun_block=eq_f_block,
                                   state_trans_block=eq_g_block,
                                   exp_fun_block=eq_h_block,
                                   exp_exp_mult_block=eq_hm_block,
                                   equation_error_block=equation_error_block,
                                   model_params=value_to_mat(params_values),
                                   model_ss=model_ss,
                                   jac_struc=jac_struc)
        else:
            text = text.format(eq_bounds_block=eq_bounds_block,
                               filename=model.fname,
                               eq_fun_block=eq_f_block,
                               state_trans_block=eq_g_block,
                               exp_fun_block=eq_h_block,
                               equation_error_block=equation_error_block,
                               model_params=value_to_mat(params_values),
                               model_ss=model_ss,
                               jac_struc=jac_struc)

        return text
def compile_multiargument_function(equations,
                                   args_list,
                                   args_names,
                                   parms,
                                   fname='anonymous_function',
                                   diff=True,
                                   return_text=False,
                                   use_numexpr=False,
                                   order='rows'):
    """
    :param equations: list of sympy expressions
    :param args_list: list of lists of symbols (e.g. [[a_1,a_2], [b_1,b_2]])
    :param args_names: list of strings (['a','b']
    :param parms: list of symbols to be used as parameters
    :param fname: name of the python function to be generated
    :param diff: include symbolic derivates in generated function
    :param vectorize: arguments are vectorized (not parameters)
    :param return_function: a python function f(a,b,p) where p is a vector of parameters and a, b, arrays
    :return:
    """

    template = '{0}_{1}'

    declarations = ""
    sub_list = {}

    for i, args in enumerate(args_list):
        vec_name = args_names[i]
        for j, v in enumerate(args):
            sub_list[v] = template.format(vec_name, j)
            if order == 'rows':
                declarations += "    {0}_{1} = {0}[{1},...]\n".format(
                    vec_name, j)
            else:
                declarations += "    {0}_{1} = {0}[:,{1}]\n".format(
                    vec_name, j)
    for i, p in enumerate(parms):
        sub_list[p] = '{0}_{1}'.format('p', i)
        declarations += "    {0}_{1} = {0}[{1}]\n".format('p', i)

    import sympy
    # TODO: construct a common list of symbol that should be understood everywhere
    sub_list[sympy.Symbol('inf')] = 'inf'

    text = '''
def {fname}({args_names}, {param_names}, derivs=False):

    import numpy as np
    from numpy import exp, log
    from numpy import sin, cos, tan
    from numpy import arcsin as asin
    from numpy import arccos as acos
    from numpy import arctan as atan
    from numpy import sinh, cosh, tanh
    from numpy import pi
    from numpy import inf

    {use_numexpr}

{declarations}


    n = {var}.shape[{size}]

{content}

    return {return_names}
    '''

    from dolo.compiler.common import DicPrinter

    dp = DicPrinter(sub_list)

    def write_eqs(eq_l, outname='val'):
        if order == 'rows':
            eq_block = '    {0} = np.zeros( ({1},n) )\n'.format(
                outname, len(eq_l))
        else:
            eq_block = '    {0} = np.zeros( (n,{1}) )\n'.format(
                outname, len(eq_l))
        for i, eq in enumerate(eq_l):
            eq_string = dp.doprint_numpy(eq)
            if use_numexpr:
                if order == 'rows':
                    eq_block += "    {0}[{1},:] = numexpr.evaluate('{2}')\n".format(
                        outname, i, eq_string)
                else:
                    eq_block += "    {0}[:,{1}] = numexpr.evaluate('{2}')\n".format(
                        outname, i, eq_string)
            else:
                if order == 'rows':
                    eq_block += '    {0}[{1},:] = {2}\n'.format(
                        outname, i, eq_string)
                else:
                    eq_block += '    {0}[:,{1}] = {2}\n'.format(
                        outname, i, eq_string)
        return eq_block

    def write_der_eqs(eq_l, v_l, lhs):
        if order == 'rows':
            eq_block = '    {lhs} = np.zeros( ({0},{1},n) )\n'.format(
                len(eq_l), len(v_l), lhs=lhs)
        else:
            eq_block = '    {lhs} = np.zeros( (n,{0},{1}) )\n'.format(
                len(eq_l), len(v_l), lhs=lhs)
        eq_l_d = eqdiff(eq_l, v_l)
        for i, eqq in enumerate(eq_l_d):
            for j, eq in enumerate(eqq):
                if not eq == 0:
                    if use_numexpr:
                        eq_string = dp.doprint_numpy(eq)
                        if order == 'rows':
                            eq_block += "    {lhs}[{0},{1},:] = numexpr.evaluate('{2}')\n".format(
                                i, j, eq_string, lhs=lhs)
                        else:
                            eq_block += "    {lhs}[:,{0},{1}] = numexpr.evaluate('{2}')\n".format(
                                i, j, eq_string, lhs=lhs)
                    else:
                        eq_string = dp.doprint(eq)
                        if order == 'rows':
                            eq_block += "    {lhs}[{0},{1},:] = {2}\n".format(
                                i, j, eq_string, lhs=lhs)
                        else:
                            eq_block += "    {lhs}[:,{0},{1}] = {2}\n".format(
                                i, j, eq_string, lhs=lhs)
        return eq_block

    content = write_eqs(equations)
    content += '''
    if not derivs:
        return val
    '''

    if diff:
        for i, a_g in enumerate(args_list):
            lhs = 'val_' + args_names[i]
            content += "\n    # Derivatives w.r.t: {0}\n\n".format(
                args_names[i])
            content += write_der_eqs(equations, a_g, lhs)

    return_names = '[val, ' + str.join(
        ', ', ['val_' + str(a) for a in args_names]) + ']' if diff else 'val'
    text = text.format(size=-1 if order == 'rows' else 0,
                       fname=fname,
                       use_numexpr="import numexpr\n" if use_numexpr else "",
                       declarations=declarations,
                       var=args_names[0],
                       content=content,
                       return_names=return_names,
                       args_names=str.join(', ', args_names),
                       param_names='p')

    if return_text:
        return text

    return code_to_function(text, fname)
Beispiel #8
0
    def compute_dynamic_mfile(self, max_order=2):

        print "Computing dynamic .m file at order {0}.".format(max_order)

        DerivativesTree.symbol_type = TSymbol

        model = self.model

        var_order = model.dyn_var_order + model.shocks

        # TODO create a log system
        t = []
        t.append(time.time())
        sols = []
        i = 0
        for eq in model.equations:
            i += 1
            ndt = DerivativesTree(eq.gap)
            ndt.compute_nth_order_children(max_order)
            sols.append(ndt)

        t.append(time.time())

        self.dynamic_derivatives = sols

        dyn_subs_dict = self.dynamic_substitution_list()
        dyn_printer = DicPrinter(dyn_subs_dict)

        txt = """function [residual, {gs}] = {fname}_dynamic(y, x, params, it_)
%
% Status : Computes dynamic model for Dynare
%
% Warning : this file is generated automatically by Dynare
%           from model file (.mod)

%
% Model equations
%

    residual = zeros({neq}, 1);
"""
        gs = str.join(", ", [("g" + str(i)) for i in range(1, (max_order + 1))])
        txt = txt.format(gs=gs, fname=model.fname, neq=len(model.equations))

        t.append(time.time())
        for i in range(len(sols)):
            ndt = sols[i]
            eq = ndt.expr
            rhs = dyn_printer.doprint_matlab(eq)
            txt += "    residual({0}) = {1};\n".format(i + 1, rhs)
        t.append(time.time())

        for current_order in range(1, (max_order + 1)):
            if current_order == 1:
                matrix_name = "Jacobian"
            elif current_order == 2:
                matrix_name = "Hessian"
            else:
                matrix_name = "{0}_th order".format(current_order)

            txt += """
    if nargout >= {orderr}
%
% {matrix_name} matrix
%

""".format(
                orderr=current_order + 1, matrix_name=matrix_name
            )
            if current_order == 2:
                txt.format(matrix_name="Hessian")
            elif current_order == 1:
                txt.format(matrix_name="Jacobian")
            t.append(time.time())

            nnzd = self.NNZDerivatives(current_order)
            if True:  # we write full matrices ...
                txt += "        v{order} = zeros({nnzd}, 3);\n".format(order=current_order, nnzd=nnzd)
                i = 0
                for n in range(len(sols)):
                    ndt = sols[n]
                    l = ndt.list_nth_order_children(current_order)
                    for nd in l:
                        i += 1
                        # here we compute indices where we write the derivatives
                        indices = nd.compute_index_set_matlab(var_order)
                        rhs = dyn_printer.doprint_matlab(nd.expr)
                        i0 = indices[0]
                        indices.remove(i0)
                        i_ref = i
                        txt += "        v{order}({i},:) = [{i_eq}, {i_col}, {value}] ;\n".format(
                            order=current_order, i=i, i_eq=n + 1, i_col=i0, value=rhs
                        )
                        for ind in indices:
                            i += 1
                            txt += "        v{order}({i},:) = [{i_eq}, {i_col}, v{order}({i_ref},3)];\n".format(
                                order=current_order, i=i, i_eq=n + 1, i_col=ind, i_ref=i_ref
                            )
                txt += "        g{order} = sparse(v{order}(:,1),v{order}(:,2),v{order}(:,3),{n_rows},{n_cols});\n".format(
                    order=current_order, n_rows=len(model.equations), n_cols=len(var_order) ** current_order
                )
            else:  # ... or sparse matrices
                print "to be implemented"

            txt += """
    end
"""
        t.append(time.time())
        f = file(model.fname + "_dynamic.m", "w")
        f.write(txt)
        f.close()
        return txt
Beispiel #9
0
def compile_multiargument_function(equations,
                                   args_list,
                                   args_names,
                                   parms,
                                   diff=False,
                                   fname='anonymous_function'):
    """
    :param equations: list of sympy expressions
    :param args_list: list of lists of symbols (e.g. [[a_1,a_2], [b_1,b_2]])
    :param args_names: list of strings (['a','b']
    :param parms: list of symbols to be used as parameters
    :param fname: name of the python function to be generated
    :param diff: include symbolic derivates in generated function
    :param vectorize: arguments are vectorized (not parameters)
    :param return_function: the source of a Julia function f(a,b,p) where p is a vector of parameters and a, b, arrays
    :return:
    """

    vectorize = True

    template = '{0}[:,{1}]'

    sub_list = {}

    for i, args in enumerate(args_list):
        vec_name = args_names[i]
        for j, v in enumerate(args):
            sub_list[v] = template.format(vec_name, j + 1)

    for i, p in enumerate(parms):
        sub_list[p] = '{0}[{1}]'.format('p', i + 1)

    import sympy
    sub_list[sympy.Symbol('inf')] = 'inf'

    text = '''
function {fname}({args_names}, {param_names})

    n = size({var},1)

{content}

    return {return_names}

end
    '''

    from dolo.compiler.common import DicPrinter

    dp = DicPrinter(sub_list)

    def write_eqs(eq_l, outname='val'):
        eq_block = '    {0} = zeros( n, {1} )\n'.format(outname, len(eq_l))
        for i, eq in enumerate(eq_l):
            eq_block += '    {0}[:,{1}] = {2}\n'.format(
                outname, i + 1, dp.doprint_numpy(eq))
        return eq_block

    def write_der_eqs(eq_l, v_l, lhs):
        eq_block = '    {lhs} = np.zeros( (n,{1},{0}) )\n'.format(len(eq_l),
                                                                  len(v_l),
                                                                  lhs=lhs)
        eq_l_d = eqdiff(eq_l, v_l)
        for i, eqq in enumerate(eq_l_d):
            for j, eq in enumerate(eqq):
                s = dp.doprint_numpy(eq)
                eq_block += '    {lhs}[:,{1},{0}] = {2}\n'.format(i + 1,
                                                                  j + 1,
                                                                  s,
                                                                  lhs=lhs)
        return eq_block

    content = write_eqs(equations)

    if diff:
        for i, a_g in enumerate(args_list):
            lhs = 'val_' + args_names[i]
            content += "\n    # Derivatives w.r.t: {0}\n\n".format(
                args_names[i])
            content += write_der_eqs(equations, a_g, lhs)

    return_names = '[val, ' + str.join(
        ', ', ['val_' + str(a) for a in args_names]) + ']' if diff else 'val'
    text = text.format(fname=fname,
                       var=args_names[0],
                       content=content,
                       return_names=return_names,
                       args_names=str.join(', ', args_names),
                       param_names='p')

    text = text.replace('**', '.^')
    text = text.replace('*', '.*')
    text = text.replace('/', './')
    #    text = text.replace('+','.+')
    #    text = text.replace('-','.-')

    return text
    def compute_static_mfile(self, max_order=1):

        print "Computing static .m file at order {0}.".format(max_order)

        DerivativesTree.symbol_type = Variable

        model = self.model
        var_order = model.variables

        # TODO create a log system

        sols = []
        i = 0
        for eq in model.equations:
            i += 1
            l = [tv for tv in eq.atoms() if isinstance(tv, Variable)]
            expr = eq.gap
            for tv in l:
                if tv.lag != 0:
                    expr = expr.subs(tv, tv.P)
            ndt = DerivativesTree(expr)
            ndt.compute_nth_order_children(max_order)
            sols.append(ndt)
        self.static_derivatives = sols

        stat_subs_dict = self.static_substitution_list()

        stat_printer = DicPrinter(stat_subs_dict)

        txt = """function [residual, {gs}] = {fname}_static(y, x, params, it_)
%
% Status : Computes static model for Dynare
%
% Warning : this file is generated automatically by Dynare
%           from model file (.mod)

%
% Model equations
%

    residual = zeros({neq}, 1);
"""
        gs = str.join(', ',
                      [('g' + str(i)) for i in range(1, (max_order + 1))])
        txt = txt.format(gs=gs, fname=model.fname, neq=len(model.equations))

        for i in range(len(sols)):
            ndt = sols[i]
            eq = ndt.expr
            rhs = stat_printer.doprint_matlab(eq)
            txt += '    residual({0}) = {1};\n'.format(i + 1, rhs)

        for current_order in range(1, (max_order + 1)):
            if current_order == 1:
                matrix_name = "Jacobian"
            elif current_order == 2:
                matrix_name = "Hessian"
            else:
                matrix_name = "{0}_th order".format(current_order)

            txt += """
    if nargout >= {orderr}
        g{order} = zeros({n_rows}, {n_cols});

%
% {matrix_name} matrix
%
\n""".format(order=current_order,
             orderr=current_order + 1,
             n_rows=len(model.equations),
             n_cols=len(var_order)**current_order,
             matrix_name=matrix_name)
            if current_order == 2:
                txt.format(matrix_name="Hessian")

            # What is the equivalent of NNZ for static files ?
            nnzd = self.NNZStaticDerivatives(current_order)

            if True:
                for n in range(len(sols)):
                    ndt = sols[n]
                    l = ndt.list_nth_order_children(current_order)
                    for nd in l:
                        # here we compute indices where we write the derivatives
                        indices = nd.compute_index_set_matlab(var_order)

                        rhs = stat_printer.doprint_matlab(nd.expr)

                        #rhs = comp.dyn_tabify_expression(nd.expr)
                        i0 = indices[0]
                        indices.remove(i0)
                        txt += '        g{order}({0},{1}) = {2};\n'.format(
                            n + 1, i0, rhs, order=current_order)
                        for ind in indices:
                            txt += '        g{order}({0},{1}) = g{order}({0},{2});\n'.format(
                                n + 1, ind, i0, order=current_order)
            else:
                print 'to be implemented'
            txt += """
    end
"""

        f = file(model.fname + '_static.m', 'w')
        f.write(txt)
        f.close()
        return txt
    def compute_dynamic_mfile(self, max_order=2):

        print "Computing dynamic .m file at order {0}.".format(max_order)

        DerivativesTree.symbol_type = TSymbol

        model = self.model

        var_order = model.dyn_var_order + model.shocks

        # TODO create a log system
        t = []
        t.append(time.time())
        sols = []
        i = 0
        for eq in model.equations:
            i += 1
            ndt = DerivativesTree(eq.gap)
            ndt.compute_nth_order_children(max_order)
            sols.append(ndt)

        t.append(time.time())

        self.dynamic_derivatives = sols

        dyn_subs_dict = self.dynamic_substitution_list()
        dyn_printer = DicPrinter(dyn_subs_dict)

        txt = """function [residual, {gs}] = {fname}_dynamic(y, x, params, it_)
%
% Status : Computes dynamic model for Dynare
%
% Warning : this file is generated automatically by Dynare
%           from model file (.mod)

%
% Model equations
%

    residual = zeros({neq}, 1);
"""
        gs = str.join(', ',
                      [('g' + str(i)) for i in range(1, (max_order + 1))])
        txt = txt.format(gs=gs, fname=model.fname, neq=len(model.equations))

        t.append(time.time())
        for i in range(len(sols)):
            ndt = sols[i]
            eq = ndt.expr
            rhs = dyn_printer.doprint_matlab(eq)
            txt += '    residual({0}) = {1};\n'.format(i + 1, rhs)
        t.append(time.time())

        for current_order in range(1, (max_order + 1)):
            if current_order == 1:
                matrix_name = "Jacobian"
            elif current_order == 2:
                matrix_name = "Hessian"
            else:
                matrix_name = "{0}_th order".format(current_order)

            txt += """
    if nargout >= {orderr}
%
% {matrix_name} matrix
%

""".format(orderr=current_order + 1, matrix_name=matrix_name)
            if current_order == 2:
                txt.format(matrix_name="Hessian")
            elif current_order == 1:
                txt.format(matrix_name="Jacobian")
            t.append(time.time())

            nnzd = self.NNZDerivatives(current_order)
            if True:  # we write full matrices ...
                txt += "        v{order} = zeros({nnzd}, 3);\n".format(
                    order=current_order, nnzd=nnzd)
                i = 0
                for n in range(len(sols)):
                    ndt = sols[n]
                    l = ndt.list_nth_order_children(current_order)
                    for nd in l:
                        i += 1
                        # here we compute indices where we write the derivatives
                        indices = nd.compute_index_set_matlab(var_order)
                        rhs = dyn_printer.doprint_matlab(nd.expr)
                        i0 = indices[0]
                        indices.remove(i0)
                        i_ref = i
                        txt += '        v{order}({i},:) = [{i_eq}, {i_col}, {value}] ;\n'.format(
                            order=current_order,
                            i=i,
                            i_eq=n + 1,
                            i_col=i0,
                            value=rhs)
                        for ind in indices:
                            i += 1
                            txt += '        v{order}({i},:) = [{i_eq}, {i_col}, v{order}({i_ref},3)];\n'.format(
                                order=current_order,
                                i=i,
                                i_eq=n + 1,
                                i_col=ind,
                                i_ref=i_ref)
                txt += '        g{order} = sparse(v{order}(:,1),v{order}(:,2),v{order}(:,3),{n_rows},{n_cols});\n'.format(
                    order=current_order,
                    n_rows=len(model.equations),
                    n_cols=len(var_order)**current_order)
            else:  # ... or sparse matrices
                print 'to be implemented'

            txt += """
    end
"""
        t.append(time.time())
        f = file(model.fname + '_dynamic.m', 'w')
        f.write(txt)
        f.close()
        return txt
    def compute_main_file(self, omit_nnz=True):
        model = self.model

        # should be computed somewhere else
        all_symbols = set([])
        for eq in model.equations:
            all_symbols.update(eq.atoms())
        format_dict = dict()
        format_dict['fname'] = model.fname
        format_dict['maximum_lag'] = max(
            [-v.lag for v in all_symbols if isinstance(v, TSymbol)])
        format_dict['maximum_lead'] = max(
            [v.lag for v in all_symbols if isinstance(v, TSymbol)])
        format_dict['maximum_endo_lag'] = max(
            [-v.lag for v in all_symbols if isinstance(v, Variable)])
        format_dict['maximum_endo_lead'] = max(
            [v.lag for v in all_symbols if isinstance(v, Variable)])
        format_dict['maximum_exo_lag'] = max(
            [-v.lag for v in all_symbols if isinstance(v, Shock)])
        format_dict['maximum_exo_lead'] = max(
            [v.lag for v in all_symbols if isinstance(v, Shock)])
        format_dict['endo_nbr'] = len(model.variables)
        format_dict['exo_nbr'] = len(model.shocks)
        format_dict['param_nbr'] = len(model.parameters)

        output = """%
% Status : main Dynare file
%
% Warning : this file is generated automatically by Dolo for Dynare
%           from model file (.mod)

clear all
tic;
global M_ oo_ options_
global ys0_ ex0_ ct_
options_ = [];
M_.fname = '{fname}';
%
% Some global variables initialization
%
global_initialization;
diary off;
warning_old_state = warning;
warning off;
delete {fname}.log;
warning warning_old_state;
logname_ = '{fname}.log';
diary {fname}.log;
options_.model_mode = 0;
erase_compiled_function('{fname}_static');
erase_compiled_function('{fname}_dynamic');

M_.exo_det_nbr = 0;
M_.exo_nbr = {exo_nbr};
M_.endo_nbr = {endo_nbr};
M_.param_nbr = {param_nbr};
M_.Sigma_e = zeros({exo_nbr}, {exo_nbr});
M_.exo_names_orig_ord = [1:{exo_nbr}];
""".format(**format_dict)

        string_of_names = lambda l: str.join(' , ',
                                             ["'%s'" % str(v) for v in l])
        string_of_tex_names = lambda l: str.join(
            ' , ', ["'%s'" % v._latex_() for v in l])
        output += "M_.exo_names = strvcat( {0} );\n".format(
            string_of_names(model.shocks))
        output += "M_.exo_names_tex = strvcat( {0} );\n".format(
            string_of_tex_names(model.shocks))
        output += "M_.endo_names = strvcat( {0} );\n".format(
            string_of_names(model.variables))
        output += "M_.endo_names_tex = strvcat( {0} );\n".format(
            string_of_tex_names(model.variables))
        output += "M_.param_names = strvcat( {0} );\n".format(
            string_of_names(model.parameters))
        output += "M_.param_names_tex = strvcat( {0} );\n".format(
            string_of_tex_names(model.parameters))

        from dolo.misc.matlab import value_to_mat
        lli = value_to_mat(self.lead_lag_incidence_matrix())
        output += "M_.lead_lag_incidence = {0}';\n".format(lli)

        output += """M_.maximum_lag = {maximum_lag};
M_.maximum_lead = {maximum_lead};
M_.maximum_endo_lag = {maximum_endo_lag};
M_.maximum_endo_lead = {maximum_endo_lead};
M_.maximum_exo_lag = {maximum_exo_lag};
M_.maximum_exo_lead = {maximum_exo_lead};
oo_.steady_state = zeros({endo_nbr}, 1);
oo_.exo_steady_state = zeros({exo_nbr}, 1);
M_.params = repmat(NaN,{param_nbr}, 1);
""".format(**format_dict)

        # Now we add tags for equations
        tags_array_string = []
        for eq in model.equations:
            for k in eq.tags.keys():
                tags_array_string.append("{n}, '{key}', '{value}'".format(
                    n=eq.n, key=k, value=eq.tags[k]))
        output += "M_.equations_tags = {{\n{0}\n}};\n".format(
            ";\n".join(tags_array_string))

        if not omit_nnz:
            # we don't set the number of non zero derivatives yet
            order = max([ndt.depth() for ndt in self.dynamic_derivatives])
            output += "M_.NNZDerivatives = zeros({0}, 1); % parrot mode\n".format(
                order)
            output += "M_.NNZDerivatives(1) = {0}; % parrot mode\n".format(
                self.NNZDerivatives(1))
            output += "M_.NNZDerivatives(2) = {0}; % parrot mode\n".format(
                self.NNZDerivatives(2))
            output += "M_.NNZDerivatives(3) = {0}; % parrot mode\n".format(
                self.NNZDerivatives(3))

        idp = DicPrinter(
            self.static_substitution_list(y='oo_.steady_state',
                                          params='M_.params'))

        # BUG: how do we treat parameters absent from the model, but present in parameters_values ?

        from dolo.misc.triangular_solver import solve_triangular_system

        [junk, porder] = solve_triangular_system(model.parameters_values)
        porder = [p for p in porder if p in model.parameters]

        d = dict()
        d.update(model.parameters_values)
        d.update(model.init_values)

        [junk, vorder] = solve_triangular_system(model.init_values)
        vorder = [v for v in vorder if p in model.variables]

        for p in porder:
            i = model.parameters.index(p) + 1
            output += "M_.params({0}) = {1};\n".format(
                i, idp.doprint_matlab(model.parameters_values[p]))
            output += "{0} = M_.params({1});\n".format(p, i)

        output += '''%
% INITVAL instructions
%
'''
        #idp = DicPrinter(self.static_substitution_list(y='oo_.steady_state',params='M_.params'))
        output += "options_.initval_file = 0; % parrot mode\n"
        for v in vorder:
            if v in self.model.variables:  # should be removed
                i = model.variables.index(v) + 1
                output += "oo_.steady_state({0}) = {1};\n".format(
                    i, idp.doprint_matlab(model.init_values[v]))
        # we don't allow initialization of shocks to nonzero values
        output += "oo_.exo_steady_state = zeros({0},1);\n".format(
            len(model.shocks))
        output += '''oo_.endo_simul=[oo_.steady_state*ones(1,M_.maximum_lag)];
if M_.exo_nbr > 0;
    oo_.exo_simul = [ones(M_.maximum_lag,1)*oo_.exo_steady_state'];
end;
if M_.exo_det_nbr > 0;
    oo_.exo_det_simul = [ones(M_.maximum_lag,1)*oo_.exo_det_steady_state'];
end;
'''
        #output += '''steady;
        output += """
%
% SHOCKS instructions
%
make_ex_;
M_.exo_det_length = 0; % parrot
"""

        for i in range(model.covariances.shape[0]):
            for j in range(model.covariances.shape[1]):
                expr = model.covariances[i, j]
                if expr != 0:
                    v = str(expr).replace("**", "^")
                    #if (v != 0) and not isinstance(v,sympy.core.numbers.Zero):
                    output += "M_.Sigma_e({0}, {1}) = {2};\n".format(
                        i + 1, j + 1, v)

        # This results from the stoch_simul(


#        output += '''options_.drop = 200;
#options_.order = 3;
#var_list_=[];
#info = stoch_simul(var_list_);
#'''
#
#        output += '''save('example2_results.mat', 'oo_', 'M_', 'options_');
#diary off
#
#disp(['Total computing time : ' dynsec2hms(toc) ]);'''

        f = file(model.fname + '.m', 'w')
        f.write(output)
        f.close()

        return output
 def static_tabify_expression(self, eq, for_matlab=False, for_c=True):
     #from dolo.misc.calculus import map_function_to_expression
     # works when all variables are expressed without lag
     subs_dict = self.static_substitution_list
     res = DicPrinter(subs_dict).doprint(eq)
    def compute_static_pfile(self, max_order):

        DerivativesTree.symbol_type = Variable

        model = self.model
        var_order = model.variables

        # TODO create a log system

        sols = []
        i = 0
        for eq in model.equations:
            i += 1
            l = [tv for tv in eq.atoms() if isinstance(tv, Variable)]
            expr = eq.gap
            for tv in l:
                if tv.lag != 0:
                    expr = expr.subs(tv, tv.P)
            ndt = DerivativesTree(expr)
            ndt.compute_nth_order_children(max_order)
            sols.append(ndt)
        self.static_derivatives = sols

        stat_subs_dict = self.static_substitution_list(ind_0=0, brackets=True)

        stat_printer = DicPrinter(stat_subs_dict)

        txt = """def static_gaps(y, x, params):
#
# Status : Computes static model for Python
#
# Warning : this file is generated automatically by Dynare
#           from model file (.mod)
#
#
# Model equations
#
    import numpy as np
    from numpy import exp,log, sin, cos, tan, sinh, cosh, tanh
    from numpy import arcsin as asin
    from numpy import arccos as acos
    from numpy import arctan as atan

    it_ = 1 # should remove this !

    g = []

    residual = np.zeros({neq})
"""
        gs = str.join(", ", [("g" + str(i)) for i in range(1, (max_order + 1))])
        txt = txt.format(gs=gs, fname=model.fname, neq=len(model.equations))

        for i in range(len(sols)):
            ndt = sols[i]
            eq = ndt.expr
            rhs = stat_printer.doprint_matlab(eq)
            txt += "    residual[{0}] = {1}\n".format(i, rhs)

        txt += "    g.append(residual)\n"

        for current_order in range(1, (max_order + 1)):
            if current_order == 1:
                matrix_name = "Jacobian"
            elif current_order == 2:
                matrix_name = "Hessian"
            else:
                matrix_name = "{0}_th order".format(current_order)

            txt += """
    g{order} = np.zeros(({n_rows}, {n_cols}))
#    {matrix_name} matrix\n""".format(
                order=current_order,
                orderr=current_order + 1,
                n_rows=len(model.equations),
                n_cols=len(var_order) ** current_order,
                matrix_name=matrix_name,
            )
            for n in range(len(sols)):
                ndt = sols[n]
                l = ndt.list_nth_order_children(current_order)
                for nd in l:
                    # here we compute indices where we write the derivatives
                    indices = nd.compute_index_set_matlab(var_order)

                    rhs = stat_printer.doprint_matlab(nd.expr)

                    # rhs = comp.dyn_tabify_expression(nd.expr)
                    i0 = indices[0]
                    indices.remove(i0)
                    txt += "    g{order}[{0},{1}] = {2}\n".format(n, i0 - 1, rhs, order=current_order)
                    for ind in indices:
                        txt += "    g{order}[{0},{1}] = g{order}[{0},{2}]\n".format(
                            n, ind - 1, i0 - 1, order=current_order
                        )
            txt += "    g.append(g{order})\n".format(order=current_order)

        txt += "    return g\n"
        txt = txt.replace("^", "**")
        exec(txt)
        return static_gaps
Beispiel #15
0
    def process_output_recs(self, solution_order=False, fname=None):

        data = self.read_model()
        dmodel = self.model
        model = dmodel

        f_eqs = data['f_eqs']
        g_eqs = data['g_eqs']
        h_eqs = data['h_eqs']
        states_vars = data['states_vars']
        controls = data['controls']
        exp_vars = data['exp_vars']
        inf_bounds = data['inf_bounds']
        sup_bounds = data['sup_bounds']


        controls_f = [v(1) for v in controls]
        states_f = [v(1) for v in states_vars]

        sub_list = dict()
        for i,v in enumerate(exp_vars):
            sub_list[v] = 'z(:,{0})'.format(i+1)

        for i,v in enumerate(controls):
            sub_list[v] = 'x(:,{0})'.format(i+1)
            sub_list[v(1)] = 'xnext(:,{0})'.format(i+1)

        for i,v in enumerate(states_vars):
            sub_list[v] = 's(:,{0})'.format(i+1)
            sub_list[v(1)] = 'snext(:,{0})'.format(i+1)

        for i,v in enumerate(dmodel.shocks):
            sub_list[v] = 'e(:,{0})'.format(i+1)

        for i,v in enumerate(dmodel.parameters):
            sub_list[v] = 'p({0})'.format(i+1)

        import sympy
        sub_list[sympy.Symbol('inf')] = 'Inf'


        text = '''function [out1,out2,out3,out4,out5] = {mfname}(flag,s,x,z,e,snext,xnext,p,out);

output = struct('F',1,'Js',0,'Jx',0,'Jsn',0,'Jxn',0,'Jz',0,'hmult',0);

if nargin == 9
  output                     = catstruct(output,out);
  voidcell                   = cell(1,5);
  [out1,out2,out3,out4,out5] = voidcell{{:}};
else
  if nargout >= 2, output.Js = 1; end
  if nargout >= 3, output.Jx = 1; end
  if nargout >= 4
    if strcmpi(flag, 'f')
      output.Jz = 1;
    else
      output.Jsn = 1;
    end
  end
  if nargout >= 5, output.Jxn = 1; end
end


switch flag

  case 'b';
    n = size(s,1);
{eq_bounds_block}

  case 'f';
    n = size(s,1);
{eq_fun_block}
  case 'g';
    n = size(s,1);
{state_trans_block}
  case 'h';
    n = size(snext,1);
{exp_fun_block}
  case 'e';
    out1 = [];

  case 'model'; % informations about the model
{model_info}

end
'''

        from dolo.compiler.common import DicPrinter

        dp = DicPrinter(sub_list)

        def write_eqs(eq_l,outname='out1',ntabs=0):
            eq_block = '  ' * ntabs + '{0} = zeros(n,{1});'.format(outname,len(eq_l))
            for i,eq in enumerate(eq_l):
                eq_block += '\n' + '  ' * ntabs + '{0}(:,{1}) = {2};'.format( outname,  i+1,  dp.doprint_matlab(eq,vectorize=True) )
            return eq_block

        def write_der_eqs(eq_l,v_l,lhs,ntabs=0):
            eq_block = '  ' * ntabs + '{lhs} = zeros(n,{0},{1});'.format(len(eq_l),len(v_l),lhs=lhs)
            eq_l_d = eqdiff(eq_l,v_l)
            for i,eqq in enumerate(eq_l_d):
                for j,eq in enumerate(eqq):
                    s = dp.doprint_matlab( eq, vectorize=True )
                    eq_block += '\n' + '  ' * ntabs + '{lhs}(:,{0},{1}) = {2}; % d eq_{eq_n} w.r.t. {vname}'.format(i+1,j+1,s,lhs=lhs,eq_n=i+1,vname=str(v_l[j]) )
            return eq_block

        eq_bounds_block = write_eqs(inf_bounds,ntabs=2)
        eq_bounds_block += '\n'
        eq_bounds_block += write_eqs(sup_bounds,'out2',ntabs=2)

        eq_f_block = '''
    % f
    if output.F
{0}
    end

    % df/ds
    if output.Js
{1}
    end

    % df/dx
    if output.Jx
{2}
    end

    % df/dz
    if output.Jz
{3}
    end
        '''.format( write_eqs(f_eqs,'out1',3),
                    write_der_eqs(f_eqs,states_vars,'out2',3),
                    write_der_eqs(f_eqs,controls,'out3',3),
                    write_der_eqs(f_eqs,exp_vars,'out4',3)
            )

        eq_g_block = '''
    % g
    if output.F
{0}      
    end

    if output.Js
{1}
    end

    if output.Jx
{2}
    end
        '''.format( write_eqs(g_eqs,'out1',3),
                    write_der_eqs(g_eqs,states_vars,'out2',3),
                    write_der_eqs(g_eqs,controls,'out3',3)
            )

        eq_h_block = '''
    %h
    if output.F
{0}
    end

    if output.Js
{1}
    end

    if output.Jx
{2}
    end

    if output.Jsn
{3}
    end

    if output.Jxn
{4}
    end
        '''.format(
             write_eqs(h_eqs,'out1',3),
             write_der_eqs(h_eqs,states_vars,'out2',3),
             write_der_eqs(h_eqs,controls,'out3',3),
             write_der_eqs(h_eqs,states_f,'out4',3),
             write_der_eqs(h_eqs,controls_f,'out5',3)
        )

        # if not with_param_names:
        #    eq_h_block = 's=snext;\nx=xnext;\n'+eq_h_block

        # param_def = 'p = [ ' + str.join(',',[p.name for p in dmodel.parameters])  + '];'

        from dolo.misc.matlab import value_to_mat

        # read model informations
        [y,x,params_values] = model.read_calibration()
        #params_values = '[' + str.join(  ',', [ str( p ) for p in params] ) + '];'
        vvs = model.variables
        s_ss = [ y[vvs.index(v)] for v in model['variables_groups']['states'] ]
        x_ss = [ y[vvs.index(v)] for v in model['variables_groups']['controls'] ]

        model_info = '''
    mod = struct;
    mod.s_ss = {s_ss};
    mod.x_ss = {x_ss};
    mod.params = {params_values};
'''.format(
    s_ss = value_to_mat(s_ss),
    x_ss = value_to_mat(x_ss),
    params_values = value_to_mat(params_values)
)
        if solution_order:
            from dolo.numeric.perturbations_to_states import approximate_controls

            ZZ = approximate_controls(self.model,order=solution_order)
            n_c = len(controls)
            
            ZZ = [np.array(e) for e in ZZ]
            ZZ = [e[:n_c,...] for e in ZZ] # keep only control vars. (x) not expectations (h)

            solution = "    mod.X = cell({0},1);\n".format(len(ZZ))
            for i,zz in enumerate(ZZ):
                solution += "    mod.X{{{0}}} = {1};\n".format(i+1,value_to_mat(zz))
            model_info += solution
        model_info += '    out1 = mod;\n'

        text = text.format(
            eq_bounds_block = eq_bounds_block,
            mfname = fname if fname else 'mf_' + model.fname,
            eq_fun_block=eq_f_block,
            state_trans_block=eq_g_block,
            exp_fun_block=eq_h_block,
#            solution = solution,
            model_info = model_info
        )

        return text
Beispiel #16
0
    def compute_main_file(self, omit_nnz=True):
        model = self.model

        # should be computed somewhere else
        all_symbols = set([])
        for eq in model.equations:
            all_symbols.update(eq.atoms())
        format_dict = dict()
        format_dict["fname"] = model.fname
        format_dict["maximum_lag"] = max([-v.lag for v in all_symbols if isinstance(v, TSymbol)])
        format_dict["maximum_lead"] = max([v.lag for v in all_symbols if isinstance(v, TSymbol)])
        format_dict["maximum_endo_lag"] = max([-v.lag for v in all_symbols if isinstance(v, Variable)])
        format_dict["maximum_endo_lead"] = max([v.lag for v in all_symbols if isinstance(v, Variable)])
        format_dict["maximum_exo_lag"] = max([-v.lag for v in all_symbols if isinstance(v, Shock)])
        format_dict["maximum_exo_lead"] = max([v.lag for v in all_symbols if isinstance(v, Shock)])
        format_dict["endo_nbr"] = len(model.variables)
        format_dict["exo_nbr"] = len(model.shocks)
        format_dict["param_nbr"] = len(model.parameters)

        output = """%
% Status : main Dynare file
%
% Warning : this file is generated automatically by Dolo for Dynare
%           from model file (.mod)

clear all
tic;
global M_ oo_ options_
global ys0_ ex0_ ct_
options_ = [];
M_.fname = '{fname}';
%
% Some global variables initialization
%
global_initialization;
diary off;
warning_old_state = warning;
warning off;
delete {fname}.log;
warning warning_old_state;
logname_ = '{fname}.log';
diary {fname}.log;
options_.model_mode = 0;
erase_compiled_function('{fname}_static');
erase_compiled_function('{fname}_dynamic');

M_.exo_det_nbr = 0;
M_.exo_nbr = {exo_nbr};
M_.endo_nbr = {endo_nbr};
M_.param_nbr = {param_nbr};
M_.Sigma_e = zeros({exo_nbr}, {exo_nbr});
M_.exo_names_orig_ord = [1:{exo_nbr}];
""".format(
            **format_dict
        )

        string_of_names = lambda l: str.join(" , ", ["'%s'" % str(v) for v in l])
        string_of_tex_names = lambda l: str.join(" , ", ["'%s'" % v._latex_() for v in l])
        output += "M_.exo_names = strvcat( {0} );\n".format(string_of_names(model.shocks))
        output += "M_.exo_names_tex = strvcat( {0} );\n".format(string_of_tex_names(model.shocks))
        output += "M_.endo_names = strvcat( {0} );\n".format(string_of_names(model.variables))
        output += "M_.endo_names_tex = strvcat( {0} );\n".format(string_of_tex_names(model.variables))
        output += "M_.param_names = strvcat( {0} );\n".format(string_of_names(model.parameters))
        output += "M_.param_names_tex = strvcat( {0} );\n".format(string_of_tex_names(model.parameters))

        from dolo.misc.matlab import value_to_mat

        lli = value_to_mat(self.lead_lag_incidence_matrix())
        output += "M_.lead_lag_incidence = {0}';\n".format(lli)

        output += """M_.maximum_lag = {maximum_lag};
M_.maximum_lead = {maximum_lead};
M_.maximum_endo_lag = {maximum_endo_lag};
M_.maximum_endo_lead = {maximum_endo_lead};
M_.maximum_exo_lag = {maximum_exo_lag};
M_.maximum_exo_lead = {maximum_exo_lead};
oo_.steady_state = zeros({endo_nbr}, 1);
oo_.exo_steady_state = zeros({exo_nbr}, 1);
M_.params = repmat(NaN,{param_nbr}, 1);
""".format(
            **format_dict
        )

        # Now we add tags for equations
        tags_array_string = []
        for eq in model.equations:
            for k in eq.tags.keys():
                tags_array_string.append("{n}, '{key}', '{value}'".format(n=eq.n, key=k, value=eq.tags[k]))
        output += "M_.equations_tags = {{\n{0}\n}};\n".format(";\n".join(tags_array_string))

        if not omit_nnz:
            # we don't set the number of non zero derivatives yet
            order = max([ndt.depth() for ndt in self.dynamic_derivatives])
            output += "M_.NNZDerivatives = zeros({0}, 1); % parrot mode\n".format(order)
            output += "M_.NNZDerivatives(1) = {0}; % parrot mode\n".format(self.NNZDerivatives(1))
            output += "M_.NNZDerivatives(2) = {0}; % parrot mode\n".format(self.NNZDerivatives(2))
            output += "M_.NNZDerivatives(3) = {0}; % parrot mode\n".format(self.NNZDerivatives(3))

        idp = DicPrinter(self.static_substitution_list(y="oo_.steady_state", params="M_.params"))

        # BUG: how do we treat parameters absent from the model, but present in parameters_values ?

        from dolo.misc.triangular_solver import solve_triangular_system

        [junk, porder] = solve_triangular_system(model.parameters_values)
        porder = [p for p in porder if p in model.parameters]

        d = dict()
        d.update(model.parameters_values)
        d.update(model.init_values)

        [junk, vorder] = solve_triangular_system(model.init_values)
        vorder = [v for v in vorder if p in model.variables]

        for p in porder:
            i = model.parameters.index(p) + 1
            output += "M_.params({0}) = {1};\n".format(i, idp.doprint_matlab(model.parameters_values[p]))
            output += "{0} = M_.params({1});\n".format(p, i)

        output += """%
% INITVAL instructions
%
"""
        # idp = DicPrinter(self.static_substitution_list(y='oo_.steady_state',params='M_.params'))
        output += "options_.initval_file = 0; % parrot mode\n"
        for v in vorder:
            if v in self.model.variables:  # should be removed
                i = model.variables.index(v) + 1
                output += "oo_.steady_state({0}) = {1};\n".format(i, idp.doprint_matlab(model.init_values[v]))
        # we don't allow initialization of shocks to nonzero values
        output += "oo_.exo_steady_state = zeros({0},1);\n".format(len(model.shocks))
        output += """oo_.endo_simul=[oo_.steady_state*ones(1,M_.maximum_lag)];
if M_.exo_nbr > 0;
    oo_.exo_simul = [ones(M_.maximum_lag,1)*oo_.exo_steady_state'];
end;
if M_.exo_det_nbr > 0;
    oo_.exo_det_simul = [ones(M_.maximum_lag,1)*oo_.exo_det_steady_state'];
end;
"""
        # output += '''steady;
        output += """
%
% SHOCKS instructions
%
make_ex_;
M_.exo_det_length = 0; % parrot
"""

        for i in range(model.covariances.shape[0]):
            for j in range(model.covariances.shape[1]):
                expr = model.covariances[i, j]
                if expr != 0:
                    v = str(expr).replace("**", "^")
                    # if (v != 0) and not isinstance(v,sympy.core.numbers.Zero):
                    output += "M_.Sigma_e({0}, {1}) = {2};\n".format(i + 1, j + 1, v)

        # This results from the stoch_simul(
        #        output += '''options_.drop = 200;
        # options_.order = 3;
        # var_list_=[];
        # info = stoch_simul(var_list_);
        #'''
        #
        #        output += '''save('example2_results.mat', 'oo_', 'M_', 'options_');
        # diary off
        #
        # disp(['Total computing time : ' dynsec2hms(toc) ]);'''

        f = file(model.fname + ".m", "w")
        f.write(output)
        f.close()

        return output
def compile_theano_source(values, args_list, args_names, parms, fname='anonymous_function'):


    """
    :param vars: parameters
    :param values: list of values (already triangular)


    """


    vars = ['_res_{}'.format(i) for i in range(len(values))]

    sub_dict = {}
    for e in vars:
        try:
            sn = e.safe_name()
        except Exception:
            sn = '_'+str(e)
        sub_dict[e] = sn

    from dolo.compiler.common import DicPrinter

    dec = ''

    for s in args_names:
        dec += "{} = T.matrix('{}')\n".format(s,s)

    dec += "p = T.vector('p')\n"

    for i,p in enumerate(parms):
        sn = '_'+str(p)
        sub_dict[p] = sn
        dec += '{} = p[{}]\n'.format(sn,i)

    for i, l in enumerate( args_list):
        name = args_names[i]
        for j, e in enumerate(l):
            try:
                sn = e.safe_name()
            except Exception:
                sn = '_'+str(e)
            sub_dict[e] = sn
            dec += '{} = {}[{},:]\n'.format(sn,name,j)

    dp = DicPrinter(sub_dict)
    strings = [ ]
    for i,eq in enumerate( values ):
        rhs = ( dp.doprint( eq) )
        lhs = vars[i]
#        strings.append( '{} = OO + {}'.format(lhs,rhs))
        strings.append( '{} = {}'.format(lhs,rhs))

    source = """

from theano import tensor as T
from theano import function
from theano.tensor import exp

{declarations}

#    OO =  T.zeros((1,s.shape[1]))

{computations}

res = T.stack({vars})

f = function([{args}], res, mode='FAST_RUN',name="{fname}"{on_unused_input})

"""

#    print(args_names)
    source = source.format(
        computations = str.join( '\n', strings),
        declarations = dec,
        vars = str.join(', ', [str(v) for v in vars]),
        args = str.join(', ', [str(v) for v in args_names] + ['p'] ),
        fname = fname,
        on_unused_input = ",on_unused_input='ignore'" if not theano_less_than_6 else ""

    )

    return source
Beispiel #18
0
    def compute_static_mfile(self, max_order=1):

        print "Computing static .m file at order {0}.".format(max_order)

        DerivativesTree.symbol_type = Variable

        model = self.model
        var_order = model.variables

        # TODO create a log system

        sols = []
        i = 0
        for eq in model.equations:
            i += 1
            l = [tv for tv in eq.atoms() if isinstance(tv, Variable)]
            expr = eq.gap
            for tv in l:
                if tv.lag != 0:
                    expr = expr.subs(tv, tv.P)
            ndt = DerivativesTree(expr)
            ndt.compute_nth_order_children(max_order)
            sols.append(ndt)
        self.static_derivatives = sols

        stat_subs_dict = self.static_substitution_list()

        stat_printer = DicPrinter(stat_subs_dict)

        txt = """function [residual, {gs}] = {fname}_static(y, x, params, it_)
%
% Status : Computes static model for Dynare
%
% Warning : this file is generated automatically by Dynare
%           from model file (.mod)

%
% Model equations
%

    residual = zeros({neq}, 1);
"""
        gs = str.join(", ", [("g" + str(i)) for i in range(1, (max_order + 1))])
        txt = txt.format(gs=gs, fname=model.fname, neq=len(model.equations))

        for i in range(len(sols)):
            ndt = sols[i]
            eq = ndt.expr
            rhs = stat_printer.doprint_matlab(eq)
            txt += "    residual({0}) = {1};\n".format(i + 1, rhs)

        for current_order in range(1, (max_order + 1)):
            if current_order == 1:
                matrix_name = "Jacobian"
            elif current_order == 2:
                matrix_name = "Hessian"
            else:
                matrix_name = "{0}_th order".format(current_order)

            txt += """
    if nargout >= {orderr}
        g{order} = zeros({n_rows}, {n_cols});

%
% {matrix_name} matrix
%
\n""".format(
                order=current_order,
                orderr=current_order + 1,
                n_rows=len(model.equations),
                n_cols=len(var_order) ** current_order,
                matrix_name=matrix_name,
            )
            if current_order == 2:
                txt.format(matrix_name="Hessian")

            # What is the equivalent of NNZ for static files ?
            nnzd = self.NNZStaticDerivatives(current_order)

            if True:
                for n in range(len(sols)):
                    ndt = sols[n]
                    l = ndt.list_nth_order_children(current_order)
                    for nd in l:
                        # here we compute indices where we write the derivatives
                        indices = nd.compute_index_set_matlab(var_order)

                        rhs = stat_printer.doprint_matlab(nd.expr)

                        # rhs = comp.dyn_tabify_expression(nd.expr)
                        i0 = indices[0]
                        indices.remove(i0)
                        txt += "        g{order}({0},{1}) = {2};\n".format(n + 1, i0, rhs, order=current_order)
                        for ind in indices:
                            txt += "        g{order}({0},{1}) = g{order}({0},{2});\n".format(
                                n + 1, ind, i0, order=current_order
                            )
            else:
                print "to be implemented"
            txt += """
    end
"""

        f = file(model.fname + "_static.m", "w")
        f.write(txt)
        f.close()
        return txt
Beispiel #19
0
def compile_multiargument_function(equations,
                                   args_list,
                                   args_names,
                                   parms,
                                   fname='anonymous_function',
                                   diff=True,
                                   return_text=False,
                                   order='columns'):
    """
    :param equations: list of sympy expressions
    :param args_list: list of lists of symbols (e.g. [[a_1,a_2], [b_1,b_2]])
    :param args_names: list of strings (['a','b']
    :param parms: list of symbols to be used as parameters
    :param fname: name of the python function to be generated
    :param diff: include symbolic derivates in generated function
    :param vectorize: arguments are vectorized (not parameters)
    :param return_function: a python function f(a,b,p) where p is a vector of parameters and a, b, arrays
    :return:
    """

    if order == 'rows':
        raise (Exception('not implemented'))

    template = '{0}[i,{1}]'

    declarations = ""
    sub_list = {}

    for i, args in enumerate(args_list):
        vec_name = args_names[i]
        for j, v in enumerate(args):
            sub_list[v] = template.format(vec_name, j)
            # declarations += "    {0}_{1} = {0}[{1}]\n".format(vec_name, j)

    for i, p in enumerate(parms):
        sub_list[p] = '{0}[{1}]'.format('p', i)
        # declarations += "    {0}_{1} = {0}[{1}]\n".format('p', i)

    import sympy
    # TODO: construct a common list of symbol that should be understood everywhere
    sub_list[sympy.Symbol('inf')] = 'inf'

    args_size = [len(e) for e in args_list] + [len(parms)]
    return_size = len(equations)

    size_same_as_output = args_size.index(return_size)

    signature = str.join(',',
                         ['(n{})'.format(i) for i in range(len(args_size))])
    signature += '->(n{})'.format(return_size - 1)
    argtypes = [float64[:, :]] * (len(args_size) - 1) + [
        float64[:], float64[:, :]
    ]

    text = '''
from numbapro import float64, void
from numbapro import jit
from numbapro import cuda

@jit( argtypes={argtypes}, target='gpu' )
def {fname}({args_names}, {param_names}, val):

    i = cuda.grid(1)
{content}

#    return val



'''

    from dolo.compiler.common import DicPrinter

    dp = DicPrinter(sub_list)

    def write_eqs(eq_l, outname='val'):
        eq_block = ''
        for i, eq in enumerate(eq_l):
            eq_string = dp.doprint_numpy(eq)
            eq_block += '    val[i,{0}] = {1}\n'.format(i, eq_string)
        return eq_block

    content = write_eqs(equations)

    return_names = 'val'
    text = text.format(
        fname=fname,
        n_equations=len(equations),
        declarations=declarations,
        var=args_names[0],
        content=content,
        return_names=return_names,
        args_names=str.join(', ', args_names),
        param_names='p',
        argtypes=str(argtypes),
        signature=signature,
    )

    if return_text:
        return text
    print(args_list)

    return code_to_function(text, fname, args_size, return_size,
                            size_same_as_output)
def compile_function(equations, args, parms, max_order, return_text=False):
    """
    :param equations:
    :param args:
    :param parms:
    :param max_order:
    :param return_function:
    :return:
    """

    var_order = args

    sols = []
    for eq in equations:
        ndt = DerivativesTree(eq, ref_var_list=var_order)
        ndt.compute_nth_order_children(max_order)
        sols.append(ndt)

    dyn_subs_dict = dict()
    for i, v in enumerate(args):
        dyn_subs_dict[v] = 'x_' + str(i)

    for i, p in enumerate(parms):
        dyn_subs_dict[p] = 'p_' + str(i)

    preamble_l = [
        '    x_{i} = x[{i}]   # {v}'.format(i=i, v=v)
        for i, v in enumerate(args)
    ]
    preamble_l += [
        '    p_{i} = p[{i}]    # {p}'.format(i=i, p=p)
        for i, p in enumerate(parms)
    ]
    preamble = str.join('\n', preamble_l)

    dyn_printer = DicPrinter(dyn_subs_dict)

    txt = """def dynamic_function(x, p):
#
#
#
    import numpy as np
    from numpy import exp, log
    from numpy import sin, cos, tan
    from numpy import arcsin as asin
    from numpy import arccos as acos
    from numpy import arctan as atan
    from numpy import sinh, cosh, tanh
    from numpy import pi

{preamble}

    f = []

    residual = np.zeros({neq},dtype=np.float64);
"""
    gs = str.join(', ', [('f' + str(i)) for i in range(1, (max_order + 1))])
    txt = txt.format(gs=gs,
                     fname='noname',
                     neq=len(equations),
                     preamble=preamble)

    for i in range(len(sols)):
        ndt = sols[i]
        eq = ndt.expr
        rhs = dyn_printer.doprint_numpy(eq)
        txt += '    residual[{0}] = {1}\n'.format(i, rhs)

    txt += '    f.append(residual)\n'

    for current_order in range(1, (max_order + 1)):
        if current_order == 1:
            matrix_name = "Jacobian"
        elif current_order == 2:
            matrix_name = "Hessian"
        else:
            matrix_name = "{0}_th order".format(current_order)

        txt += """
#
# {matrix_name} matrix
#

""".format(orderr=current_order + 1, matrix_name=matrix_name)
        if current_order == 2:
            txt.format(matrix_name="Hessian")
        elif current_order == 1:
            txt.format(matrix_name="Jacobian")

        #nnzd = self.NNZDerivatives(current_order)

        n_cols = (len(var_order), ) * current_order
        n_cols = ','.join([str(s) for s in n_cols])
        txt += "    f{order} = np.zeros( ({n_eq}, {n_cols}), dtype=np.float64 )\n".format(
            order=current_order, n_eq=len(equations), n_cols=n_cols)
        for n in range(len(sols)):
            ndt = sols[n]
            l = ndt.list_nth_order_children(current_order)
            for nd in l:
                # here we compute indices where we write the derivatives
                indices = nd.compute_index_set(var_order)
                rhs = dyn_printer.doprint_numpy(nd.expr)
                i0 = indices[0]
                i_col_s = ','.join([str(nn) for nn in i0])
                indices.remove(i0)

                i_col_s_ref = i_col_s
                txt += '    f{order}[{i_eq},{i_col}] = {value}\n'.format(
                    order=current_order, i_eq=n, i_col=i_col_s, value=rhs)
                for ind in indices:
                    i += 1
                    i_col_s = ','.join([str(nn) for nn in ind])
                    txt += '    f{order}[{i_eq},{i_col}] = f{order}[{i_eq},{i_col_ref}] \n'.format(
                        order=current_order,
                        i_eq=n,
                        i_col=i_col_s,
                        i_col_ref=i_col_s_ref)

        txt += "    f.append(f{order})\n".format(order=current_order)
    txt += "    return f\n"
    txt = txt.replace('^', '**')

    if return_text:
        return txt
    else:
        return code_to_function(txt, 'dynamic_function')
def compile_multiargument_function(equations,
                                   args_list,
                                   args_names,
                                   parms,
                                   fname='anonymous_function',
                                   diff=True,
                                   return_text=False,
                                   use_numexpr=False,
                                   order='columns'):
    """
    :param equations: list of sympy expressions
    :param args_list: list of lists of symbols (e.g. [[a_1,a_2], [b_1,b_2]])
    :param args_names: list of strings (['a','b']
    :param parms: list of symbols to be used as parameters
    :param fname: name of the python function to be generated
    :param diff: include symbolic derivates in generated function
    :param vectorize: arguments are vectorized (not parameters)
    :param return_function: a python function f(a,b,p) where p is a vector of parameters and a, b, arrays
    :return:
    """

    if order == 'rows':
        raise (Exception('not implemented'))

    template = '{0}[{1}]'

    declarations = ""
    sub_list = {}

    for i, args in enumerate(args_list):
        vec_name = args_names[i]
        for j, v in enumerate(args):
            sub_list[v] = template.format(vec_name, j)
            # declarations += "    {0}_{1} = {0}[{1}]\n".format(vec_name, j)

    for i, p in enumerate(parms):
        sub_list[p] = '{0}[{1}]'.format('p', i)
        # declarations += "    {0}_{1} = {0}[{1}]\n".format('p', i)

    import sympy
    # TODO: construct a common list of symbol that should be understood everywhere
    sub_list[sympy.Symbol('inf')] = 'inf'

    text = '''
from numpy import zeros
from numpy import exp, log
from numpy import sin, cos, tan
from numpy import arcsin as asin
from numpy import arccos as acos
from numpy import arctan as atan
from numpy import sinh, cosh, tanh
from numpy import pi
from numpy import inf

def {fname}({args_names}, {param_names}, val):

    val = zeros({n_equations})
{content}

    return val

    '''

    from dolo.compiler.common import DicPrinter

    dp = DicPrinter(sub_list)

    def write_eqs(eq_l, outname='val'):
        eq_block = ''
        for i, eq in enumerate(eq_l):
            eq_string = dp.doprint_numpy(eq)
            eq_block += '    val[{0}] = {1}\n'.format(i, eq_string)
        return eq_block

    content = write_eqs(equations)

    return_names = 'val'
    text = text.format(fname=fname,
                       n_equations=len(equations),
                       declarations=declarations,
                       var=args_names[0],
                       content=content,
                       return_names=return_names,
                       args_names=str.join(', ', args_names),
                       param_names='p')

    if return_text:
        return text

    args_size = [len(e) for e in args_list] + [len(parms)]
    return_size = len(equations)

    return code_to_function(text, fname, args_size, return_size)