Home > nisdet > auxiliary > optimization > fminsearchbnd.m

fminsearchbnd

PURPOSE ^

FMINSEARCHBND: FMINSEARCH, but with bound constraints by transformation

SYNOPSIS ^

function [x,fval,exitflag,output]=fminsearchbnd3(fun,x0,LB,UB,options,varargin)

DESCRIPTION ^

 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
 Downloaded at: http://math.nyu.edu/~atm262/files/takeover/fminsearchbnd.m

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function [x,fval,exitflag,output]=fminsearchbnd3(fun,x0,LB,UB,options,varargin)
0002 % FMINSEARCHBND: FMINSEARCH, but with bound constraints by transformation
0003 % usage: x=FMINSEARCHBND(fun,x0)
0004 % usage: x=FMINSEARCHBND(fun,x0,LB)
0005 % usage: x=FMINSEARCHBND(fun,x0,LB,UB)
0006 % usage: x=FMINSEARCHBND(fun,x0,LB,UB,options)
0007 % usage: x=FMINSEARCHBND(fun,x0,LB,UB,options,p1,p2,...)
0008 % usage: [x,fval,exitflag,output]=FMINSEARCHBND(fun,x0,...)
0009 %
0010 % arguments:
0011 %  fun, x0, options - see the help for FMINSEARCH
0012 %
0013 %  LB - lower bound vector or array, must be the same size as x0
0014 %
0015 %       If no lower bounds exist for one of the variables, then
0016 %       supply -inf for that variable.
0017 %
0018 %       If no lower bounds at all, then LB may be left empty.
0019 %
0020 %       Variables may be fixed in value by setting the corresponding
0021 %       lower and upper bounds to exactly the same value.
0022 %
0023 %  UB - upper bound vector or array, must be the same size as x0
0024 %
0025 %       If no upper bounds exist for one of the variables, then
0026 %       supply +inf for that variable.
0027 %
0028 %       If no upper bounds at all, then UB may be left empty.
0029 %
0030 %       Variables may be fixed in value by setting the corresponding
0031 %       lower and upper bounds to exactly the same value.
0032 %
0033 % Notes:
0034 %
0035 %  If options is supplied, then TolX will apply to the transformed
0036 %  variables. All other FMINSEARCH parameters should be unaffected.
0037 %
0038 %  Variables which are constrained by both a lower and an upper
0039 %  bound will use a sin transformation. Those constrained by
0040 %  only a lower or an upper bound will use a quadratic
0041 %  transformation, and unconstrained variables will be left alone.
0042 %
0043 %  Variables may be fixed by setting their respective bounds equal.
0044 %  In this case, the problem will be reduced in size for FMINSEARCH.
0045 %
0046 %  The bounds are inclusive inequalities, which admit the
0047 %  boundary values themselves, but will not permit ANY function
0048 %  evaluations outside the bounds. These constraints are strictly
0049 %  followed.
0050 %
0051 %  If your problem has an EXCLUSIVE (strict) constraint which will
0052 %  not admit evaluation at the bound itself, then you must provide
0053 %  a slightly offset bound. An example of this is a function which
0054 %  contains the log of one of its parameters. If you constrain the
0055 %  variable to have a lower bound of zero, then FMINSEARCHBND may
0056 %  try to evaluate the function exactly at zero.
0057 %
0058 %
0059 % Example usage:
0060 % rosen = @(x) (1-x(1)).^2 + 105*(x(2)-x(1).^2).^2;
0061 %
0062 % fminsearch(rosen,[3 3])     % unconstrained
0063 % ans =
0064 %    1.0000    1.0000
0065 %
0066 % fminsearchbnd(rosen,[3 3],[2 2],[])     % constrained
0067 % ans =
0068 %    2.0000    4.0000
0069 %
0070 % See test_main.m for other examples of use.
0071 %
0072 %
0073 % See also: fminsearch, fminspleas
0074 %
0075 %
0076 % Author: John D'Errico
0077 % E-mail: woodchips@rochester.rr.com
0078 % Release: 4
0079 % Release date: 7/23/06
0080 % Downloaded at: http://math.nyu.edu/~atm262/files/takeover/fminsearchbnd.m
0081 %
0082 %
0083   
0084 % size checks
0085 xsize = size(x0);
0086 x0 = x0(:);
0087 n=length(x0);
0088 
0089 if (nargin<3) || isempty(LB)
0090   LB = repmat(-inf,n,1);
0091 else
0092   LB = LB(:);
0093 end
0094 if (nargin<4) || isempty(UB)
0095   UB = repmat(inf,n,1);
0096 else
0097   UB = UB(:);
0098 end
0099 
0100 if (n~=length(LB)) || (n~=length(UB))
0101   error 'x0 is incompatible in size with either LB or UB.'
0102 end
0103 
0104 % set default options if necessary
0105 if (nargin<5) || isempty(options)
0106   options = optimset('fminsearch');
0107 end
0108 
0109 % stuff into a struct to pass around
0110 params.args = varargin;
0111 params.LB = LB;
0112 params.UB = UB;
0113 params.fun = fun;
0114 params.n = n;
0115 params.OutputFcn = [];
0116 
0117 % 0 --> unconstrained variable
0118 % 1 --> lower bound only
0119 % 2 --> upper bound only
0120 % 3 --> dual finite bounds
0121 % 4 --> fixed variable
0122 params.BoundClass = zeros(n,1);
0123 for i=1:n
0124   k = isfinite(LB(i)) + 2*isfinite(UB(i));
0125   params.BoundClass(i) = k;
0126   if (k==3) && (LB(i)==UB(i))
0127     params.BoundClass(i) = 4;
0128   end
0129 end
0130 
0131 % transform starting values into their unconstrained
0132 % surrogates. Check for infeasible starting guesses.
0133 x0u = x0;
0134 k=1;
0135 for i = 1:n
0136   switch params.BoundClass(i)
0137     case 1
0138       % lower bound only
0139       if x0(i)<=LB(i)
0140         % infeasible starting value. Use bound.
0141         x0u(k) = 0;
0142       else
0143         x0u(k) = sqrt(x0(i) - LB(i));
0144       end
0145       
0146       % increment k
0147       k=k+1;
0148     case 2
0149       % upper bound only
0150       if x0(i)>=UB(i)
0151         % infeasible starting value. use bound.
0152         x0u(k) = 0;
0153       else
0154         x0u(k) = sqrt(UB(i) - x0(i));
0155       end
0156       
0157       % increment k
0158       k=k+1;
0159     case 3
0160       % lower and upper bounds
0161       if x0(i)<=LB(i)
0162         % infeasible starting value
0163         x0u(k) = -pi/2;
0164       elseif x0(i)>=UB(i)
0165         % infeasible starting value
0166         x0u(k) = pi/2;
0167       else
0168         x0u(k) = 2*(x0(i) - LB(i))/(UB(i)-LB(i)) - 1;
0169         % shift by 2*pi to avoid problems at zero in fminsearch
0170         % otherwise, the initial simplex is vanishingly small
0171         x0u(k) = 2*pi+asin(max(-1,min(1,x0u(k))));
0172       end
0173       
0174       % increment k
0175       k=k+1;
0176     case 0
0177       % unconstrained variable. x0u(i) is set.
0178       x0u(k) = x0(i);
0179       
0180       % increment k
0181       k=k+1;
0182     case 4
0183       % fixed variable. drop it before fminsearch sees it.
0184       % k is not incremented for this variable.
0185   end
0186   
0187 end
0188 % if any of the unknowns were fixed, then we need to shorten
0189 % x0u now.
0190 if k<=n
0191   x0u(k:n) = [];
0192 end
0193 
0194 % were all the variables fixed?
0195 if isempty(x0u)
0196   % All variables were fixed. quit immediately, setting the
0197   % appropriate parameters, then return.
0198   
0199   % undo the variable transformations into the original space
0200   x = xtransform(x0u,params);
0201   
0202   % final reshape
0203   x = reshape(x,xsize);
0204   
0205   % stuff fval with the final value
0206   fval = feval(params.fun,x,params.args{:});
0207   
0208   % fminsearchbnd was not called
0209   exitflag = 0;
0210   
0211   output.iterations = 0;
0212   output.funcount = 1;
0213   output.algorithm = 'fminsearch';
0214   output.message = 'All variables were held fixed by the applied bounds';
0215   
0216   % return with no call at all to fminsearch
0217   return
0218 end
0219 
0220 % Check for an outputfcn. If there is any, then substitute my
0221 % own wrapper function.
0222 if ~isempty(options.OutputFcn)
0223   params.OutputFcn = options.OutputFcn;
0224   options.OutputFcn = @outfun_wrapper;
0225 end
0226 
0227 % now we can call fminsearch, but with our own
0228 % intra-objective function.
0229 [xu,fval,exitflag,output] = fminsearch(@intrafun,x0u,options,params);
0230 
0231 % undo the variable transformations into the original space
0232 x = xtransform(xu,params);
0233 
0234 % final reshape
0235 x = reshape(x,xsize);
0236 
0237 % Use a nested function as the OutputFcn wrapper
0238   function stop = outfun_wrapper(x,varargin);
0239     % we need to transform x first
0240     xtrans = xtransform(x,params);
0241     
0242     % then call the user supplied OutputFcn
0243     stop = params.OutputFcn(xtrans,varargin{1:(end-1)});
0244     
0245   end
0246 
0247 end % mainline end
0248 
0249 % ======================================
0250 % ========= begin subfunctions =========
0251 % ======================================
0252 function fval = intrafun(x,params)
0253 % transform variables, then call original function
0254 
0255 % transform
0256 xtrans = xtransform(x,params);
0257 
0258 % and call fun
0259 fval = feval(params.fun,xtrans,params.args{:});
0260 
0261 end % sub function intrafun end
0262 
0263 % ======================================
0264 function xtrans = xtransform(x,params)
0265 % converts unconstrained variables into their original domains
0266 
0267 xtrans = zeros(1,params.n);
0268 % k allows some variables to be fixed, thus dropped from the
0269 % optimization.
0270 k=1;
0271 for i = 1:params.n
0272   switch params.BoundClass(i)
0273     case 1
0274       % lower bound only
0275       xtrans(i) = params.LB(i) + x(k).^2;
0276       
0277       k=k+1;
0278     case 2
0279       % upper bound only
0280       xtrans(i) = params.UB(i) - x(k).^2;
0281       
0282       k=k+1;
0283     case 3
0284       % lower and upper bounds
0285       xtrans(i) = (sin(x(k))+1)/2;
0286       xtrans(i) = xtrans(i)*(params.UB(i) - params.LB(i)) + params.LB(i);
0287       % just in case of any floating point problems
0288       xtrans(i) = max(params.LB(i),min(params.UB(i),xtrans(i)));
0289       
0290       k=k+1;
0291     case 4
0292       % fixed variable, bounds are equal, set it at either bound
0293       xtrans(i) = params.LB(i);
0294     case 0
0295       % unconstrained variable.
0296       xtrans(i) = x(k);
0297       
0298       k=k+1;
0299   end
0300 end
0301 
0302 end % sub function xtransform end
0303 
0304 
0305 
0306 
0307

Generated on Sun 07-Feb-2010 08:38:39 by m2html © 2005