I can get close with sympy's integration with theano:from sympy.printing.theanocode import theano_functionf = theano_function(xs + ks, syms)def my_odes(x, k): return np.array(f(*np.concatenate([x,k]))))这将编译每个表达式,但是对输入和输出的所有这种打包和拆包都会使它变慢. theano_function返回的函数接受numpy数组作为参数,但是每个符号需要一个数组,而不是每个符号需要一个元素.对于functify和ufunctify,这也是相同的行为.我不需要广播行为;我需要它来将数组的每个元素解释为不同的符号.This compiles each expression, but all this packing and unpacking of the inputs and outputs slows it back down. The function returned by theano_function accepts numpy arrays as arguments, but it needs one array for each symbol rather than one element for each symbol. This is the same behavior for functify and ufunctify as well. I don't need the broadcast behavior; I need it to interpret each element of the array as a different symbol. 尝试3:DeferredVector如果使用DeferredVector,我可以创建一个接受numpy数组的函数,但是我不能将其编译为C代码或返回numpy数组而不自行打包.If I use DeferredVector I can make a function that accepts numpy arrays, but I can't compile it to C code or return a numpy array without packaging it myself.import numpy as npimport sympy as spfrom sympy import DeferredVectorx = sp.DeferredVector('x')k = sp.DeferredVector('k')deferred_syms = [s.subs({'x1':x[0], 'x2':x[1], 'k1':k[0], 'k2':k[1]}) for s in syms]f = [lambdify([x,k], s) for s in deferred_syms]def my_odes(x, k): return np.array([f_i(x, k) for f_i in f])使用DeferredVector我不需要解压缩输入,但仍然需要解压缩输出.另外,我可以使用lambdify,但是ufuncify和theano_function版本会消失,因此不会生成快速的C代码.Using DeferredVector I do not need to unpack the inputs, but I still need to pack the outputs. Also, I can use lambdify, but the ufuncify and theano_function versions perish, so no fast C code is generated.from sympy.utilities.autowrap import ufuncifyf = [ufuncify([x,k], s) for s in deferred_syms] # errorfrom sympy.printing.theanocode import theano_functionf = theano_function([x,k], deferred_syms) # error推荐答案您可以使用sympy函数 lambdify .例如,You can use the sympy function lambdify. For example,from sympy import symbols, lambdifyfrom sympy.parsing.sympy_parser import parse_exprimport numpy as npxs = symbols('x1 x2')ks = symbols('k1 k2')strs = ['-k1 * x1**2 + k2 * x2', 'k1 * x1**2 - k2 * x2']syms = [parse_expr(item) for item in strs]# Convert each expression in syms to a function with signature f(x1, x2, k1, k2):funcs = [lambdify(xs + ks, f) for f in syms]# This is not exactly the same as the `my_odes` in the question.# `t` is included so this can be used with `scipy.integrate.odeint`.# The value returned by `sym.subs` is wrapped in a call to `float`# to ensure that the function returns python floats and not sympy Floats.def my_odes(x, t, k): all_dict = dict(zip(xs, x)) all_dict.update(dict(zip(ks, k))) return np.array([float(sym.subs(all_dict)) for sym in syms])def lambdified_odes(x, t, k): x1, x2 = x k1, k2 = k xdot = [f(x1, x2, k1, k2) for f in funcs] return xdotif __name__ == "__main__": from scipy.integrate import odeint k1 = 0.5 k2 = 1.0 init = [1.0, 0.0] t = np.linspace(0, 1, 6) sola = odeint(lambdified_odes, init, t, args=((k1, k2),)) solb = odeint(my_odes, init, t, args=((k1, k2),)) print(np.allclose(sola, solb))运行脚本时会打印 True.True is printed when the script is run.速度更快(请注意计时结果单位的变化):It is much faster (note the change in units of the timing results):In [79]: t = np.linspace(0, 10, 1001)In [80]: %timeit sol = odeint(my_odes, init, t, args=((k1, k2),))1 loops, best of 3: 239 ms per loopIn [81]: %timeit sol = odeint(lambdified_odes, init, t, args=((k1, k2),))1000 loops, best of 3: 610 µs per loop 这篇关于将sympy表达式转换为numpy数组的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-18 15:03
查看更多