我正在尝试使用 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-packagessympyutilitiesdecorator.py", line 91, in func_wrapper
return func(*args, **kwargs)
File "C:...site-packagessympysolverssolvers.py", line 2847, in nsolve
x = findroot(f, x0, J=J, **kwargs)
File "C:...site-packagesmpmathcalculusoptimization.py", line 960, in findroot
for x, error in iterations:
File "C:...site-packagesmpmathcalculusoptimization.py", line 658, in __iter__
s = self.ctx.lu_solve(Jx, fxn)
File "C:...site-packagesmpmathmatriceslinalg.py", line 227, in lu_solve
A, p = ctx.LU_decomp(A)
File "C:...site-packagesmpmathmatriceslinalg.py", line 137, in LU_decomp
raise ZeroDivisionError('matrix is numerically singular')
ZeroDivisionError: matrix is numerically singular
我已经将问题缩小到x - x0
和y - y0
部分。出于某种原因,编译的代码无法处理在根不等于 0 时查找根。nsolve 不能简单地使用 Cython 转换为 C 吗?我错过了与Cython有关的东西吗?
sympy.lambdify
与SciPy的求解器一起使用。如果这还不够快,您可以使用 symengine.Lambdify
.
获得正确的函数签名,并派生雅可比函数,需要你跳过箍。如果你想使用一个库,我已经写了pyneqsys:
>>> 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]))
如果这 170 000 个求解涉及逐渐更改参数pyneqsys
可以利用它(通过将解作为求解之间的猜测传播(。它还可以通过设置环境变量来自动使用symengine.Lambdify
SYM_BACKEND=sympysymengine