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