import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize
# 1. Определение функции и её градиента
def f(x):
return x[0]**4 + 2*x[1]**2 - 1.1*x[0]*x[1]
# Аналитические производные (для градиентного метода)
def grad_f(x):
df_dx1 = 4 * x[0]**3 - 1.1 * x[1]
df_dx2 = 4 * x[1] - 1.1 * x[0]
return np.array([df_dx1, df_dx2])
# Реализация метода Нелдера-Мида (на основе вашего фото)
def simplex_method(f, x_start, eps=1e-9, alpha=1, beta=0.5, gamma=2, sigma=0.5):
# Создаем начальный симплекс (3 точки для 2D)
x = np.stack((x_start, x_start + [0.5, 0], x_start + [0, 0.5]), axis=-1)
it = 0
while True:
fx = f(x)
ix = np.argsort(fx)
x = x[:, ix]
fx = fx[ix]
if np.std(fx) < eps: break
xo = np.mean(x[:, :-1], axis=1) # Центроид
xr = xo + alpha * (xo - x[:, -1]) # Отражение
fxr = f(xr)
if fx[0] <= fxr < fx[-2]:
x[:, -1] = xr
elif fxr < fx[0]:
xe = xo + gamma * (xr - xo) # Растяжение
x[:, -1] = xe if f(xe) < fxr else xr
else:
xc = xo + beta * (x[:, -1] - xo) # Сжатие
if f(xc) < fx[-1]:
x[:, -1] = xc
else:
x = x[:, [0]] + sigma * (x - x[:, [0]]) # Редукция
it += 1
return x[:, 0], f(x[:, 0]), it
# Тестирование
x_start = np.array([3.0, 3.0])
res_nm_custom, f_nm_custom, it_nm = simplex_method(f, x_start)
# Сравнение с решателем scipy
res_nm_scipy = minimize(f, x_start, method='Nelder-Mead')
print("--- Метод Нелдера-Мида ---")
print(f"Своя реализация: точка {res_nm_custom}, f = {f_nm_custom}, итераций: {it_nm}")
print(f"Scipy реализация: точка {res_nm_scipy.x}, f = {res_nm_scipy.fun}")