# Программа 2: Градиентный метод с аналитическими частными производными
# Вариант 16
import numpy as np
import scipy.optimize as optim
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 gradient_descent(f, grad, x0, alpha=0.2, eps=1e-6, max_iter=10000):
x = x0.copy()
f_prev = f(x)
iterations = 0
for _ in range(max_iter):
g = grad(x)
if np.linalg.norm(g) < eps:
break
# Адаптивный шаг: уменьшаем, пока функция не уменьшится
step_ok = False
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
step_ok = True
break
alpha *= 0.5
if not step_ok:
break
iterations += 1
return x, f(x), iterations
x0 = np.array([1.0, 0.0])
x_min, f_min, iters = gradient_descent(f, grad, x0, alpha=0.2, eps=1e-6)
print("="*50)
print("Градиентный метод (самостоятельная реализация)")
print(f"Минимум: x = [{x_min[0]:.8f}, {x_min[1]:.8f}]")
print(f"f(x) = {f_min:.10f}")
print(f"Количество итераций: {iters}")
# Проверка через BFGS (встроенный квазиньютоновский метод)
res = optim.minimize(f, x0, method='BFGS', jac=grad, options={'disp': False})
print("\nПроверка через scipy.optimize (method='BFGS'):")
print(f"x = {res.x}")
print(f"f = {res.fun:.10f}")
print("="*50)