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


import numpy as np
from scipy.integrate import quad
import matplotlib.pyplot as plt

# ============================================================
# Постановка задачи (вариант 2)
#   y'' = x + 1,   y(4) = y(5) = 0
# ============================================================
a, b = 4.0, 5.0
L = b - a

f_rhs = lambda x: x + 1.0   # правая часть

# ============================================================
# Базисные функции: синусы (как в методичке 10.pdf)
#   phi_i(x) = sin(pi * i * (x-a) / (b-a))
# ============================================================
def phi(i, x):
    return np.sin(np.pi * i * (x - a) / L)

def phi_dd(i, x):
    # Вторая производная по x
    k = np.pi * i / L
    return -(k**2) * np.sin(k * (x - a))

N = 3   # число базисных функций

# ============================================================
# 1) МЕТОД КОЛЛОКАЦИЙ
# ============================================================
x_col = np.linspace(a, b, N+2)[1:-1]
A_col = np.zeros((N, N))
b_col = np.zeros(N)
for j, xj in enumerate(x_col):
    for i in range(1, N+1):
        A_col[j, i-1] = phi_dd(i, xj)
    b_col[j] = f_rhs(xj)
c_col = np.linalg.solve(A_col, b_col)

# ============================================================
# 2) МЕТОД НАИМЕНЬШИХ КВАДРАТОВ
# ============================================================
A_ls = np.zeros((N, N))
b_ls = np.zeros(N)
for i in range(1, N+1):
    for j in range(1, N+1):
        A_ls[i-1, j-1] = quad(lambda x: phi_dd(i, x) * phi_dd(j, x), a, b)[0]
    b_ls[i-1] = quad(lambda x: f_rhs(x) * phi_dd(i, x), a, b)[0]
c_ls = np.linalg.solve(A_ls, b_ls)

# ============================================================
# 3) МЕТОД ГАЛЁРКИНА
# ============================================================
A_gal = np.zeros((N, N))
b_gal = np.zeros(N)
for i in range(1, N+1):
    for j in range(1, N+1):
        A_gal[i-1, j-1] = quad(lambda x: phi_dd(i, x) * phi(j, x), a, b)[0]
    b_gal[i-1] = quad(lambda x: f_rhs(x) * phi(i, x), a, b)[0]
c_gal = np.linalg.solve(A_gal, b_gal)

# ============================================================
# Точное решение (для [4,5])
# ============================================================
y_exact = lambda x: x**3/6.0 + x**2/2.0 - (44.0/3.0)*x + 40.0

def y_approx(x, c):
    return sum(c[i-1] * phi(i, x) for i in range(1, N+1))

# ============================================================
# Вывод
# ============================================================
print("="*60)
print("  Коэффициенты (синусоидальный базис, N = 3)")
print("="*60)
print(f"  Коллокации : c = {np.round(c_col, 4)}")
print(f"  МНК        : c = {np.round(c_ls, 4)}")
print(f"  Галёркин   : c = {np.round(c_gal, 4)}")

xs = np.linspace(a, b, 11)
print("\n" + "="*85)
print(f"{'x':>6} | {'y_точн':>10} | {'Коллокации':>12} | {'МНК':>12} | {'Галёркин':>12} | {'max|err|':>10}")
print("-"*85)
err_max = 0.0
for x in xs:
    ye = y_exact(x)
    yc = y_approx(x, c_col)
    yl = y_approx(x, c_ls)
    yg = y_approx(x, c_gal)
    emax = max(abs(yc-ye), abs(yl-ye), abs(yg-ye))
    err_max = max(err_max, emax)
    print(f"{x:6.2f} | {ye:10.6f} | {yc:12.6f} | {yl:12.6f} | {yg:12.6f} | {emax:10.2e}")
print("="*85)
print(f"Максимальная погрешность: {err_max:.4e}")

# ============================================================
# График
# ============================================================
xx = np.linspace(a, b, 400)
plt.figure(figsize=(10, 6))
plt.plot(xx, y_exact(xx), 'k-',  lw=3, label='Точное решение')
plt.plot(xx, y_approx(xx, c_col), 'r--', lw=2, label='Коллокации')
plt.plot(xx, y_approx(xx, c_ls),  'b-.', lw=2, label='МНК')
plt.plot(xx, y_approx(xx, c_gal), 'g:',  lw=2.5, label='Галёркин')
plt.scatter(x_col, y_exact(x_col), c='r', s=80, zorder=5, label='Точки коллокации')

plt.xlabel('x'); plt.ylabel('y(x)')
plt.title('Вариант 2: y\'\' = x+1, y(4)=y(5)=0 (синусоидальный базис)')
plt.legend(); plt.grid(alpha=0.3)
plt.tight_layout()
plt.show()