diff toolboxes/FullBNT-1.0.7/netlab3.3/minbrack.m @ 0:e9a9cd732c1e tip

first hg version after svn
author wolffd
date Tue, 10 Feb 2015 15:05:51 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toolboxes/FullBNT-1.0.7/netlab3.3/minbrack.m	Tue Feb 10 15:05:51 2015 +0000
@@ -0,0 +1,127 @@
+function  [br_min, br_mid, br_max, num_evals] = minbrack(f, a, b, fa,  ...
+			 varargin)
+%MINBRACK Bracket a minimum of a function of one variable.
+%
+%	Description
+%	BRMIN, BRMID, BRMAX, NUMEVALS] = MINBRACK(F, A, B, FA) finds a
+%	bracket of three points around a local minimum of F.  The function F
+%	must have a one dimensional domain. A < B is an initial guess at the
+%	minimum and maximum points of a bracket, but MINBRACK will search
+%	outside this interval if necessary. The bracket consists of three
+%	points (in increasing order) such that F(BRMID) < F(BRMIN) and
+%	F(BRMID) < F(BRMAX). FA is the value of the function at A: it is
+%	included to avoid unnecessary function evaluations in the
+%	optimization routines. The return value NUMEVALS is the number of
+%	function evaluations in MINBRACK.
+%
+%	MINBRACK(F, A, B, FA, P1, P2, ...) allows additional arguments to be
+%	passed to F
+%
+%	See also
+%	LINEMIN, LINEF
+%
+
+%	Copyright (c) Ian T Nabney (1996-2001)
+
+% Check function string
+f = fcnchk(f, length(varargin));
+
+% Value of golden section (1 + sqrt(5))/2.0
+phi = 1.6180339887499;
+
+% Initialise count of number of function evaluations
+num_evals = 0;
+
+% A small non-zero number to avoid dividing by zero in quadratic interpolation
+TINY = 1.e-10;
+
+% Maximal proportional step to take: don't want to make this too big
+% as then spend a lot of time finding the minimum inside the bracket
+max_step = 10.0;
+
+fb = feval(f, b, varargin{:});
+num_evals = num_evals + 1;
+
+% Assume that we know going from a to b is downhill initially 
+% (usually because gradf(a) < 0).
+if (fb > fa)
+  % Minimum must lie between a and b: do golden section until we find point
+  % low enough to be middle of bracket
+  c = b;
+  b = a + (c-a)/phi;
+  fb = feval(f, b, varargin{:});
+  num_evals = num_evals + 1;
+  while (fb > fa)
+    c = b;
+    b = a + (c-a)/phi;
+    fb = feval(f, b, varargin{:});
+    num_evals = num_evals + 1;
+  end
+else  
+  % There is a valid bracket upper bound greater than b
+  c = b + phi*(b-a);
+  fc = feval(f, c, varargin{:});
+  num_evals = num_evals + 1;
+  bracket_found = 0;
+  
+  while (fb > fc)
+    % Do a quadratic interpolation (i.e. to minimum of quadratic)
+    r = (b-a).*(fb-fc);
+    q = (b-c).*(fb-fa);
+    u = b - ((b-c)*q - (b-a)*r)/(2.0*(sign(q-r)*max([abs(q-r), TINY])));
+    ulimit = b + max_step*(c-b);
+    
+    if ((b-u)'*(u-c) > 0.0)
+      % Interpolant lies between b and c
+      fu = feval(f, u, varargin{:});
+      num_evals = num_evals + 1;
+      if (fu < fc)
+	% Have a minimum between b and c
+	br_min = b;
+	br_mid = u;
+	br_max = c;
+	return;
+      elseif (fu > fb)
+	% Have a minimum between a and u
+	br_min = a;
+	br_mid = c;
+	br_max = u;
+	return;
+      end
+      % Quadratic interpolation didn't give a bracket, so take a golden step
+      u = c + phi*(c-b);
+    elseif ((c-u)'*(u-ulimit) > 0.0)
+      % Interpolant lies between c and limit
+      fu = feval(f, u, varargin{:});
+      num_evals = num_evals + 1;
+      if (fu < fc)
+	% Move bracket along, and then take a golden section step
+	b = c;
+	c = u;
+	u = c + phi*(c-b);
+      else
+	bracket_found = 1;
+      end
+    elseif ((u-ulimit)'*(ulimit-c) >= 0.0)
+      % Limit parabolic u to maximum value
+      u = ulimit;
+    else
+      % Reject parabolic u and use golden section step
+      u = c + phi*(c-b);
+    end
+    if ~bracket_found
+      fu = feval(f, u, varargin{:});
+      num_evals = num_evals + 1;
+    end
+    a = b; b = c; c = u;
+    fa = fb; fb = fc; fc = fu;
+  end % while loop
+end   % bracket found
+br_mid = b;
+if (a < c)
+  br_min = a;
+  br_max = c;
+else
+  br_min = c; 
+  br_max = a;
+end