用户自定义函数的牛顿法

Newtons Method of a User-defined Function

我正在尝试使用牛顿法求方程的根。这可能是一个非常明显的错误,但我不断收到一条错误消息:"TypeError: cannot determine truth value of Relational"。有什么我忘了 import/include 的吗?抱歉,我是 python 的新手。

import sympy

from sympy import *
x, y, z = symbols('x y z')
init_printing(use_unicode=True)

def newton(f, n, eps):
    y = f(n)
    delta = diff(eps, x)
    while abs(y) > eps:
        dy = (f(n + delta) - y) / delta
        n = n - y/dy
        y = f(n)
    return n

def f(n):
    return 5 * n + 10

eps = input("input function:")

print(newton(f, 0, eps))

您的代码未实现牛顿法。您想估计初始猜测的切线,用 y=0 截取它以获得新的猜测并继续这样做,直到猜测值的函数足够接近 0。请参见下面的代码。

def newton(f, x, eps=1e-50):
    y = f(x)
    delta = 1e-10
    while abs(y) > eps:
        dy = (f(x+delta) - y) / delta
        x = x - y/dy
        y = f(x)
    return x

def f(x):
    return 5 * x + 10

newton(f, 0) # outputs -2.0

User-supplied 通过文本实现的功能并不容易实现。我们通常做的是提供上述函数的数值实现。

如果你想在符号级别上操作,你需要解析字符串并在你的代码中构造一个合适的函数,这不是很简单。您可能想检查是否有可用的库。

在实践中,您可能希望实现最大迭代次数,以防有人在没有根的函数上运行它。

总结:可以在SymPy中制定一个用户定义的函数,其导数几乎可以自动获得,objective函数及其导数的数值函数可以通过lambdify检索。通过使用 lambdifyed Python 函数,您不会因符号计算而影响效率。另外,我们可以利用包含牛顿法的SciPy优化包。

scipy.optimize.minimize 提供牛顿法。您可以将 objective 函数及其导数输入它并得到结果。

在您的原始代码中使用符号数学对我来说没有意义,因为它处理的是特定的数学公式。使用 NumPy 并获得更好的执行性能。

如果您正在考虑为各种数学公式提供通用的数学接口,SymPy 很棒,因为我们可以享受它的衍生功能。

几个月前,我结合使用 SymPy 和 SciPy 优化来制作 spring 连接体的物理模型。

https://github.com/wakita/symdoc/blob/master/kk.ipynb

  • objective函数的公式在[9]中给出。
  • 在[10]中得到一个Python函数对应objective函数。
  • objective函数的导数在[14]中得到。
  • In[19]中执行基于牛顿的最小化。它利用了 objective 函数的一阶和二阶导数。

使用 SymPy 的美妙之处在于,正如您在我的示例中看到的那样,我根本不会搞乱导数的复杂计算,另一方面,该解决方案处理在 SymPy 中表达的任何公式。