scipy.optimize.fsolve 收敛错误?

1 投票
1 回答
1808 浏览
提问于 2025-04-18 17:52

这是代码

import scipy as sc
import scipy.optimize as sco

def g(rho):
    return 0.5 * (rho**2 + rho) * sc.exp(-rho)

p = 0.01017036
guess = 1.5879245860401234
sol = sco.fsolve(lambda rho: g(rho) - p, guess, full_output=True)

print g(sol[0]) - p
print sol

输出结果是

[ 0.40970908]
(array([ 1.58792459]), {'qtf': array([-0.40970908]), 'nfev': 4, 'r': array([  9.52007670e+26]), 'fjac': array([[-1.]]), 'fvec': array([ 0.40970908])}, 1, 'The solution converged.')

它说已经收敛了,但显然没有,因为我应该得到的 g(sol[0]) - p 应该离零更近,而不是 0.4

我觉得用来检查收敛的测试有问题,导致出现错误。我知道我可以改变猜测的值来得到正确的结果,但这不是我想要的情况(我需要找到成千上万的根,而我得到了很多错误的根),问题在于这个错误捕捉的算法不可靠。我是不是做错了什么??

提前谢谢你。

1 个回答

1

你现在是在最小化一个目标函数,而不是在找一个根,所以你应该使用 optimize.fmin 来做这个:

import scipy as sc
import scipy.optimize as sco

def g(rho):
    return 0.5 * (rho**2 + rho) * sc.exp(-rho)

p = 0.01017036
guess = 1.5879245860401234
sol = sco.fmin(lambda rho: (g(rho)-p)**2, guess)

print sol
Optimization terminated successfully.
         Current function value: 0.000000
         Iterations: 23
         Function evaluations: 46
[ 8.2240227] 

这可能也跟你最开始的猜测不太好有关:

p = 0.01017036
guess = 1.5879245860401234
print sco.fsolve(f, 10, fprime=gp, args=(p,), full_output=1)
print sco.fsolve(lambda rho: g(rho) - p, 10, full_output=True)

print '\n==================bad_guess====================='
print sco.fsolve(f, guess, fprime=gp, args=(p,), full_output=1)
print sco.fsolve(lambda rho: g(rho) - p, guess, full_output=True)
#(array([ 8.22399478]), {'fvec': array([ -1.90472638e-15]), 'qtf': array([  1.87372265e-10]), 'nfev': 10, 'r': array([ 0.00783117]), 'fjac': array([[-1.]]), 'njev': 1}, 1, 'The solution converged.')
#(array([ 8.22399478]), {'qtf': array([  1.87372918e-10]), 'nfev': 11, 'r': array([ 0.00783117]), 'fjac': array([[-1.]]), 'fvec': array([ -1.90472638e-15])}, 1, 'The solution converged.')
#
#==================bad_guess=====================
#(array([ 1.58792459]), {'fvec': array([ 0.40970908]), 'qtf': array([-0.40970908]), 'nfev': 3, 'r': array([  9.52013062e+26]), 'fjac': array([[-1.]]), 'njev': 1}, 1, 'The solution converged.')
#(array([ 1.58792459]), {'qtf': array([-0.40970908]), 'nfev': 4, 'r': array([  9.52007670e+26]), 'fjac': array([[-1.]]), 'fvec': array([ 0.40970908])}, 1, 'The solution converged.')

可能收敛性是由雅可比矩阵决定的,而你的 guess 可能让雅可比矩阵落在了一个奇怪的地方。注意,rho=8.22399478rho=1.58792459 的雅可比矩阵是一样的,而 1.58792459 正好是你最开始的猜测。看起来 fsolve 由于某种原因从来没有离开过这个初始猜测。

撰写回答