def gradient_descent(f, grad, x_start, lr=0.01, eps=1e-7, max_it=10000):
x = x_start.copy()
for i in range(max_it):
g = grad(x)
if np.linalg.norm(g) < eps:
break
x = x - lr * g
return x, f(x), i
# Тестирование
res_grad_custom, f_grad_custom, it_grad = gradient_descent(f, grad_f, x_start)
# Сравнение с BFGS
res_bfgs_scipy = minimize(f, x_start, method='BFGS', jac=grad_f)
print("\n--- Градиентный метод ---")
print(f"Своя реализация: точка {res_grad_custom}, f = {f_grad_custom}, итераций: {it_grad}")
print(f"Scipy (BFGS): точка {res_bfgs_scipy.x}, f = {res_bfgs_scipy.fun}")