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


# Создание сетки для графиков
# У этой функции минимумы находятся примерно в (+/- 0.275, +/- 0.076)
# Сделаем диапазон пошире, чтобы увидеть рельеф
x_vals = np.linspace(-1.5, 3.5, 100)
y_vals = np.linspace(-1.5, 3.5, 100)
X, Y = np.meshgrid(x_vals, y_vals)
Z = f([X, Y])

fig = plt.figure(figsize=(14, 6))

# 3D Поверхность
ax1 = fig.add_subplot(121, projection='3d')
ax1.plot_surface(X, Y, Z, cmap='viridis', alpha=0.8)
ax1.set_title('Поверхность функции')

# Линии уровня и градиенты (Quiver)
ax2 = fig.add_subplot(122)
cp = ax2.contour(X, Y, Z, levels=50)
plt.colorbar(cp)

# Рисуем стрелки градиентов (на редкой сетке)
x_q = np.linspace(-1, 3, 15)
y_q = np.linspace(-1, 3, 15)
XQ, YQ = np.meshgrid(x_q, y_q)
GQ = grad_f([XQ, YQ])
ax2.quiver(XQ, YQ, -GQ[0], -GQ[1], color='red', alpha=0.5, scale=50, label='Антиградиент')

# Наносим найденные минимумы
ax2.plot(res_nm_custom[0], res_nm_custom[1], 'm*', markersize=12, label='Min (Nelder-Mead)')
ax2.plot(res_grad_custom[0], res_grad_custom[1], 'cx', markersize=10, label='Min (Gradient)')

# Поскольку минимума два (симметричных), отметим и второй для полноты картины
second_min = minimize(f, [-1, -1]).x
ax2.plot(second_min[0], second_min[1], 'ro', markersize=5, label='Второй минимум')

ax2.set_title('Линии уровня и градиенты')
ax2.legend()
plt.show()