Графический метод Ньютона в питоне - PullRequest
0 голосов
/ 04 ноября 2018

В следующем коде я реализовал метод Ньютона в Python.

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'

1 Ответ

0 голосов
/ 05 ноября 2018

Я предлагаю хранить каждое значение x и соответствующий вывод f для каждой итерации в двух соответствующих массивах, а затем возвращать каждый массив. Если ваша функция правильная (вы должны знать, сходится ли она), то это должно быть легко сделать. Оттуда, просто построите массив.

Я сделал это пару месяцев назад. Вы можете увидеть, как я работал через это здесь: Как определить, что метод Ньютона не работает

Итак, пара вещей, на которые стоит обратить внимание.

1) Я не проверял, чтобы убедиться, что ваша функция сходится правильно или нет.

2) Метод Ньютонов обычно имеет очень большой размер шага, и вы обычно не получите никаких симпатичных визуализаций для его сходимостей. Нередко бывает <10 итераций, и они также обычно не следуют по плавному пути к точке сходимости (опять же, большой размер шага). Обратите внимание, что для кода, который я реализовал, было только 3 итерации. Но это может быть просто потому, что ваша функция неправильная. Честно говоря, я не уверен </p>

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()

enter image description here

...