Python 符号矩阵的辛慢代换

Python 符号矩阵的辛慢代换,python,numpy,sympy,substitution,differential-equations,Python,Numpy,Sympy,Substitution,Differential Equations,我正在和sympy一起研究一个符号雅可比矩阵J,大小QxQ。该矩阵的每个系数包含Q符号,从f[0]到f[Q-1]。 我想做的是用已知值g[0]到g[Q-1](不再是符号)替换J的每个系数中的每个符号。我发现最快的方法如下: for k in range(Q): J = J.subs(f[k], g[k]) 然而,我发现这个“基本”操作非常长!例如,使用此MCVE: import sympy import numpy as np import time Q = 17 f0, f1, f

我正在和sympy一起研究一个符号雅可比矩阵
J
,大小
QxQ
。该矩阵的每个系数包含
Q
符号,从
f[0]
f[Q-1]
。 我想做的是用已知值
g[0]
g[Q-1]
(不再是符号)替换
J
的每个系数中的每个符号。我发现最快的方法如下:

for k in range(Q):
    J = J.subs(f[k], g[k])
然而,我发现这个“基本”操作非常长!例如,使用此MCVE:

import sympy
import numpy as np
import time

Q = 17
f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16 = \
    sympy.symbols("f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 f16")
f = [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16]
e = np.array([0., 1., 0., -1., 0., 1., -1., -1., 1.,
              2., -2., -2., 2., 3., 0., -3., 0.])
u = np.sum(f * e) / np.sum(f)
function = e * np.sum(f) * (1. + u * e + (u * e)**2 - u * u)
F = sympy.Matrix(function)
g = e * (1. + 0.2 * e + (0.2 * e)**2)

start_time = time.time()
J = F.jacobian(f)
print("--- %s seconds ---" % (time.time() - start_time))

start_time = time.time()
for k in range(Q):
    J = J.subs(f[k], g[k])
print("--- %s seconds ---" % (time.time() - start_time))
在我的计算机上,替换大约需要5秒,而雅可比矩阵的计算只需要0.6秒。在另一个(较长)代码上,替换需要360秒,Q=37(而雅可比计算需要20秒)

此外,当我查看正在运行的进程时,我可以看到Python进程有时在矩阵替换期间停止工作

  • 有人知道这可能来自哪里吗
  • 有没有办法让这个操作更快
  • 你可能想试试看。它实现了一个比sympy更快的并行函数

    以下版本实现了3.88的加速比!现在的换人时间不如第二次

    import numpy as np
    import sympy as sp
    import theano as th
    import time
    
    
    def main_sympy():
        start_time = time.time()
    
        Q = 17
        f = sp.symbols(('f{} ' * Q).format(*range(Q)))
    
        e = np.array([0., 1., 0., -1., 0., 1., -1., -1., 1.,
                      2., -2., -2., 2., 3., 0., -3., 0.])
        u = np.sum(f * e) / np.sum(f)
        ue = u * e
        phi = e * np.sum(f) * (1. + ue + ue*ue - u*u)
        F = sp.Matrix(phi)
        J = F.jacobian(f)
    
        g = e * (1. + 0.2*e + (0.2*e)**2)
    
        for k in range(Q):
            J = J.subs(f[k], g[k])
    
        print("--- %s seconds ---" % (time.time() - start_time))
        return J
    
    
    def main_theano():
        start_time = time.time()
    
        Q = 17
        f = th.tensor.dvector('f')
    
        e = np.array([0., 1., 0., -1., 0., 1., -1., -1., 1., 2.,
                      -2., -2., 2., 3., 0., -3., 0.])
        u = (f * e).sum() / f.sum()
        ue = u * e
        phi = e * f.sum() * (1. + ue + ue*ue - u*u)
        jacobi = th.gradient.jacobian(phi, f)
        J = th.function([f], jacobi)
    
        g = e * (1. + 0.2*e + (0.2*e)**2)
        Jg = J(g)  # evaluate expression
    
        print("--- %s seconds ---" % (time.time() - start_time))
        return Jg
    
    
    J0 = np.array(main_sympy().tolist(), dtype='float64')
    J1 = main_theano()
    
    print(np.allclose(J0, J1))  # compare results
    

    欢迎这样做,不要忘了带:)关于这个问题,我怀疑雅可比矩阵可能不会被简化,导致大量重复变量/计算。