def compile_function_matlab(equations, symbols, arg_names, output_names=None, funname='anonymous'): from function_compiler_ast import std_date_symbol from function_compiler_ast import StandardizeDates from collections import OrderedDict table = OrderedDict() aa = arg_names # if output_names is not None: # aa = arg_names + [output_names] for a in aa: symbol_group = a[0] date = a[1] an = a[2] for b in symbols[symbol_group]: index = symbols[symbol_group].index(b) table[(b,date)] = (an, index) table_symbols = { k: (std_date_symbol(*k)) for k in table.keys() } code_preamble = "" for k,v in table.iteritems(): std_name = table_symbols[k] if v[0] != 'p': code_preamble += "{} = {}(:,{});\n".format(std_name, v[0], v[1]+1) else: code_preamble += "{} = {}({});\n".format(std_name, v[0], v[1]+1) if output_names: out_group, out_time, out_s = output_names else: out_s = 'out' expressions = [] code_expr = "" import sympy for i,eq in enumerate(equations): expr = str_to_expr(eq) sd = StandardizeDates(symbols, arg_names) sexpr = sd.visit(expr) expressions.append(sexpr) eq_string = (print_matlab(sexpr)) if output_names is None: code_expr += "out(:,{}) = {} ;\n".format(i+1, eq_string) else: out_symbol = symbols[out_group][i] out_name = std_date_symbol(out_symbol, out_time) code_expr += "{} = {} ;\n".format(out_name, eq_string) code_expr += "{}(:,{}) = {} ;\n".format(out_s,i+1, out_name) ## temporary code to differentiate equations using sympy if output_names: # solve triangular system sympy_names = [sympy.Symbol(e) for e in symbols[out_group]] eq_dict = OrderedDict() for i,name in enumerate(sympy_names): eq = sympy.sympify(codegen.to_source(expressions[i])) eq_dict[name] = eq.subs(eq_dict) sympy_equations = eq_dict.values() else: sympy_equations = [sympy.sympify(codegen.to_source(expr)) for expr in expressions] all_derivatives = OrderedDict() for agn in arg_names: sym_group = agn[0] date = agn[1] short_sym_group = agn[2] sym_names = [std_date_symbol(s, date) for s in symbols[sym_group]] dvals = [] for eq in sympy_equations: deq = [] for s in sym_names: sym = sympy.Symbol(s) ddif = (eq.diff(sym)) deq.append(ast.parse(str(ddif)).body[0]) dvals.append(deq) all_derivatives[short_sym_group] = dvals ## end of temporary code code_dexpr = "" for k,derivs in all_derivatives.iteritems(): code_dexpr += '\n%derivatives w.r.t {}\n'.format(k) assign_name = "d_{}".format(k) code_dexpr += '{} = zeros(N,{},{});\n'.format(assign_name, len(derivs), len(derivs[0])) for i in range(len(derivs)): for j in range(len(derivs[0])): eq = derivs[i][j] ss = print_matlab(eq) if ss != '0': code_dexpr += "{}(:,{},{}) = {};\n".format(assign_name, i+1, j+1, ss) code_dexpr += '\n' code = """\ function [{out_s}, {dout_s}] = {funname}({args_list}) %% preamble {preamble} N = size({first_arg},1); out = zeros(N,{n_out}); %% equations {equations} %% derivatives if nargout > 1 {dequations} end end """.format( out_s = out_s, dout_s = str.join(', ', ["d_{}".format(e[2]) for e in arg_names]), preamble = code_preamble, funname = funname, args_list = str.join(', ', [e[2] for e in arg_names]), n_out = len(equations), first_arg = arg_names[0][2], equations = code_expr, dequations = code_dexpr ) return code
def compile_function_matlab(equations, symbols, arg_names, output_names=None, funname='anonymous'): from function_compiler_ast import std_date_symbol from function_compiler_ast import StandardizeDates from collections import OrderedDict table = OrderedDict() aa = arg_names # if output_names is not None: # aa = arg_names + [output_names] for a in aa: symbol_group = a[0] date = a[1] an = a[2] for b in symbols[symbol_group]: index = symbols[symbol_group].index(b) table[(b, date)] = (an, index) table_symbols = {k: (std_date_symbol(*k)) for k in table.keys()} code_preamble = "" for k, v in table.iteritems(): std_name = table_symbols[k] if v[0] != 'p': code_preamble += "{} = {}(:,{});\n".format(std_name, v[0], v[1] + 1) else: code_preamble += "{} = {}({});\n".format(std_name, v[0], v[1] + 1) if output_names: out_group, out_time, out_s = output_names else: out_s = 'out' code_expr = "" for i, eq in enumerate(equations): expr = str_to_expr(eq) sd = StandardizeDates(symbols, arg_names) sexpr = sd.visit(expr) eq_string = (print_matlab(sexpr)) if output_names is None: code_expr += "out(:,{}) = {} ;\n".format(i + 1, eq_string) else: out_symbol = symbols[out_group][i] out_name = std_date_symbol(out_symbol, out_time) code_expr += "{} = {} ;\n".format(out_name, eq_string) code_expr += "{}(:,{}) = {} ;\n".format(out_s, i + 1, out_name) code = """\ function [{out_s}] = {funname}({args_list}) {preamble} N = size({first_arg},1); out = zeros(N,{n_out}); {equations} end """.format(out_s=out_s, preamble=code_preamble, funname=funname, args_list=str.join(', ', [e[2] for e in arg_names]), n_out=len(equations), first_arg=arg_names[0][2], equations=code_expr) return code
def compile_higher_order_function(eqs, syms, params, order=2, funname='anonymous', return_code=False, compile=False): '''From a list of equations and variables, define a multivariate functions with higher order derivatives.''' from function_compiler_ast import StandardizeDatesSimple, std_date_symbol all_vars = syms + [(p,0) for p in params] sds = StandardizeDatesSimple(all_vars) if isinstance(eqs[0], str): # elif not isinstance(eqs[0], sympy.Basic): # assume we have ASTs eqs = [ast.parse(eq).body[0] for eq in eqs] eqs_std = [sds.visit(eq) for eq in eqs] eqs_sym = [ast_to_sympy(eq) for eq in eqs_std] else: eqs_sym = eqs symsd = [std_date_symbol(a,b) for a,b in syms] paramsd = [std_date_symbol(a,0) for a in params] D = higher_order_diff(eqs_sym, symsd, order=order) txt = """def {funname}(x, p, order=1): import numpy from numpy import log, exp, tan """.format(funname=funname) for i in range(len(syms)): txt += " {} = x[{}]\n".format(symsd[i], i) txt += "\n" for i in range(len(params)): txt += " {} = p[{}]\n".format(paramsd[i], i) txt += "\n out = numpy.zeros({})".format(len(eqs)) for i in range(len(eqs)): txt += "\n out[{}] = {}".format(i, D[0][i]) txt += """ if order == 0: return out """ if order >= 1: # Jacobian txt += " out_1 = numpy.zeros(({},{}))\n".format(len(eqs), len(syms)) for i in range(len(eqs)): for j in range(len(syms)): val = D[1][i,j] if val != 0: txt += " out_1[{},{}] = {}\n".format(i,j,D[1][i,j]) txt += """ if order == 1: return [out, out_1] """ if order >= 2: # Hessian txt += " out_2 = numpy.zeros(({},{},{}))\n".format(len(eqs), len(syms), len(syms)) for n in range(len(eqs)): for i in range(len(syms)): for j in range(len(syms)): val = D[2][n,i,j] if val is not None: if val != 0: txt += " out_2[{},{},{}] = {}\n".format(n,i,j,D[2][n,i,j]) else: i1, j1 = sorted( (i,j) ) if D[2][n,i1,j1] != 0: txt += " out_2[{},{},{}] = out_2[{},{},{}]\n".format(n,i,j,n,i1,j1) txt += """ if order == 2: return [out, out_1, out_2] """ if order >= 3: # Hessian txt += " out_3 = numpy.zeros(({},{},{},{}))\n".format(len(eqs), len(syms), len(syms), len(syms)) for n in range(len(eqs)): for i in range(len(syms)): for j in range(len(syms)): for k in range(len(syms)): val = D[3][n,i,j,k] if val is not None: if val != 0: txt += " out_3[{},{},{},{}] = {}\n".format(n,i,j,k,D[3][n,i,j,k]) else: i1, j1, k1 = sorted( (i,j,k) ) if D[3][n,i1,j1,k1] != 0: txt += " out_3[{},{},{},{}] = out_3[{},{},{},{}]\n".format(n,i,j,k,n,i1,j1,k1) txt += """ if order == 3: return [out, out_1, out_2, out_3] """ if return_code: return txt else: d = {} d['division'] = division exec(txt, d) fun = d[funname] if compile: raise Exception("Not implemented.") return fun
def compile_function_matlab(equations, symbols, arg_names, output_names=None, funname='anonymous'): from function_compiler_ast import std_date_symbol from function_compiler_ast import StandardizeDates from collections import OrderedDict table = OrderedDict() aa = arg_names # if output_names is not None: # aa = arg_names + [output_names] for a in aa: symbol_group = a[0] date = a[1] an = a[2] for b in symbols[symbol_group]: index = symbols[symbol_group].index(b) table[(b,date)] = (an, index) table_symbols = { k: (std_date_symbol(*k)) for k in table.keys() } code_preamble = "" for k,v in table.iteritems(): std_name = table_symbols[k] if v[0] != 'p': code_preamble += "{} = {}(:,{});\n".format(std_name, v[0], v[1]+1) else: code_preamble += "{} = {}({});\n".format(std_name, v[0], v[1]+1) if output_names: out_group, out_time, out_s = output_names else: out_s = 'out' code_expr = "" for i,eq in enumerate(equations): expr = str_to_expr(eq) sd = StandardizeDates(symbols, arg_names) sexpr = sd.visit(expr) eq_string = (print_matlab(sexpr)) if output_names is None: code_expr += "out(:,{}) = {} ;\n".format(i+1, eq_string) else: out_symbol = symbols[out_group][i] out_name = std_date_symbol(out_symbol, out_time) code_expr += "{} = {} ;\n".format(out_name, eq_string) code_expr += "{}(:,{}) = {} ;\n".format(out_s,i+1, out_name) code = """\ function [{out_s}] = {funname}({args_list}) {preamble} N = size({first_arg},1); out = zeros(N,{n_out}); {equations} end """.format( out_s = out_s, preamble = code_preamble, funname = funname, args_list = str.join(', ', [e[2] for e in arg_names]), n_out = len(equations), first_arg = arg_names[0][2], equations = code_expr ) return code