【问题标题】:Graphing Newtons method in python在python中绘制牛顿法
【发布时间】:2018-11-05 06:34:17
【问题描述】:

在以下代码中,我在 Python 中实现了 Newtons 方法。

import math
def Newton(f, dfdx, x, eps):
    f_value = f(x)
    iteration_counter = 0
    while abs(f_value) > eps and iteration_counter < 100:
        try:
            x = x - float(f_value)/dfdx(x)
        except ZeroDivisionError:
            print ("Error! - derivative zero for x = ", x)
            sys.exit(1)     # Abort with error
        f_value = f(x)
        iteration_counter += 1

    # Here, either a solution is found, or too many iterations
    if abs(f_value) > eps:
        iteration_counter = -1
    return x, iteration_counter
def f(x):
    return (math.cos(x)-math.sin(x))
def dfdx(x):
    return (-math.sin(x)-math.cos(x))
solution, no_iterations = Newton(f, dfdx, x=1, eps=1.0e-14)
if no_iterations > 0:    # Solution found
    print ("Number of function calls: %d" % (1 + 2*no_iterations))
    print ("A solution is: %f" % (solution))
else:
    print ("Solution not found!")

但是现在我希望在同一时间间隔上绘制收敛图。这将是作为迭代次数函数的绝对误差。

我尝试制作一个可迭代的,每次都会产生一个具有绝对误差和迭代的 2 元组。下面是我的代码,其中还包含我从中得到的错误,

import math
def Newton(f, dfdx, x, eps):
    f_value = f(x)
    iteration_counter = 0
    while abs(f_value) > eps and iteration_counter < 100:
        try:
            x = x - float(f_value)/dfdx(x)
            yield interation_counter, abs(f(x))
        except ZeroDivisionError:
            print ("Error! - derivative zero for x = ", x)
            sys.exit(1)     # Abort with error
        f_value = f(x)
        iteration_counter += 1

    # Here, either a solution is found, or too many iterations
    if abs(f_value) > eps:
        iteration_counter = -1
def f(x):
    (math.cos(x)-math.sin(x))
def dfdx(x):
    (-math.sin(x)-math.cos(x))

通过这个,我尝试将结果放入一个数组中,以便绘制我的结果

import numpy as np
np.array(list(Newton(f,dfdx, 1,10e-4)))

但是我收到以下错误:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-20-9378f4e2dbe3> in <module>()
      1 import numpy as np
----> 2 np.array(list(Newton(f,dfdx, 1,10e-4)))

<ipython-input-19-40b67c2c3121> in Newton(f, dfdx, x, eps)
      4     f_value = f(x)
      5     iteration_counter = 0
----> 6     while abs(f_value) > eps and iteration_counter < 100:
      7         try:
      8             x = x - float(f_value)/dfdx(x)

TypeError: bad operand type for abs(): 'NoneType'

【问题讨论】:

  • 你忘记了 return 函数中的任何内容...
  • 感谢您指出这一点
  • @usr2564301 一旦修复了,我应该得到正确的输出吗?我的数组输出给了我一个 2x2
  • 它将修复您遇到的错误。你的算法是否正确,我不知道。
  • 好的,谢谢你的帮助!

标签: python newtons-method


【解决方案1】:

我建议将每次迭代的每个值 x 和对应的输出 f 存储在两个各自的数组中,然后返回每个数组。如果你的函数是正确的(你应该知道它是否收敛),那么这应该很容易做到。从那里,只需绘制数组。

我在几个月前做了这个。你可以在这里看到我是如何完成它的: How to tell if Newtons-Method Fails

所以这里有几点需要注意。

1) 我没有检查以确保您的函数是否正确收敛。

2) 牛顿法通常具有非常大的步长,并且您通常不会得到任何漂亮的收敛性可视化。小于 10 次迭代的情况并不少见,而且它们通常也不会沿着平滑的路径到达收敛点(再一次,大步长)。请注意,对于我实现的代码,只有 3 次迭代。但这可能只是因为你的功能是错误的。坦率地说,我不确定

import numpy as np
import math
import matplotlib.pyplot as plt

def Newton(f, dfdx, x, eps):
    xstore=[]
    fstore=[]
    f_value = f(x)
    iteration_counter = 0
    while abs(f_value) > eps and iteration_counter < 100:
        try:
            x = x - float(f_value)/dfdx(x)
        except ZeroDivisionError:
            print ("Error! - derivative zero for x = ", x)
            sys.exit(1)     # Abort with error
        f_value = f(x)
        xstore.append(x)
        fstore.append(f_value)
        iteration_counter += 1

    # Here, either a solution is found, or too many iterations
    if abs(f_value) > eps:
        iteration_counter = -1

    return x, iteration_counter,xstore,fstore

def f(x):
    return (math.cos(x)-math.sin(x))
def dfdx(x):
    return (-math.sin(x)-math.cos(x))

solution, no_iterations,xvalues,fvalues = Newton(f, dfdx, x=1, eps=1.0e-14)

if no_iterations > 0:    # Solution found
    print ("Number of function calls: %d" % (1 + 2*no_iterations))
    print ("A solution is: %f" % (solution))
else:
    print ("Solution not found!")

x = np.array([i for i in xvalues])
f = np.array(fvalues)
fig = plt.figure()
plt.scatter(x,f,label='Newton')
plt.legend()

【讨论】:

  • 你能告诉我这是如何用我的代码完成的吗?那我可以接受答案了
  • 感谢您的编辑。这是显示绝对误差随迭代次数变化的收敛图吗?现在我的代码只需要 7 次迭代就能找到我的解决方案
  • 我相信这只是显示了答案,而不是作为迭代次数函数的绝对误差
  • 不,这只是绘制牛顿方法迭代的值(例如 x_1、x_2、x_3 等,带有给定 x 的相应目标函数输出)此外,您的代码仅迭代 3次。我不知道您为什么将函数调用的数量定义为1 + 2*no_iterations。当您说“绝对错误是迭代次数的函数”时,我没有遵循您的意思。无论如何,您应该了解如何为您尝试输出的任何内容可视化您的输出
  • 那么我将如何修复迭代次数?
猜你喜欢
  • 1970-01-01
  • 2018-02-26
  • 1970-01-01
  • 2018-04-09
  • 2018-11-21
  • 1970-01-01
  • 2017-06-28
  • 2018-10-16
  • 2017-01-25
相关资源
最近更新 更多