Python 避免使用同一输入多次评估函数

Python 避免使用同一输入多次评估函数,python,numpy,scipy,solver,Python,Numpy,Scipy,Solver,我试图使用scipy.optimize.fsolve来解函数。我注意到,在迭代步骤的开始和结束时,函数多次使用相同的值求值。例如,当计算以下代码时: from scipy.optimize import fsolve def yy(x): print(x) return x**2+9*x+20 y = fsolve(yy,22.) print(y) 获得以下输出: [ 22.] [ 22.] [ 22.] [ 22.00000033] [ 8.75471707] [ 4.

我试图使用scipy.optimize.fsolve来解函数。我注意到,在迭代步骤的开始和结束时,函数多次使用相同的值求值。例如,当计算以下代码时:

from scipy.optimize import fsolve

def yy(x):
    print(x)
    return x**2+9*x+20

y = fsolve(yy,22.)

print(y)
获得以下输出:

[ 22.]
[ 22.]
[ 22.]
[ 22.00000033]
[ 8.75471707]
[ 4.34171812]
[ 0.81508685]
[-1.16277103]
[-2.42105811]
[-3.17288066]
[-3.61657372]
[-3.85653348]
[-3.96397335]
[-3.99561793]
[-3.99984826]
[-3.99999934]
[-4.]
[-4.]
[-4.]
因此,使用22对函数进行评估。三次,这是不必要的


当函数需要大量的计算时间时,这尤其令人讨厌。有人能解释一下并建议如何避免这个问题吗?

第一次评估只是为了检查函数输出的形状和数据类型。具体来说,
fsolve
调用
\u root\u hybr
,其中包含

当然,
\u check\u func

由于此计算仅保留形状和数据类型,因此当实际根查找过程开始时,解算器将再次调用值为
x0
的函数

以上说明了一个无关调用(两个调用中的一个)。我没有找到另一个,但可以想象FORTRAN代码自己也会做一些初步检查。当很久以前编写的算法被反复包装时,就会发生这种情况

如果您真的想保存昂贵函数yy的这两个求值,一种方法是分别计算值yy(x0)并存储它。例如:

def yy(x):
    if x == x0 and y0 is not None:
       return y0
    print(x)
    return x**2+9*x+20

x0 = 22.
y0 = None
y0 = yy(x0)
y = fsolve(yy, x0)

我意识到这个问题的一个重要原因是,fsolve并不适用于这样的问题:应该明智地选择解决者:)


其中一个参数是,它被描述为“一个计算func的雅可比矩阵的函数,该函数具有跨行的导数。默认情况下,雅可比矩阵将被估计。”。我想知道前几个调用是否是在前几个步骤的雅可比矩阵近似过程中进行的。但是,为什么它会使用相同的变量呢?它是否应该更改计算雅可比矩阵的值?看起来我的猜测是错误的,我为你的函数
defy_p(x):返回2*x+9
,并将其作为
fprime=y_p
传递,它仍然多次计算
22.
值。奇怪的是,我猜不出它为什么会这样做。看起来这些调用的细节隐藏在MINPACK代码中:
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
def yy(x):
    if x == x0 and y0 is not None:
       return y0
    print(x)
    return x**2+9*x+20

x0 = 22.
y0 = None
y0 = yy(x0)
y = fsolve(yy, x0)
multivariate: fmin, fmin_powell, fmin_cg, fmin_bfgs, fmin_ncg
nonlinear: leastsq
constrained: fmin_l_bfgs_b, fmin_tnc, fmin_cobyla
global: basinhopping, brute, differential_evolution
local: fminbound, brent, golden, bracket
n-dimensional: fsolve
one-dimensional: brenth, ridder, bisect, newton
scalar: fixed_point