diff Code/Descriptors/Matlab/MPEG7/FromWeb/VoiceSauce/fminsearchbnd.m @ 4:92ca03a8fa99 tip

Update to ICASSP 2013 benchmark
author Dawn Black
date Wed, 13 Feb 2013 11:02:39 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Code/Descriptors/Matlab/MPEG7/FromWeb/VoiceSauce/fminsearchbnd.m	Wed Feb 13 11:02:39 2013 +0000
@@ -0,0 +1,304 @@
+function [x,fval,exitflag,output]=fminsearchbnd(fun,x0,LB,UB,options,varargin)
+% FMINSEARCHBND: FMINSEARCH, but with bound constraints by transformation
+% usage: x=FMINSEARCHBND(fun,x0)
+% usage: x=FMINSEARCHBND(fun,x0,LB)
+% usage: x=FMINSEARCHBND(fun,x0,LB,UB)
+% usage: x=FMINSEARCHBND(fun,x0,LB,UB,options)
+% usage: x=FMINSEARCHBND(fun,x0,LB,UB,options,p1,p2,...)
+% usage: [x,fval,exitflag,output]=FMINSEARCHBND(fun,x0,...)
+% 
+% arguments:
+%  fun, x0, options - see the help for FMINSEARCH
+%
+%  LB - lower bound vector or array, must be the same size as x0
+%
+%       If no lower bounds exist for one of the variables, then
+%       supply -inf for that variable.
+%
+%       If no lower bounds at all, then LB may be left empty.
+%
+%       Variables may be fixed in value by setting the corresponding
+%       lower and upper bounds to exactly the same value.
+%
+%  UB - upper bound vector or array, must be the same size as x0
+%
+%       If no upper bounds exist for one of the variables, then
+%       supply +inf for that variable.
+%
+%       If no upper bounds at all, then UB may be left empty.
+%
+%       Variables may be fixed in value by setting the corresponding
+%       lower and upper bounds to exactly the same value.
+%
+% Notes:
+%
+%  If options is supplied, then TolX will apply to the transformed
+%  variables. All other FMINSEARCH parameters should be unaffected.
+%
+%  Variables which are constrained by both a lower and an upper
+%  bound will use a sin transformation. Those constrained by
+%  only a lower or an upper bound will use a quadratic
+%  transformation, and unconstrained variables will be left alone.
+%
+%  Variables may be fixed by setting their respective bounds equal.
+%  In this case, the problem will be reduced in size for FMINSEARCH.
+%
+%  The bounds are inclusive inequalities, which admit the
+%  boundary values themselves, but will not permit ANY function
+%  evaluations outside the bounds. These constraints are strictly
+%  followed.
+%
+%  If your problem has an EXCLUSIVE (strict) constraint which will
+%  not admit evaluation at the bound itself, then you must provide
+%  a slightly offset bound. An example of this is a function which
+%  contains the log of one of its parameters. If you constrain the
+%  variable to have a lower bound of zero, then FMINSEARCHBND may
+%  try to evaluate the function exactly at zero.
+%
+%
+% Example usage:
+% rosen = @(x) (1-x(1)).^2 + 105*(x(2)-x(1).^2).^2;
+%
+% fminsearch(rosen,[3 3])     % unconstrained
+% ans =
+%    1.0000    1.0000
+%
+% fminsearchbnd(rosen,[3 3],[2 2],[])     % constrained
+% ans =
+%    2.0000    4.0000
+%
+% See test_main.m for other examples of use.
+%
+%
+% See also: fminsearch, fminspleas
+%
+%
+% Author: John D'Errico
+% E-mail: woodchips@rochester.rr.com
+% Release: 4
+% Release date: 7/23/06
+
+% size checks
+xsize = size(x0);
+x0 = x0(:);
+n=length(x0);
+
+if (nargin<3) || isempty(LB)
+  LB = repmat(-inf,n,1);
+else
+  LB = LB(:);
+end
+if (nargin<4) || isempty(UB)
+  UB = repmat(inf,n,1);
+else
+  UB = UB(:);
+end
+
+if (n~=length(LB)) || (n~=length(UB))
+  error 'x0 is incompatible in size with either LB or UB.'
+end
+
+% set default options if necessary
+if (nargin<5) || isempty(options)
+  options = optimset('fminsearch');
+end
+
+% stuff into a struct to pass around
+params.args = varargin;
+params.LB = LB;
+params.UB = UB;
+params.fun = fun;
+params.n = n;
+params.OutputFcn = [];
+
+% 0 --> unconstrained variable
+% 1 --> lower bound only
+% 2 --> upper bound only
+% 3 --> dual finite bounds
+% 4 --> fixed variable
+params.BoundClass = zeros(n,1);
+for i=1:n
+  k = isfinite(LB(i)) + 2*isfinite(UB(i));
+  params.BoundClass(i) = k;
+  if (k==3) && (LB(i)==UB(i))
+    params.BoundClass(i) = 4;
+  end
+end
+
+% transform starting values into their unconstrained
+% surrogates. Check for infeasible starting guesses.
+x0u = x0;
+k=1;
+for i = 1:n
+  switch params.BoundClass(i)
+    case 1
+      % lower bound only
+      if x0(i)<=LB(i)
+        % infeasible starting value. Use bound.
+        x0u(k) = 0;
+      else
+        x0u(k) = sqrt(x0(i) - LB(i));
+      end
+      
+      % increment k
+      k=k+1;
+    case 2
+      % upper bound only
+      if x0(i)>=UB(i)
+        % infeasible starting value. use bound.
+        x0u(k) = 0;
+      else
+        x0u(k) = sqrt(UB(i) - x0(i));
+      end
+      
+      % increment k
+      k=k+1;
+    case 3
+      % lower and upper bounds
+      if x0(i)<=LB(i)
+        % infeasible starting value
+        x0u(k) = -pi/2;
+      elseif x0(i)>=UB(i)
+        % infeasible starting value
+        x0u(k) = pi/2;
+      else
+        x0u(k) = 2*(x0(i) - LB(i))/(UB(i)-LB(i)) - 1;
+        % shift by 2*pi to avoid problems at zero in fminsearch
+        % otherwise, the initial simplex is vanishingly small
+        x0u(k) = 2*pi+asin(max(-1,min(1,x0u(k))));
+      end
+      
+      % increment k
+      k=k+1;
+    case 0
+      % unconstrained variable. x0u(i) is set.
+      x0u(k) = x0(i);
+      
+      % increment k
+      k=k+1;
+    case 4
+      % fixed variable. drop it before fminsearch sees it.
+      % k is not incremented for this variable.
+  end
+  
+end
+% if any of the unknowns were fixed, then we need to shorten
+% x0u now.
+if k<=n
+  x0u(k:n) = [];
+end
+
+% were all the variables fixed?
+if isempty(x0u)
+  % All variables were fixed. quit immediately, setting the
+  % appropriate parameters, then return.
+  
+  % undo the variable transformations into the original space
+  x = xtransform(x0u,params);
+  
+  % final reshape
+  x = reshape(x,xsize);
+  
+  % stuff fval with the final value
+  fval = feval(params.fun,x,params.args{:});
+  
+  % fminsearchbnd was not called
+  exitflag = 0;
+  
+  output.iterations = 0;
+  output.funcount = 1;
+  output.algorithm = 'fminsearch';
+  output.message = 'All variables were held fixed by the applied bounds';
+  
+  % return with no call at all to fminsearch
+  return
+end
+
+% Check for an outputfcn. If there is any, then substitute my
+% own wrapper function.
+if ~isempty(options.OutputFcn)
+  params.OutputFcn = options.OutputFcn;
+  options.OutputFcn = @outfun_wrapper;
+end
+
+% now we can call fminsearch, but with our own
+% intra-objective function.
+[xu,fval,exitflag,output] = fminsearch(@intrafun,x0u,options,params);
+
+% undo the variable transformations into the original space
+x = xtransform(xu,params);
+
+% final reshape
+x = reshape(x,xsize);
+
+% Use a nested function as the OutputFcn wrapper
+  function stop = outfun_wrapper(x,varargin);
+    % we need to transform x first
+    xtrans = xtransform(x,params);
+    
+    % then call the user supplied OutputFcn
+    stop = params.OutputFcn(xtrans,varargin{1:(end-1)});
+    
+  end
+
+end % mainline end
+
+% ======================================
+% ========= begin subfunctions =========
+% ======================================
+function fval = intrafun(x,params)
+% transform variables, then call original function
+
+% transform
+xtrans = xtransform(x,params);
+
+% and call fun
+fval = feval(params.fun,xtrans,params.args{:});
+
+end % sub function intrafun end
+
+% ======================================
+function xtrans = xtransform(x,params)
+% converts unconstrained variables into their original domains
+
+xtrans = zeros(1,params.n);
+% k allows some variables to be fixed, thus dropped from the
+% optimization.
+k=1;
+for i = 1:params.n
+  switch params.BoundClass(i)
+    case 1
+      % lower bound only
+      xtrans(i) = params.LB(i) + x(k).^2;
+      
+      k=k+1;
+    case 2
+      % upper bound only
+      xtrans(i) = params.UB(i) - x(k).^2;
+      
+      k=k+1;
+    case 3
+      % lower and upper bounds
+      xtrans(i) = (sin(x(k))+1)/2;
+      xtrans(i) = xtrans(i)*(params.UB(i) - params.LB(i)) + params.LB(i);
+      % just in case of any floating point problems
+      xtrans(i) = max(params.LB(i),min(params.UB(i),xtrans(i)));
+      
+      k=k+1;
+    case 4
+      % fixed variable, bounds are equal, set it at either bound
+      xtrans(i) = params.LB(i);
+    case 0
+      % unconstrained variable.
+      xtrans(i) = x(k);
+      
+      k=k+1;
+  end
+end
+
+end % sub function xtransform end
+
+
+
+
+