我正在尝试使用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 - x0
和y - y0
部分。由于某种原因,编译后的代码无法在它们不等于0时找到根。可以使用Cython将nsolve简单地转换为C吗?我有什么遗失的东西与Cython有关吗?
答案 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" />