fsolve总是返回初始猜测

5 投票
2 回答
5241 浏览
提问于 2025-04-17 08:38

我第一次使用scipy的optimize.fsolve函数来寻找方程的根。问题是,无论我用什么数字作为初始猜测值,得到的答案几乎都是这个数字(精确到大约8位小数)。当我设置full_output=True时,得到的exitflag是'1',这应该意味着'解已经收敛',根据我的理解,这应该表示输出确实是方程的一个根。

我知道方程有有限个不同的根(它们是分开的),因为我在画图时可以看到这些根。此外,当我输入的起始点在一个应该返回未定义值的范围内(比如除以零或负数的平方根)时,fsolve会失败(给出错误的exitflag)。但除此之外,它总是返回起始点作为根。

我用一个非常简单的方程测试了fsolve,它运行得很好,所以我知道我导入的东西都是需要的,并且应该正确使用fsolve。我还尝试调整一些输入参数,但我对这些参数不是很了解,似乎没有什么变化。

下面是相关的代码(E是唯一的变量,其余的都有非零值):

def func(E):
    s = sqrt(c_sqr * (1 - E / V_0))
    f = s / tan(s) + sqrt(c_sqr - s**2)
    return f

guess = 3
fsolve(func, guess)

这段代码只输出'3'并说'解已经收敛',尽管最近的解应该在大约2.8和4.7附近。

有没有人知道怎么解决这个问题,得到正确的答案(使用fsolve)?

2 个回答

1

你有没有试过把你的函数改得简单一点?比如这样:

#!/usr/bin/python
from scipy.optimize import fsolve

def func(E):
#    s = sqrt(c_sqr * (1 - E / V_0))
#    f = s / tan(s) + sqrt(c_sqr - s**2)
    f = E**2 -3.
    return f

guess = 9

sol=fsolve(func, guess)
print sol, func(sol)

对我来说,上面的代码确实能收敛到应该到达的地方。

另外,在你提供的代码中,c_strV_0是什么?如果你的函数实际上依赖于多个变量,而你把其中一个当作常量参数处理,那么可以使用fsolveargs参数,像这样:

#!/usr/bin/python
from scipy.optimize import fsolve
from numpy import sqrt

def func(E,V_0):
    #s = sqrt(c_sqr * (1 - E / V_0))
    #f = s / tan(s) + sqrt(c_sqr - s**2)
    f = E**2 -V_0
    return f

VV=4.
guess = 9
sol=fsolve(func, guess, args=(VV))

print sol, func(sol,VV) 
6

我觉得你的方程可能没有你想的那么简单。首先,当我尝试这个方程时,它并不会返回你猜的那个值,而是返回一个接近你猜的值的数字。这个结果非常不稳定,这似乎让fsolve感到困惑。例如:

>>> V_0 = 100
>>> c_sqr = 3e8 ** 2
>>> guess = 5
>>> fsolve(func, guess)
array([ 5.00000079])

这个结果并不是5。甚至在计算机的精度范围内也不是5。它也不是方程的根:

>>> func(5.00000079)
2114979.3239706755

不过,这个方程的表现其实是相当不可预测的:

>>> func(5.0000008)
6821403.0196130127
>>> func(5.0000006)
-96874198.203683496

所以很明显,在那附近有一个零交叉。我建议你仔细检查一下你的方程。确保你在使用tan的时候,传入的参数是以弧度为单位的。

撰写回答