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


import math
import matplotlib.pyplot as plt

# Вариант 2: f(x,y) = (3x^2 + y) / (2x)
def f(x, y):
    return (3*x*x + y) / (2*x)

# Точное решение (проверено: y = x^2 + sqrt(x) подходит)
def exact(x):
    return x**2 + math.sqrt(x)

def euler(x, y, h):
    return y + h * f(x, y)

def rk4(x, y, h):
    k1 = f(x, y)
    k2 = f(x + h/2, y + h*k1/2)
    k3 = f(x + h/2, y + h*k2/2)
    k4 = f(x + h, y + h*k3)
    return y + h * (k1 + 2*k2 + 2*k3 + k4) / 6

# Параметры задачи
h = 0.1
x0 = 1.0
y0 = 2.0
b = 1.8

# Количество шагов (от 1.0 до 1.8 это 8 шагов)
n_steps = int((b - x0) / h) + 1
x = [x0 + i*h for i in range(n_steps)]

# Инициализация массивов
y_rk = [y0]
y_euler = [y0]

# --- ЭТАП 1: Разгон (4 шага) ---
# Нам нужно 4 начальные точки для формулы Адамса, 
# поэтому делаем 3 шага (получаем точки 0,1,2,3) или 4 шага.
# Сделаем 4 шага, чтобы получить точки x0, x1, x2, x3, x4.
for i in range(4):
    y_rk.append(rk4(x[i], y_rk[i], h))
    y_euler.append(euler(x[i], y_euler[i], h))

# --- ЭТАП 2: Метод Адамса ---
# Начинаем с i=4, так как у нас уже есть значения для x[0]..x[4]
for i in range(4, n_steps - 1): # n_steps-1, так как цикл идет до предпоследнего индекса
    # Формула Адамса 4-го порядка
    # y_{i+1} = y_i + h/24 * (55*f_i - 59*f_{i-1} + 37*f_{i-2} - 9*f_{i-3})
    
    # Для Рунге-Кутты
    y_new_rk = y_rk[i] + h / 24 * (
        55 * f(x[i], y_rk[i])
        - 59 * f(x[i-1], y_rk[i-1])
        + 37 * f(x[i-2], y_rk[i-2])
        - 9 * f(x[i-3], y_rk[i-3])
    )
    y_rk.append(y_new_rk)

    # Для Эйлера
    y_new_euler = y_euler[i] + h / 24 * (
        55 * f(x[i], y_euler[i])
        - 59 * f(x[i-1], y_euler[i-1])
        + 37 * f(x[i-2], y_euler[i-2])
        - 9 * f(x[i-3], y_euler[i-3])
    )
    y_euler.append(y_new_euler)

# Точное решение
y_exact = [exact(xi) for xi in x]

# Погрешности
error_rk = [abs(y_rk[i] - y_exact[i]) for i in range(len(x))]
error_euler = [abs(y_euler[i] - y_exact[i]) for i in range(len(x))]

# Вывод таблицы
print("k   x     Адамс+РК    Адамс+Эйлер   точное y    ошибка РК    ошибка Эйлера")
for i in range(len(x)):
    print(
        i,
        round(x[i], 1),
        round(y_rk[i], 6),
        round(y_euler[i], 6),
        round(y_exact[i], 6),
        round(error_rk[i], 8),
        round(error_euler[i], 8)
    )

# График решений
plt.figure()
plt.plot(x, y_rk, "o-", label="Адамс + Рунге-Кутта")
plt.plot(x, y_euler, "o-", label="Адамс + Эйлер")
plt.plot(x, y_exact, "s--", label="Точное решение")
plt.xlabel("x")
plt.ylabel("y")
plt.title("Сравнение методов (Вариант 2)")
plt.grid()
plt.legend()
plt.show()

# График погрешностей
plt.figure()
plt.plot(x, error_rk, "o-", label="Ошибка: Рунге-Кутта")
plt.plot(x, error_euler, "o-", label="Ошибка: Эйлер")
plt.xlabel("x")
plt.ylabel("Погрешность")
plt.title("Сравнение погрешностей")
plt.grid()
plt.legend()
plt.show()