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


# Программа 3: Графики + стрелки градиентов + точки минимумов от двух методов
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

def f(x):
    return x[0]**2 + x[1]**2 + 1.1*x[0]*x[1] + x[0] - x[1] + 1.1

def grad(x):
    return np.array([2*x[0] + 1.1*x[1] + 1,
                     2*x[1] + 1.1*x[0] - 1])

# ---------- Находим минимум методом Нелдера-Мида (повторяем код из первой программы) ----------
def simplex_min(f, x0, eps=1e-6):
    n = len(x0)
    simplex = np.zeros((n, n+1))
    simplex[:, 0] = x0
    for i in range(n):
        step = np.zeros(n)
        step[i] = 0.5
        simplex[:, i+1] = x0 + step
    fx = np.array([f(simplex[:, i]) for i in range(n+1)])
    alpha, beta, gamma, sigma = 1.0, 0.5, 2.0, 0.5
    it = 0
    while np.var(fx) > eps and it < 10000:
        ix = np.argsort(fx)
        fx = fx[ix]
        simplex = simplex[:, ix]
        xo = np.mean(simplex[:, :-1], axis=1)
        xr = xo + alpha * (xo - simplex[:, -1])
        fxr = f(xr)
        if fx[0] <= fxr < fx[-2]:
            simplex[:, -1] = xr
            fx[-1] = fxr
        elif fxr < fx[0]:
            xe = xo + gamma * (xr - xo)
            if f(xe) < fxr:
                simplex[:, -1] = xe
                fx[-1] = f(xe)
            else:
                simplex[:, -1] = xr
                fx[-1] = fxr
        elif fxr >= fx[-2]:
            xc = xo + beta * (simplex[:, -1] - xo)
            if f(xc) < fx[-1]:
                simplex[:, -1] = xc
                fx[-1] = f(xc)
            else:
                for i in range(1, n+1):
                    simplex[:, i] = simplex[:, 0] + sigma * (simplex[:, i] - simplex[:, 0])
                fx = np.array([f(simplex[:, i]) for i in range(n+1)])
        it += 1
    ix = np.argmin(fx)
    return simplex[:, ix]

# ---------- Минимум градиентным методом ----------
def grad_min(f, grad, x0, alpha=0.2, eps=1e-6):
    x = x0.copy()
    f_prev = f(x)
    for _ in range(10000):
        g = grad(x)
        if np.linalg.norm(g) < eps:
            break
        for _ in range(10):
            x_new = x - alpha * g
            f_new = f(x_new)
            if f_new < f_prev:
                x = x_new
                f_prev = f_new
                break
            alpha *= 0.5
    return x

# Начальная точка
x0 = np.array([1.0, 0.0])
x_nm = simplex_min(f, x0)
x_gd = grad_min(f, grad, x0)

print("Точки минимума для графика:")
print(f"Нелдер-Мид: {x_nm}")
print(f"Градиентный: {x_gd}")

# ---------- Построение сетки и вычисление функции ----------
xx = np.linspace(-2, 2, 50)
X, Y = np.meshgrid(xx, xx)
Z = X**2 + Y**2 + 1.1*X*Y + X - Y + 1.1

# ---------- 2D контурный график с линиями уровня и стрелками градиентов ----------
plt.figure(figsize=(9, 7))
contour = plt.contour(X, Y, Z, levels=20, cmap='viridis')
plt.clabel(contour, inline=True, fontsize=8)
plt.colorbar(contour, label='f(x1, x2)')

# Стрелки градиентов (редкая сетка)
Xq, Yq = np.meshgrid(np.linspace(-2, 2, 12), np.linspace(-2, 2, 12))
U = np.zeros_like(Xq)
V = np.zeros_like(Xq)
for i in range(Xq.shape[0]):
    for j in range(Xq.shape[1]):
        g = grad([Xq[i,j], Yq[i,j]])
        U[i,j] = g[0]
        V[i,j] = g[1]
# Нормируем для наглядности
norm = np.sqrt(U**2 + V**2)
U = U / (norm + 1e-8)
V = V / (norm + 1e-8)
plt.quiver(Xq, Yq, U, V, alpha=0.6, width=0.003, scale=25)

# Точки минимумов
plt.plot(x_nm[0], x_nm[1], 'ro', markersize=8, label=f'Нелдер-Мид')
plt.plot(x_gd[0], x_gd[1], 'b^', markersize=8, label=f'Градиентный')

plt.title('Линии уровня и стрелки градиентов (нормированные)')
plt.xlabel('x1')
plt.ylabel('x2')
plt.legend()
plt.grid(alpha=0.3)
plt.axis('equal')
plt.tight_layout()
plt.savefig('contour_grad.png', dpi=150)
plt.show()

# ---------- 3D поверхность ----------
fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_surface(X, Y, Z, cmap='viridis', edgecolor='none', alpha=0.8)
ax.scatter(x_nm[0], x_nm[1], f(x_nm), color='red', s=50, label='Нелдер-Мид')
ax.scatter(x_gd[0], x_gd[1], f(x_gd), color='blue', marker='^', s=50, label='Градиентный')
ax.set_xlabel('x1')
ax.set_ylabel('x2')
ax.set_zlabel('f')
ax.set_title('Поверхность функции и точки минимума')
ax.legend()
plt.colorbar(surf, shrink=0.5, aspect=10)
plt.tight_layout()
plt.savefig('surface_3d.png', dpi=150)
plt.show()