clear; clc;
%% Rosenbrock
a = 1;
b = 100;
f = @(x) (a-x(1)).^2 + b*(x(2)-x(1).^2).^2;

%% Pick a common initial guess
x0 = [1.2; 1.2];

%% Method 1: call Matlab's minimizer
%  with just the cost function
options = optimoptions('fminunc', ...
                       'Display', 'iter');
x1 = fminunc(f, x0, options);

%% Method 1 bis: call that minimizer but
%                also specify the gradient
g = @(x) [ -2*(a-x(1)) - 4*b*(x(2)-x(1).^2).*x(1) ;
           2*b*(x(2)-x(1).^2)];
options = optimoptions( ...
            'fminunc', 'Display', 'iter', ...
            'SpecifyObjectiveGradient', true);
x2 = fminunc(@(x) cost_and_grad(x, f, g), ...
             x0, options);

%% Method 2: use the Manopt toolbox
problem.M = euclideanfactory(2, 1);
problem.cost = f;
problem.grad = g;
checkgradient(problem);
%%
x3 = steepestdescent(problem, x0);
%%
x4 = trustregions(problem, x0);


%% Function definitions must come at the very end (Matlab's rule)
function [cost, grad] = cost_and_grad(x, f, g)
    cost = f(x);
    grad = g(x);
end
