Sympy求解二元非线性方程组长时间无响应问题咨询
问题核心诱因
- 工具定位不匹配:SymPy的
solve()函数的设计目标是求解方程组的全量解析闭式解,而非数值近似解。你构造的方程组包含反正切、余弦、平方根三类超越项,属于不存在初等函数形式闭式解的超越方程组,SymPy会持续在符号化简、根分支枚举的逻辑中循环,永远无法走到正常终止的分支,和Atom、Colab的运行环境没有关系。 - 浮点数参数放大求解冗余:你代码中传入的角度值
0.523599、2.0944是浮点近似值,SymPy在做符号运算时会尝试将浮点数转换为有理分数做精确推导,浮点精度带来的微小误差会生成大量无意义的化简分支,进一步拖慢运行速度,直接导致进程长时间无响应。 - 不存在“复杂度过高”的问题:这个方程组的数值求解复杂度极低,因此面向数值求根的
scipy.fsolve可以极短时间返回结果,但对追求解析解的SymPy.solve()而言,不存在解析解的问题本身没有终止条件,卡进程是必然结果,和方程组数值计算的复杂度无关。
SymPy侧正确求解方式
如果需要使用SymPy求解该问题,不要调用面向解析解的solve(),改用SymPy自带的数值求根接口nsolve(),同时做三个优化减少冗余计算:
- 声明符号变量为实数域变量,缩小求解范围
- 用精确的符号常量代替近似浮点数(比如
sym.pi/6对应30度、2*sym.pi/3对应120度,和你写的浮点角度值完全等价) - 传入合理的迭代初始值(可以参考fsolve返回的根作为初值)
修改后的可运行代码如下:
import sympy as sym x, y = sym.symbols('x,y', real=True) dmin = 70 # actuator最小值 dmax = 140 # actuator最大值 l3 = 10 l4 = 10 Amin = sym.pi/6 # 对应原代码0.523599弧度即30度,用精确符号值 Amax = 2*sym.pi/3 # 对应原代码2.0944弧度即120度,用精确符号值 cos1 = sym.cos(Amin - sym.atan(l4/x) - sym.atan(l3/y)) cos2 = sym.cos(Amax - sym.atan(l4/x) - sym.atan(l3/y)) a2 = x**2 + l4**2 b2 = y**2 + l3**2 f = a2 + b2 - 2*sym.sqrt(a2)*sym.sqrt(b2)*cos1 - dmin**2 g = a2 + b2 - 2*sym.sqrt(a2)*sym.sqrt(b2)*cos2 - dmax**2 # 传入正实根初值(40,40)做数值迭代 print(sym.nsolve((f, g), (x, y), (40, 40)))
上述代码可以在秒级返回数值解,精度和scipy的fsolve结果一致。
内容的提问来源于stack exchange,提问作者Fadi EID
相关产品推荐
相关产品推荐

