Загрузка данных


import math

# =========================

# ЦЕЛЕВАЯ ФУНКЦИЯ

# =========================

def f(x1, x2):

    return 2 * (x1 - 4) ** 2 + (x2 - 6) ** 2

# =========================

# ГРАДИЕНТ ФУНКЦИИ

# =========================

def grad(x1, x2):

    df_dx1 = 4 * (x1 - 4)

    df_dx2 = 2 * (x2 - 6)

    return df_dx1, df_dx2

# =========================

# МЕТОД С ПОСТОЯННЫМ ШАГОМ

# =========================

def gradient_const_alpha():

    print("\n==============================")

    print("ГРАДИЕНТНЫЙ СПУСК (alpha = const)")

    print("==============================\n")

    # Начальная точка

    x1 = 7

    x2 = 7

    # Постоянный шаг

    alpha = 0.1

    # Точность

    eps = 0.01

    # Максимум итераций

    max_iter = 100

    for k in range(max_iter):

        g1, g2 = grad(x1, x2)

        grad_norm = math.sqrt(g1**2 + g2**2)

        print(f"Итерация {k}")

        print(f"x = ({x1:.6f}, {x2:.6f})")

        print(f"grad = ({g1:.6f}, {g2:.6f})")

        print(f"|grad| = {grad_norm:.6f}")

        print(f"f(x) = {f(x1, x2):.6f}")

        print()

        # Критерий остановки

        if grad_norm < eps:

            break

        # Формула метода

        x1 = x1 - alpha * g1

        x2 = x2 - alpha * g2

    print("Минимум найден:")

    print(f"x* = ({x1:.6f}, {x2:.6f})")

    print(f"f(x*) = {f(x1, x2):.6f}")

# =========================

# МЕТОД АРМИХО

# =========================

def gradient_armijo():

    print("\n==============================")

    print("ГРАДИЕНТНЫЙ СПУСК (Армихо)")

    print("==============================\n")

    # Начальная точка

    x1 = 7

    x2 = 7

    # Параметры Армихо

    alpha_max = 1.0

    rho = 0.5

    c = 0.5

    # Точность

    eps = 0.01

    # Максимум итераций

    max_iter = 100

    for k in range(max_iter):

        g1, g2 = grad(x1, x2)

        grad_norm = math.sqrt(g1**2 + g2**2)

        print(f"Итерация {k}")

        print(f"x = ({x1:.6f}, {x2:.6f})")

        print(f"grad = ({g1:.6f}, {g2:.6f})")

        print(f"|grad| = {grad_norm:.6f}")

        print(f"f(x) = {f(x1, x2):.6f}")

        # Критерий остановки

        if grad_norm < eps:

            break

        # Начальное значение alpha

        alpha = alpha_max

        # Подбор alpha по правилу Армихо

        while True:

            new_x1 = x1 - alpha * g1

            new_x2 = x2 - alpha * g2

            left = f(new_x1, new_x2)

            right = f(x1, x2) - c * alpha * (g1**2 + g2**2)

            # Проверка условия Армихо

            if left <= right:

                break

            alpha = alpha * rho

        print(f"Подобранный alpha = {alpha:.6f}\n")

        # Переход к новой точке

        x1 = new_x1

        x2 = new_x2

    print("Минимум найден:")

    print(f"x* = ({x1:.6f}, {x2:.6f})")

    print(f"f(x*) = {f(x1, x2):.6f}")

# =========================

# ЗАПУСК ОБОИХ МЕТОДОВ

# =========================

gradient_const_alpha()

gradient_armijo()