www.gusucode.com > optim 案例源码 matlab代码程序 > optim/BananaFunctionMinimizationExample.m

    %% Banana Function Minimization
% This example shows how to minimize Rosenbrock's "banana function":                
%
% $$f(x) = 100(x(2)-x(1)^2)^2+(1-x(1))^2 .$$        
%
% $f(x)$ is called the banana function because of its curvature around the
% origin. It is notorious in optimization examples because of the slow
% convergence most methods exhibit when trying to solve this problem.
%                                                            
% $f(x)$ has a unique minimum at the point $x = [1,1]$ where $f(x) = 0$.
% This example shows a number of ways to minimize $f(x)$ starting at the
% point $x0 = [-1.9,2]$.

%% Optimization Without Derivatives
% The |fminsearch| function finds a minimum for a problem without
% constraints. It uses an algorithm that does not estimate any derivatives
% of the objective function. Rather, it uses a geometric search method
% described in <docid:optim_ug.brnoxyk>.
%
% Minimize the banana function using |fminsearch|. Include an output
% function to report the sequence of iterations.

fun = @(x)(100*(x(2) - x(1)^2)^2 + (1 - x(1))^2);
options = optimset('OutputFcn',@bananaout,'Display','off');
x0 = [-1.9,2];
[x,fval,eflag,output] = fminsearch(fun,x0,options);
title 'Rosenbrock solution via fminsearch'
Fcount = output.funcCount;
disp(['Number of function evaluations for fminsearch was ',num2str(Fcount)])
disp(['Number of solver iterations for fminsearch was ',num2str(output.iterations)])

%% Optimization with Estimated Derivatives
% The |fminunc| function finds a minimum for a problem without constraints.
% It uses a derivative-based algorithm. The algorithm attempts to estimate
% not only the first derivative of the objective function, but also the
% matrix of second derivatives. |fminunc| is usually more efficient than
% |fminsearch|.
%
% Minimize the banana function using |fminunc|.

options = optimoptions('fminunc','Display','off',...
    'OutputFcn',@bananaout,'Algorithm','quasi-newton');
[x,fval,eflag,output] = fminunc(fun,x0,options);
title 'Rosenbrock solution via fminunc'
Fcount = output.funcCount;
disp(['Number of function evaluations for fminunc was ',num2str(Fcount)])
disp(['Number of solver iterations for fminunc was ',num2str(output.iterations)])

%% Optimization with Steepest Descent
% If you attempt to minimize the banana function using a steepest descent
% algorithm, the high curvature of the problem makes the solution process
% very slow.
%
% You can run |fminunc| with the steepest descent algorithm by setting the
% hidden |HessUpdate| option to the value |'steepdesc'| for the
% |'quasi-newton'| algorithm. Set a larger-than-default maximum number of
% function evaluations, because the solver does not find the solution
% quickly. In this case, the solver does not find the solution even after
% 600 function evaluations.

options = optimoptions(options,'HessUpdate','steepdesc',...
    'MaxFunctionEvaluations',600);
[x,fval,eflag,output] = fminunc(fun,x0,options);
title 'Rosenbrock solution via steepest descent'
Fcount = output.funcCount;
disp(['Number of function evaluations for steepest descent was ',...
    num2str(Fcount)])
disp(['Number of solver iterations for steepest descent was ',...
    num2str(output.iterations)])

%% Optimization with Analytic Gradient
% If you provide a gradient, |fminunc| solves the optimization using fewer
% function evaluations. When you provide a gradient, you can use the
% |'trust-region'| algorithm, which is often faster and uses less memory
% than the |'quasi-newton'| algorithm. Reset the |HessUpdate| and
% |MaxFunctionEvaluations| options to their default values.

grad = @(x)[-400*(x(2) - x(1)^2)*x(1) - 2*(1 - x(1));
            200*(x(2) - x(1)^2)];
fungrad = @(x)deal(fun(x),grad(x));
options = resetoptions(options,{'HessUpdate','MaxFunctionEvaluations'});
options = optimoptions(options,'SpecifyObjectiveGradient',true,...
    'Algorithm','trust-region');
[x,fval,eflag,output] = fminunc(fungrad,x0,options);
title 'Rosenbrock solution via fminunc with gradient'
Fcount = output.funcCount;
disp(['Number of function evaluations for fminunc with gradient was ',...
    num2str(Fcount)])
disp(['Number of solver iterations for fminunc with gradient was ',...
    num2str(output.iterations)])

%% Optimization with Analytic Hessian
% If you provide a Hessian (matrix of second derivatives), |fminunc| can
% solve the optimization using even fewer function evaluations. For this
% problem the results are the same with or without the Hessian.

hess = @(x)[1200*x(1)^2 - 400*x(2) + 2, -400*x(1);
            -400*x(1), 200];
fungradhess = @(x)deal(fun(x),grad(x),hess(x));
options.HessianFcn = 'objective';
[x,fval,eflag,output] = fminunc(fungradhess,x0,options);
title 'Rosenbrock solution via fminunc with Hessian'
Fcount = output.funcCount;
disp(['Number of function evaluations for fminunc with gradient and Hessian was ',...
    num2str(Fcount)])
disp(['Number of solver iterations for fminunc with gradient and Hessian was ',num2str(output.iterations)])

%% Optimization with a Least Squares Solver
% The recommended solver for a nonlinear sum of squares is |lsqnonlin|.
% This solver is even more efficient than |fminunc| without a gradient for
% this special class of problems. To use |lsqnonlin|, do not write your
% objective as a sum of squares. Instead, write the underlying vector that
% |lsqnonlin| internally squares and sums.

options = optimoptions('lsqnonlin','Display','off','OutputFcn',@bananaout);
vfun = @(x)[10*(x(2) - x(1)^2),1 - x(1)];
[x,resnorm,residual,eflag,output] = lsqnonlin(vfun,x0,[],[],options);
title 'Rosenbrock solution via lsqnonlin'
Fcount = output.funcCount;
disp(['Number of function evaluations for lsqnonlin was ',...
    num2str(Fcount)])
disp(['Number of solver iterations for lsqnonlin was ',num2str(output.iterations)])

%% Optimization with a Least Squares Solver and Jacobian
% As in the minimization using a gradient for |fminunc|, |lsqnonlin| can
% use derivative information to lower the number of function evaluations.
% Provide the Jacobian of the nonlinear objective function vector and run
% the optimization again.

jac = @(x)[-20*x(1),10;
           -1,0];
vfunjac = @(x)deal(vfun(x),jac(x));
options.SpecifyObjectiveGradient = true;
[x,resnorm,residual,eflag,output] = lsqnonlin(vfunjac,x0,[],[],options);
title 'Rosenbrock solution via lsqnonlin with Jacobian'
Fcount = output.funcCount;
disp(['Number of function evaluations for lsqnonlin with Jacobian was ',...
    num2str(Fcount)])
disp(['Number of solver iterations for lsqnonlin with Jacobian was ',...
    num2str(output.iterations)])