changeset 20695:6faaab833605

fminunc.m: Clean up function to meet Octave coding standards. * fminunc.m: Rename xsiz variable to xsz. Use double quotes for strings. Use in-place accumulation operator +=1 instead of ++ for performance. Use '__' prefix and postfix for internal functions. Use two spaces between end of sentence period and start of next sentence. Only calculate third output argument if requested.
author Rik <rik@octave.org>
date Wed, 11 Nov 2015 16:58:18 -0800
parents a7dbc4fc3732
children 0dfeb5c82750
files scripts/optimization/fminunc.m
diffstat 1 files changed, 40 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/optimization/fminunc.m	Mon Feb 03 17:25:32 2014 +0200
+++ b/scripts/optimization/fminunc.m	Wed Nov 11 16:58:18 2015 -0800
@@ -41,7 +41,7 @@
 ## @qcode{"AutoScaling"}.
 ##
 ## If @qcode{"GradObj"} is @qcode{"on"}, it specifies that @var{fcn}, when
-## called with 2 output arguments, also returns the Jacobian matrix of partial
+## called with two output arguments, also returns the Jacobian matrix of partial
 ## first derivatives at the requested point.  @code{TolX} specifies the
 ## termination tolerance for the unknown variables @var{x}, while @code{TolFun}
 ## is a tolerance for the objective function value @var{fval}.  The default is
@@ -80,8 +80,8 @@
 ## (@var{output}), the output gradient (@var{grad}) at the solution @var{x},
 ## and approximate Hessian (@var{hess}) at the solution @var{x}.
 ##
-## Application Notes: If have only a single nonlinear equation of one variable
-## then using @code{fminbnd} is usually a better choice.
+## Application Notes: If the objective function is a single nonlinear equation
+## of one variable then using @code{fminbnd} is usually a better choice.
 ##
 ## The algorithm used by @code{fminsearch} is a gradient search which depends
 ## on the objective function being differentiable.  If the function has
@@ -96,7 +96,7 @@
 function [x, fval, info, output, grad, hess] = fminunc (fcn, x0, options = struct ())
 
   ## Get default options if requested.
-  if (nargin == 1 && ischar (fcn) && strcmp (fcn, 'defaults'))
+  if (nargin == 1 && strcmp (fcn, "defaults"))
     x = optimset ("MaxIter", 400, "MaxFunEvals", Inf,
                   "GradObj", "off", "TolX", 1e-7, "TolFun", 1e-7,
                   "OutputFcn", [], "FunValCheck", "off",
@@ -113,7 +113,7 @@
     fcn = str2func (fcn, "global");
   endif
 
-  xsiz = size (x0);
+  xsz = size (x0);
   n = numel (x0);
 
   has_grad = strcmpi (optimget (options, "GradObj", "off"), "on");
@@ -122,8 +122,8 @@
   maxfev = optimget (options, "MaxFunEvals", Inf);
   outfcn = optimget (options, "OutputFcn");
 
-  ## Get scaling matrix using the TypicalX option. If set to "auto", the
-  ## scaling matrix is estimated using the jacobian.
+  ## Get scaling matrix using the TypicalX option.  If set to "auto", the
+  ## scaling matrix is estimated using the Jacobian.
   typicalx = optimget (options, "TypicalX");
   if (isempty (typicalx))
     typicalx = ones (n, 1);
@@ -140,7 +140,7 @@
     fcn = @(x) guarded_eval (fcn, x);
   endif
 
-  ## These defaults are rather stringent. I think that normally, user
+  ## These defaults are rather stringent.  I think that normally, user
   ## prefers accuracy to performance.
 
   macheps = eps (class (x0));
@@ -159,7 +159,7 @@
   info = 0;
 
   ## Initial evaluation.
-  fval = fcn (reshape (x, xsiz));
+  fval = fcn (reshape (x, xsz));
   n = length (x);
 
   if (! isempty (outfcn))
@@ -167,7 +167,7 @@
     optimvalues.funccount = nfev;
     optimvalues.fval = fval;
     optimvalues.searchdirection = zeros (n, 1);
-    state = 'init';
+    state = "init";
     stop = outfcn (x, optimvalues, state);
     if (stop)
       info = -1;
@@ -187,11 +187,11 @@
 
     ## Calculate function value and gradient (possibly via FD).
     if (has_grad)
-      [fval, grad] = fcn (reshape (x, xsiz));
+      [fval, grad] = fcn (reshape (x, xsz));
       grad = grad(:);
-      nfev ++;
+      nfev += 1;
     else
-      grad = __fdjac__ (fcn, reshape (x, xsiz), fval, typicalx, cdif)(:);
+      grad = __fdjac__ (fcn, reshape (x, xsz), fval, typicalx, cdif)(:);
       nfev += (1 + cdif) * length (x);
     endif
 
@@ -202,11 +202,11 @@
       ## Use the damped BFGS formula.
       y = grad - grad0;
       sBs = sumsq (w);
-      Bs = hesr'*w;
-      sy = y'*s;
+      Bs = hesr' * w;
+      sy = y' * s;
       theta = 0.8 / max (1 - sy / sBs, 0.8);
       r = theta * y + (1-theta) * Bs;
-      hesr = cholupdate (hesr, r / sqrt (s'*r), "+");
+      hesr = cholupdate (hesr, r / sqrt (s' * r), "+");
       [hesr, info] = cholupdate (hesr, Bs / sqrt (sBs), "-");
       if (info)
         hesr = eye (n);
@@ -214,8 +214,8 @@
     endif
 
     if (autoscale)
-      ## Second derivatives approximate the hessian.
-      d2f = norm (hesr, 'columns').';
+      ## Second derivatives approximate the Hessian.
+      d2f = norm (hesr, "columns").';
       if (niter == 1)
         dg = d2f;
       else
@@ -251,8 +251,8 @@
         delta = min (delta, sn);
       endif
 
-      fval1 = fcn (reshape (x + s, xsiz)) (:);
-      nfev ++;
+      fval1 = fcn (reshape (x + s, xsz))(:);
+      nfev += 1;
 
       if (fval1 < fval)
         ## Scaled actual reduction.
@@ -261,7 +261,7 @@
         actred = -1;
       endif
 
-      w = hesr*s;
+      w = hesr * s;
       ## Scaled predicted reduction, and ratio.
       t = 1/2 * sumsq (w) + grad'*s;
       if (t < 0)
@@ -276,7 +276,7 @@
       if (ratio < min (max (0.1, 0.8*lastratio), 0.9))
         delta *= decfac;
         decfac ^= 1.4142;
-        if (delta <= 1e1*macheps*xn)
+        if (delta <= 10*macheps*xn)
           ## Trust region became uselessly small.
           info = -3;
           break;
@@ -300,7 +300,7 @@
         suc = true;
       endif
 
-      niter ++;
+      niter += 1;
 
       ## FIXME: should outputfcn be called only after a successful iteration?
       if (! isempty (outfcn))
@@ -308,7 +308,7 @@
         optimvalues.funccount = nfev;
         optimvalues.fval = fval;
         optimvalues.searchdirection = s;
-        state = 'iter';
+        state = "iter";
         stop = outfcn (x, optimvalues, state);
         if (stop)
           info = -1;
@@ -316,18 +316,18 @@
         endif
       endif
 
-      ## Tests for termination conditions. A mysterious place, anything
+      ## Tests for termination conditions.  A mysterious place, anything
       ## can happen if you change something here...
 
       ## The rule of thumb (which I'm not sure M*b is quite following)
       ## is that for a tolerance that depends on scaling, only 0 makes
-      ## sense as a default value. But 0 usually means uselessly long
+      ## sense as a default value.  But 0 usually means uselessly long
       ## iterations, so we need scaling-independent tolerances wherever
       ## possible.
 
       ## The following tests done only after successful step.
       if (ratio >= 1e-4)
-        ## This one is classic. Note that we use scaled variables again,
+        ## This one is classic.  Note that we use scaled variables again,
         ## but compare to scaled step, so nothing bad.
         if (sn <= tolx*xn)
           info = 2;
@@ -340,14 +340,14 @@
     endwhile
   endwhile
 
-  ## When info != 1, recalculate the gradient and hessian using the final x.
+  ## When info != 1, recalculate the gradient and Hessian using the final x.
   if (nargout > 4 && (info == -1 || info == 2 || info == 3))
     grad0 = grad;  
     if (has_grad)
-      [fval, grad] = fcn (reshape (x, xsiz));
+      [fval, grad] = fcn (reshape (x, xsz));
       grad = grad(:);
     else
-      grad = __fdjac__ (fcn, reshape (x, xsiz), fval, typicalx, cdif)(:);
+      grad = __fdjac__ (fcn, reshape (x, xsz), fval, typicalx, cdif)(:);
     endif
     
     if (nargout > 5)
@@ -362,15 +362,17 @@
       hesr = cholupdate (hesr, Bs / sqrt (sBs), "-");
     endif
     ## Return the gradient in the same shape as x
-    grad = reshape (grad, xsiz);
+    grad = reshape (grad, xsz);
   endif
 
   ## Restore original shapes.
-  x = reshape (x, xsiz);
+  x = reshape (x, xsz);
 
-  output.iterations = niter;
-  output.successful = nsuciter;
-  output.funcCount = nfev;
+  if (nargout > 3)
+    output.iterations = niter;
+    output.successful = nsuciter;
+    output.funcCount = nfev;
+  endif
 
   if (nargout > 5)
     hess = hesr'*hesr;
@@ -397,19 +399,19 @@
 endfunction
 
 
-%!function f = __rosenb (x)
+%!function f = __rosenb__ (x)
 %!  n = length (x);
 %!  f = sumsq (1 - x(1:n-1)) + 100 * sumsq (x(2:n) - x(1:n-1).^2);
 %!endfunction
 %!
 %!test
-%! [x, fval, info, out] = fminunc (@__rosenb, [5, -5]);
+%! [x, fval, info, out] = fminunc (@__rosenb__, [5, -5]);
 %! tol = 2e-5;
 %! assert (info > 0);
 %! assert (x, ones (1, 2), tol);
 %! assert (fval, 0, tol);
 %!test
-%! [x, fval, info, out] = fminunc (@__rosenb, zeros (1, 4));
+%! [x, fval, info, out] = fminunc (@__rosenb__, zeros (1, 4));
 %! tol = 2e-5;
 %! assert (info > 0);
 %! assert (x, ones (1, 4), tol);