Как в алгоритме Python рассчитать сходимость?

Рейтинг: 0Ответов: 1Опубликовано: 06.07.2023

Возможно, есть математики? Есть алгоритм расчета корней уравнения dichotomy() методом дихотомии. И вот мне надо считать сходимость решения, причем делать это после того, как были определены корни. И, вроде, я ровно так и делаю (пункт 8). Однако сходимость conv_param получаю для всех корней 0.5, что явно ошибочно.

Возможно, не там ставлю расчет данного коэффициента?

Код:

import numpy as np
import time
from decimal import *

def f(x):
    # 1. определим функцию для расчета 
    return 1.2 - np.log(x) - 4 * np.cos(2 * x)


def dichotomy(a, b, eps_func, eps_arg):
    # 2. определим ограничения на границы отрезка
    assert a != 0, 'a равно 0'
    assert b != 0, 'b равно 0'

    # 3. запросим количество частей n, на которые будет дробиться отрезок
    n = float( input('Введите параметр n (дробь меньше нуля): ') )

    # 4. создаем переменную-список для хранения значений сходимости
    prev_roots = []

    # 5. отделим корни
    grid = []
    current = a   # текущее значение, начинающееся с a
    while current <= b:
        grid.append(current)
        current += n

    # 6. создадим переменную f_x, чтобы оптимизировать количество вычислений функци
    f_x = f(grid[0])

    # 7. уточним наличие корней на каждом отрезке
    for x, y in zip(grid, grid[1:]):
        # 7.1. создадим переменную f_y и присвоим ей значение функции для оптимизации количества вычислений функции
        f_y = f(y)
        # 7.2. если на отрезке нет корня, смотрим следующий отрезок
        if f_x * f_y > 0:
            continue
        root = None
        # 7.3. создадим переменную f_mid
        f_mid = f((x + y) / 2)
        # 7.4. уточним корни
        # 7.4.1. пока отрезок больше заданной погрешности по функции и аргументу, выполняем нижестоящие операции:
        while abs(f_mid) > eps_func or ((y - x) / 2) > eps_arg:
            # 7.4.1.1. получаем середину отрезка
            mid = (y + x) / 2
            # 7.4.1.1. корень примем равнм серединному значению
            root = mid
            # 7.4.1.2.   
            f_x_mid = Decimal(f_mid * f_x)
            # 7.4.1.3. если произведение функции в середине отрезка на функцию в т. а <= 0:
            if f_x_mid <= 0:
                # 7.4.1.3.1. серединой отрезка признаем точку b, обновим значение функции:
                y = mid
                f_y = f_mid
            else:
                # 7.4.1.3.2. в другом случае — точку а и обновим значение функции:
                x = mid
                f_x = f_mid

            # 7.4.1.4. пересчитаем середину интервала и функцию от этого значения
            mid = (x + y) / 2
            f_mid = f(mid)
        # 8. Возвращаем корень и коэффициент сходимости conv_param
        if root:
            conv_param = abs(mid - x) / abs(y - x)
            prev_roots.append(conv_param)
            yield root
        f_x = f(y)
    print('prev_roots: ', prev_roots)
    # 9. возвращаем значение погрешности расчета корня
    yield prev_roots

list(dichotomy(0.0001, 50, 0.000001, 0.000001))

Ответы

▲ 0

Для найденных и уточненных корней получил коэффициенты сходимости, близкие к единице. Это хорошее значение. Дело в том, что я использовал (ошибочно) границы отрезков, а надо было брать корни - предыдущий root_0 и текущий root. Вот фрагмент кода:

if root:
            ...
            # 7.8.2. считаем коэффициент сходимости вычисления и заносим его в список для каждого корня
            conv_param = abs(mid - root_0) / abs(root_0 - root)
            prev_roots.append(conv_param)
            yield root

При этом после сличения корней далее в скрипте переопределяю переменные, меняя текущий корень на предыдущий: root_0 = root.