如何使用Scipy优化包的牛顿函数进行根查找

0 投票
1 回答
7053 浏览
提问于 2025-04-17 12:34
from scipy.optimize import newton

我想使用加载的 newton 函数来找出用户输入的一个函数的零点。为此,我写了一个脚本,首先让用户指定一个函数及其一阶导数,还有算法的起始点。首先,我输入 help(newton),查看这个函数需要哪些参数以及相关的解释:

newton(func, x0, fprime=None, args=(), tol=1.48e-08, maxiter=50)

func : function
    The function whose zero is wanted. It must be a function of a
    single variable of the form f(x,a,b,c...), where a,b,c... are extra
    arguments that can be passed in the `args` parameter.

我该如何传递我的函数呢?如果我把 x**3(还有它的一阶导数)作为 func 使用,系统会返回 NameError: name 'x' is not defined 的错误。在网上我发现,我首先需要定义我的函数和它的一阶导数,并把这些名称作为参数传递。所以我做了以下操作:

fie = raw_input('Enter function in terms of x (e.g. x**2 - 2*x). F= ')
dfie = raw_input('Enter first derivative of function above DF = ')
x0 = input('Enter starting point x0 = ')

def F(x,fie):
    y = eval(fie)
    return y 

def DF(x, dfie):
    dy = eval(dfie)
    return dy

print newton(F,x0,DF)

但是我得到的输出是

    102         for iter in range(maxiter):
    103             myargs = (p0,) + args
--> 104             fder = fprime(*myargs)
    105             if fder == 0:
    106                 msg = "derivative was zero."

TypeError: DF() takes exactly 2 arguments (1 given)

如果我省略 DF,对于 F 也会出现同样的问题。查看 /usr/local/share/src/scipy/scipy/optimize/zeros.py 中的代码,我看到它是通过 fder=fprime(*myargs) 来计算一阶导数的,所以也许我需要在 args 中放入一些东西来让它工作。我在考虑这个问题,但没有想到解决办法。

1 个回答

1

首先,要知道使用 eval 会让你的程序容易受到恶意用户的攻击。如果这个问题不影响你,你可以这样创建 F 和 DF:

F = eval('lambda x :'+fie)
DF = eval('lambda x :'+dfie)

这样的话,这两个函数只需要一个参数,你可以把 args 参数留空。

补充一下。如果你真的想尽量保持你的代码不变,这样做也可以,但我觉得看起来不太好。 newton 会把相同的 args 传给这两个函数。

def F(x,fie,dfie):
    y = eval(fie)
    return y 

def DF(x,fie,dfie):
    dy = eval(dfie)
    return dy

print newton(F,x0,DF,(fie,dfie))

撰写回答