www.gusucode.com > optim 案例源码 matlab代码程序 > optim/OptimizeANonsmoothFunctionExample.m
%% Optimize a Nonsmooth Function % This example shows the importance of choosing an appropriate solver. It % also shows that a single point of non-smoothness can cause failures in % Optimization Toolbox(TM) solvers, and that appropriate option choices can % alleviate these failures. %% A Function with a Single Nonsmooth Point % The function $f(x) = \sqrt{||x||}$ is nonsmooth only at the % point 0, which is the minimizing point: figure fsurf(@(x,y)(x.^2 + y.^2).^(1/4)) %% Minimize Using |fminsearch| % Start |fminsearch| from a nonzero six-dimensional point and attempt to % locate the minimum of $f$. The documentation states that |fminsearch| % sometimes can handle discontinuities, so this is a reasonable first try. fun = @(x)sqrt(norm(x)); x0 = [1,2;3,4;5,6]; rng default x0 = x0 + rand(size(x0)) [xfms,fvalfms,eflagfms,outputfms] = fminsearch(fun,x0) %% % |fminsearch| did not substantially improve the initial point, and took % hundreds of function evaluations. %% Use |patternsearch| % |patternsearch| is the recommended first solver to try for nonsmooth % problems. See <docid:gads.bsa_e9p>. [xps,fvalps,eflagps,outputps] = patternsearch(fun,x0) %% % |patternsearch| reached a good solution, but took about 2,000 function % evaluations to do so. %% Use |particleswarm| % |particleswarm| is recommended as the next solver to try. See % <docid:gads.bu9r6hl-6>. [xpsw,fvalpsw,eflagpsw,outputpsw] = particleswarm(fun,6) %% % |particleswarm| found an accurate solution, but took over 15,000 function % evaluations. %% Use |ga| % |ga| is a popular solver, but is not recommended as the first solver to % try. See how well it works on this problem. [xga,fvalga,eflagga,outputga] = ga(fun,6) %% % |ga| did not find as good a solution as |patternsearch| or % |particleswarm|, and took over 50,000 function evaluations. %% Use Optimization Toolbox Solvers % |fminunc| does not produce an accurate solution, though it does halt % after relatively few function evaluations. options = optimoptions('fminunc','Algorithm','quasi-newton'); [xfmu,fvalfmu,eflagfmu,outputfmu] = fminunc(fun,x0,options) %% % However, |fmincon| with default options produces an accurate solution % with fewer than 500 function evaluations. [xfmc,fvalfmc,eflagfmc,outputfmc] = fmincon(fun,x0) %% Use Symbolic Gradients and Hessian for Better, Faster Results % If you have Symbolic Math Toolbox(TM), you can improve the preformance % and robustness of Optimization Toolbox solvers. % % Compute the gradients and Hessian of the objective function symbolically, % and use |matlabFunction| to turn the symbolic calculation into a function % handle. For more examples of this method of obtaining derivatives for the % objective function, see <docid:optim_ug.brv_i_1> or % <docid:optim_examples.example-ex44573088>. x = sym('x%d%d',[3,2],'real'); y = norm(x(:))^(1/2); jy = jacobian(y,x(:)).'; hy = jacobian(jy,x(:)); spikefun = matlabFunction(y,jy,hy,'vars',{x}); %% % Use |spikefun| as the objective function for |fminunc|, along with % options to use the associated gradient and Hessian. options = optimoptions('fminunc','Algorithm','trust-region',... 'SpecifyObjectiveGradient',true,'HessianFcn','objective'); [xfmu2,fvalfmu2,eflagfmu2,outputfmu2] = fminunc(spikefun,x0,options) %% % This time, |fminunc| solved the problem accurately, and with only 30 % function evaluations. %% Summary of Results % Choosing the appropriate solver and options leads to better, faster % results. This summary shows how variable results can be. disp('Solver Solution quality Number of Function Evaluations') disp(['fminsearch Bad ',num2str(outputfms.funcCount)]) disp(['patternsearch Good ',num2str(outputps.funccount)]) disp(['particleswarm Good ',num2str(outputpsw.funccount)]) disp(['ga Mediocre ',num2str(outputga.funccount)]) disp(['fminunc Mediocre ',num2str(outputfmu.funcCount)]) disp(['fmincon Good ',num2str(outputfmc.funcCount)]) disp(['fminunc+derivatives Good ',num2str(outputfmu2.funcCount)])