为什么SymPy无法解复杂系数的二次方程
SymPy可以轻松地解决系数比较小的二次方程。例如:
from pprint import pprint
from sympy import *
x,b,f,Lb,z = symbols('x b f Lb z')
eq31 = Eq((x*b + f)**2, 4*Lb**2*z**2*(1 - x**2))
pprint(eq31)
sol = solve(eq31, x)
pprint(sol)
但是如果系数稍微大一点,它就解决不了:
from pprint import pprint
from sympy import *
c3,b,f,Lb,z = symbols('c3 b f Lb z')
phi,Lf,r = symbols('phi Lf r')
eq23 = Eq(
(
c3 * (2*Lb*b - 2*Lb*f + 2*Lb*r*cos(phi + pi/6))
+ (Lb**2 - Lf**2 + b**2 - 2*b*f + 2*b*r*cos(phi + pi/6) + f**2 - 2*f*r*cos(phi + pi/6) + r**2 + z**2)
)**2,
4*Lb**2*z**2*(1 - c3**2)
)
pprint(eq23)
print("\n\nSolve (23) for c3:")
solutions_23 = solve(eq23, c3)
pprint(solutions_23)
这是为什么呢?
2 个回答
2
因为支持符号解法,所以你可以先解决一个通用的二次方程,然后把你具体的系数代进去:
>>> eq = eq23.lhs-eq23.rhs
>>> a,b,c = Poly(eq,c3).all_coeffs()
>>> var('A:C')
(A, B, C)
>>> ans=[i.xreplace({A:a,B:b,C:c}) for i in solve(A*x**2 + B*x + C,x)]
>>> print filldedent(ans)
...
不过如果你关闭简化和检查的功能,其实也能得到同样的结果:
>>> ans=solve(eq23,c3,simplify=False,check=False)
(这些功能是调用解法时最耗费资源的部分。)
2
这并不是Sympy特有的问题,其他一些程序,比如Maple或Mathematica,也会遇到同样的麻烦。当我们要解一个方程时,solve
这个函数需要根据对变量和方程结构的假设来选择合适的解法策略(你可以参考一下Sympy的解法器)。这些选择通常是基于经验的,有时候会出错(所以可能找不到解,或者先尝试了错误的策略)。而且,对变量的假设往往太宽泛了(比如,假设是复数而不是实数)。
因此,对于复杂的方程,用户通常需要自己提供解法策略。针对你的例子,你可以使用:
sol23 = roots(eq23.lhs - eq23.rhs, c3)