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


import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize

def f(x):
    x1, x2 = x
    return 1.2 * (2 * x2 - x1**2)**2 + 10 * (1.1 - x1)**2

def grad(x):
    x1, x2 = x
    df_dx1 = -4.8 * x1 * (2 * x2 - x1**2) - 20 * (1.1 - x1)
    df_dx2 = 4.8 * (2 * x2 - x1**2)
    return np.array([df_dx1, df_dx2])

x0 = np.array([2.0, 1.0])

res_nm = minimize(f, x0, method='Nelder-Mead')
res_bfgs = minimize(f, x0, jac=grad, method='BFGS')

min_nm = res_nm.x
min_bfgs = res_bfgs.x

print("Точки минимумов:")
print(f"Nelder-Mead: ({min_nm[0]:.8f}, {min_nm[1]:.8f}), f = {res_nm.fun:.8f}")
print(f"BFGS:        ({min_bfgs[0]:.8f}, {min_bfgs[1]:.8f}), f = {res_bfgs.fun:.8f}")
print(f"Разница между точками: ({abs(min_nm[0]-min_bfgs[0]):.2e}, {abs(min_nm[1]-min_bfgs[1]):.2e})")

# Сетка для графиков (диапазон подобран, чтобы охватить овраг и минимум)
x1_vals = np.linspace(-1.5, 3, 40)
x2_vals = np.linspace(-0.5, 2, 40)
X1, X2 = np.meshgrid(x1_vals, x2_vals)
Z = 1.2 * (2 * X2 - X1**2)**2 + 10 * (1.1 - X1)**2

# Численный градиент
py, px = np.gradient(Z)

fig = plt.figure(figsize=(10, 12))

# 3D поверхность
ax1 = fig.add_subplot(2, 1, 1, projection='3d')
surf = ax1.plot_surface(X1, X2, Z, cmap='plasma', alpha=0.8, edgecolor='none')
ax1.scatter(min_nm[0], min_nm[1], f(min_nm), color='red', s=80, label='Nelder-Mead', zorder=5)
ax1.scatter(min_bfgs[0], min_bfgs[1], f(min_bfgs), color='blue', s=80, label='BFGS', zorder=5)
ax1.set_xlabel('x₁')
ax1.set_ylabel('x₂')
ax1.set_zlabel('f(x₁, x₂)')
ax1.set_title('3D поверхность функции Розенброка-подобного типа')
ax1.legend()
fig.colorbar(surf, ax=ax1, shrink=0.6, aspect=20)

# Контуры + градиент
ax2 = fig.add_subplot(2, 1, 2)
contour = ax2.contour(X1, X2, Z, levels=30, cmap='plasma', linewidths=0.8)
ax2.clabel(contour, inline=True, fontsize=8, fmt='%0.1f')

stride = 3
ax2.quiver(X1[::stride, ::stride], X2[::stride, ::stride],
           px[::stride, ::stride], py[::stride, ::stride],
           color='black', alpha=0.4, scale=40, width=0.005)

ax2.scatter(min_nm[0], min_nm[1], color='red', s=120, zorder=5,
            label=f'Nelder-Mead ({min_nm[0]:.4f}, {min_nm[1]:.4f})', edgecolors='black')
ax2.scatter(min_bfgs[0], min_bfgs[1], color='blue', s=120, zorder=5,
            label=f'BFGS ({min_bfgs[0]:.4f}, {min_bfgs[1]:.4f})', edgecolors='black', marker='s')

ax2.annotate('NM', (min_nm[0], min_nm[1]),
             xytext=(5, 5), textcoords='offset points', fontsize=9, color='red')
ax2.annotate('BFGS', (min_bfgs[0], min_bfgs[1]),
             xytext=(5, -8), textcoords='offset points', fontsize=9, color='blue')

ax2.set_xlabel('x₁')
ax2.set_ylabel('x₂')
ax2.set_title('Линии равного уровня и поле градиента')
ax2.legend(loc='upper right')
ax2.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()