Python Sympy模块NoConversion:收敛到根失败;请尝试n<15或MaxSteps>50

2022-04-06 00:00:00 python sympy

问题描述

我在使用Sympy解决问题时遇到了一个问题 以下是我的代码:

from math import pi, hypot
from sympy import solve, solveset, sqrt, Symbol
one_x=-0.08
one_y=1.28
second_x=0
second_y=0
second_r=7
one_r=7.3
slopes=-16.0000000000  (maybe more trailing 0s)
intercepts=0.0
x=Symbol('x')
solveset(sqrt((x-second_x)**2+(slope*x+intercept-second_y)**2)+second_r-one_r-sqrt((x-one_x)**2+(slope*x+intercept-one_y)**2),x)
这只是我的代码的一部分,但它引发了很多错误 但是,我用它的值替换了所有变量,如

x=Symbol('x')

solveset(sqrt((x)**2+((-16)*x)**2)+7-7.3-sqrt((x+0.08)**2+((-16)*x-1.28)**2),x)

它运行得很好,我可以得到输出{-0.0493567429232771}

我想这是因为坡度的类型(-16比-16.000000),我真的很想知道为什么浮点数公式不能计算,以及如何修正它(因为我需要更精确,所以我不能只忽略点后的数字) 非常感谢!


解决方案

SymPy+代数方程+浮点数=>故障。浮点数学does not work like normal math,而SymPy是为后者设计的。像16(整数)和16.0(浮点数)这样的小东西在使用SymPy解等式时会有很大的不同:理想情况下,您应该没有浮点数,而是创建精确的有理数,如下所示。

from sympy import S 
one_x = S('-0.08')
但是,您有浮点数据,并且正在寻找浮点解决方案。这使得SymPy成为不适合这项工作的工具。SymPy用于对符号进行数学运算,而不是用于处理浮点数。正确的解决方案是使用来自SciPy的适当解决方案,例如brentq。它接受括号间隔作为输入(其中函数的两端有不同的符号)。例如:

from scipy.optimize import brentq
eq = lambda x: np.sqrt((x-second_x)**2 + (slope*x+intercept-second_y)**2) + second_r - one_r - np.sqrt((x-one_x)**2 + (slope*x + intercept - one_y)**2)
brentq(eq, -10, 10)   # returns -0.049356742923277075

如果您坚持使用SymPy,这意味着您的方程式将外包到mpmath库中,后者在数值求根和优化方面受到更多限制。要获得与其方法收敛的解决方案,您需要一个非常好的起点:显然,one_x/2就是这样一个起点。

from sympy import sqrt, Symbol, nsolve
# ... as in your code
nsolve(sqrt((x-second_x)**2+(slope*x+intercept-second_y)**2)+second_r-one_r-sqrt((x-one_x)**2+(slope*x+intercept-one_y)**2), one_x/2)

返回-0.0493567429232771

通过使用用于符号解的sympy.solveset,您不仅剥夺了您自己使用SciPy强大的数字解算器的机会,而且还失去了为sympy.nsolve提供的数字搜索设置一个良好的起始值的机会。因此,在这个数值上棘手的问题上缺乏收敛。顺便说一句,这就是它在数值上棘手的原因:该函数在大多数情况下几乎是恒定的,只有一个快速变化。

相关文章