Sympy与Cython在尝试寻找根时产生奇异矩阵

时间:2018-01-22 20:28:50

标签: python cython sympy

我正在尝试使用Sympy来解决一组非线性方程。这是我的代码,改变了一些数字,只有一个输入值(实际代码通过170,000行数据):

import sympy as sp

K0 = 2.00*10**-4
x2, y2 = sp.symbols('x2, y2')
x0 = 500
y0 = 500
R1 = ((x2 - x0)**2 + (y2 - y0)**2)**0.5
R2 = K0 * R1
H2 = sp.atan(R2 * (x2 - x0)/R1)
V2 = sp.atan(R2 * (y2 - y0)/R1)
x, y = sp.symbols('x, y')
x0 = 1.0
y0 = 2.0
x = R1 * H2
y = R1 * V2
dat = sp.nsolve([x - x0, y - y0], [x2, y2], [512, 512]) # This line is the problem
print "dat = %f, %f" % (dat[0], dat[1])

纯粹使用Python,代码运行良好并产生良好的输出 - 但它非常慢。为了加快这个过程,我使用Cython来编译一个.pyx文件,其中包含完全相同的代码(在定义中为def test()),但在运行期间,我遇到了:

  File "test.py", line 3, in <module>
    demo.test()
  File "demo.pyx", line 17, in demo.test
    dat = sp.nsolve([x - x0, y - y0], [x2, y2], [512, 512])
  File "C:\...\site-packages\sympy\utilities\decorator.py", line 91, in func_wrapper
    return func(*args, **kwargs)
  File "C:\...\site-packages\sympy\solvers\solvers.py", line 2847, in nsolve
    x = findroot(f, x0, J=J, **kwargs)
  File "C:\...\site-packages\mpmath\calculus\optimization.py", line 960, in findroot
    for x, error in iterations:
  File "C:\...\site-packages\mpmath\calculus\optimization.py", line 658, in __iter__
    s = self.ctx.lu_solve(Jx, fxn)
  File "C:\...\site-packages\mpmath\matrices\linalg.py", line 227, in lu_solve
    A, p = ctx.LU_decomp(A)
  File "C:\...\site-packages\mpmath\matrices\linalg.py", line 137, in LU_decomp
    raise ZeroDivisionError('matrix is numerically singular')
ZeroDivisionError: matrix is numerically singular

我已将问题缩小到x - x0y - y0部分。由于某种原因,编译后的代码无法在它们不等于0时找到根。可以使用Cython将nsolve简单地转换为C吗?我有什么遗失的东西与Cython有关吗?

1 个答案:

答案 0 :(得分:2)

您可以将sympy.lambdify与例如symengine.Lambdify一起使用SciPy的求解器。如果速度不够快,可以使用>>> from pyneqsys.symbolic import SymbolicSys >>> neqsys = SymbolicSys([x2, y2], [x - x0, y - y0]) >>> neqsys.solve([512, 512]) Out[4]: (array([ 547.28609349, 594.58064617]), fjac: array([[ 0.91320338, 0.4075041 ], [-0.4075041 , 0.91320338]]) fun: array([ -1.37667655e-13, 1.52011737e-12]) message: 'The solution converged.' nfev: 17 njev: 2 qtf: array([ 1.55620322e-10, 4.63225371e-10]) r: array([ 0.02751454, 0.023682 , 0.03261983]) status: 1 success: True x: array([ 547.28609349, 594.58064617]))

获得正确的函数签名,并导出雅可比行列式,需要您跳过箍。如果你想使用一个库,我写了pyneqsys

pyneqsys

如果那些17万个解决方案涉及逐渐改变参数symengine.Lambdify可以利用它(通过在解决方案之间传播解决方案)。它还可以通过设置环境变量SYM_BACKEND=sympysymengine

自动使用 <rollingStyle value="Size" />