%% Supply Gradient
% fminunc can be faster and more reliable when you provide derivatives.
% Write an objective function that returns the gradient as well as the function value. Use the conditionalized form described in Including Gradients and Hessians. The objective function is Rosenbrock's function,
% \[f(x) = 100{\left( {{x_2} - x_1^2} \right)^2} + {(1 - {x_1})^2},\]
% which has gradient
% \[\nabla f(x) = \left[ {\begin{array}{*{20}{c}}
% { - 400\left( {{x_2} - x_1^2} \right){x_1} - 2\left( {1 - {x_1}} \right)}\\
% {200\left( {{x_2} - x_1^2} \right)}
% \end{array}} \right]\].
% The code for the objective function with gradient appears at the end of this example.
% Create options to use the objective function’s gradient. Also, set the algorithm to 'trust-region'.

options = optimoptions('fminunc','Algorithm','trust-region','SpecifyObjectiveGradient',true);

% Set the initial point to [-1,2]. Then call fminunc.

x0 = [-1,2];
fun = @rosenbrockwithgrad;
x = fminunc(fun,x0,options)

%
% The following code creates the rosenbrockwithgrad function, which includes the gradient as the second output.

function [f,g] = rosenbrockwithgrad(x)
% Calculate objective f
f = 100*(x(2) - x(1)^2)^2 + (1-x(1))^2;

if nargout > 1 % gradient required
    g = [-400*(x(2)-x(1)^2)*x(1) - 2*(1-x(1));
        200*(x(2)-x(1)^2)];
end
end

% Copyright 2019 The MathWorks, Inc.