You are on page 1of 17

function [X,FVAL,EXITFLAG,OUTPUT] = patternsearch(FUN,initialX,Aineq,Bineq,Aeq,Beq,LB,UB,nonlcon,options) %PATTERNSEARCH Constrained optimization using pattern search.

% PATTERNSEARCH attempts to solve problems of the form: % % % % % X = PATTERNSEARCH(FUN,X0) starts at X0 and finds a local minimum X to % the function FUN. FUN accepts input X and returns a scalar function % value evaluated at X. X0 may be a scalar or vector. % % X = PATTERNSEARCH(FUN,X0,A,b) starts at X0 and finds a local minimum X % to the function FUN, subject to the linear inequalities A*X <= B. % % X = PATTERNSEARCH(FUN,X0,A,b,Aeq,beq) starts at X0 and finds a local % minimum X to the function FUN, subject to the linear equalities % Aeq*X = Beq as well as A*X <= B. (Set A=[] and B=[] if no inequalities % exist.) % % X = PATTERNSEARCH(FUN,X0,A,b,Aeq,beq,LB,UB) defines a set of lower and % upper bounds on the design variables, X, so that a solution is found in % the range LB <= X <= UB. Use empty matrices for LB and UB if no bounds % exist. Set LB(i) = -Inf if X(i) is unbounded below; set UB(i) = Inf if % X(i) is unbounded above. % % X = PATTERNSEARCH(FUN,X0,A,b,Aeq,beq,LB,UB,NONLCON) subjects the % minimization to the constraints defined in NONLCON. The function % NONLCON accepts X and returns the vectors C and Ceq, representing the % nonlinear inequalities and equalities respectively. PATTERNSEARCH % minimizes FUN such that C(X)<=0 and Ceq(X)=0. (Set LB=[] and/or UB=[] % if no bounds exist.) % min F(X) subject to: A*X <= B, Aeq*X = Beq (linear constraints) X C(X) <= 0, Ceq(X) = 0 (nonlinear constraints) LB <= X <= UB

% X = PATTERNSEARCH(FUN,X0,A,b,Aeq,beq,LB,UB,NONLCON,options) minimizes % with the default optimization parameters replaced by values in the % structure OPTIONS. OPTIONS can be created with the PSOPTIMSET function. % See PSOPTIMSET for details. % % X = PATTERNSEARCH(PROBLEM) finds the minimum for PROBLEM. PROBLEM is a % structure that has the following fields: % % % % % % % % % % % % objective: <Objective function> x0: <Starting point> Aineq: <A matrix for inequality constraints> bineq: <B vector for inequality constraints> Aeq: <A matrix for equality constraints> beq: <B vector for equality constraints> lb: <Lower bound on X> ub: <Upper bound on X> nonlcon: <Nonlinear constraint function> options: <options structure created with PSOPTIMSET> solver: <solver name 'patternsearch'> rngstate: <State of the random number generator>

% This syntax is specially useful if you export a problem from % PSEARCHTOOL and use it from the command line to call PATTERNSEARCH. % NOTE: PROBLEM must have all the fields as specified above. % % [X,FVAL] = PATTERNSEARCH(FUN,X0,...) returns FVAL, the value of the % objective function FUN at the solution X. % % [X,FVAL,EXITFLAG] = PATTERNSEARCH(FUN,X0,...) returns EXITFLAG which % describes the exit condition of PATTERNSEARCH. Possible values of % EXITFLAG and the corresponding exit conditions are % % % % 1 Magnitude of mesh size is less than specified tolerance and constraint violation less than options.TolCon. 2 Change in X less than the specified tolerance and

% % % % % %

constraint violation less than options.TolCon. 3 Change in FVAL less than the specified tolerance and constraint violation less than options.TolCon. 4 Magnitude of step smaller than machine precision and constraint violation less than options.TolCon. 0 Maximum number of function evaluations or iterations reached.

% -1 Optimization terminated by the output or plot function. % -2 No feasible point found. % % [X,FVAL,EXITFLAG,OUTPUT] = PATTERNSEARCH(FUN,X0,...) returns a % structure OUTPUT with the following information: % % % % % % % % % % % % Examples: % FUN can be a function handle (using @) % X = patternsearch(@lincontest6, ...) function: <Objective function> problemtype: <Type of problem> (Unconstrained, Bound constrained or linear constrained) pollmethod: <Polling technique> searchmethod: <Search technique used>, if any iterations: <Total iterations> funccount: <Total function evaluations> meshsize: <Mesh size at X> maxconstraint: <Maximum constraint violation>, if any message: <PATTERNSEARCH termination message>

% In this case, F = lincontest6(X) returns the scalar function % value F of the function evaluated at X. % % An example with inequality constraints and lower bounds % A = [1 1; -1 2; 2 1]; b = [2; 2; 3]; lb = zeros(2,1); % [X,FVAL,EXITFLAG] = patternsearch(@lincontest6,[0 0],A,b,[],[],lb); % % FUN can also be an anonymous function:

% % %

X = patternsearch(@(x) 3*sin(x(1))+exp(x(2)),[1;1],[],[],[],[],[0 0]) returns X = [0;0].

% If FUN or NONLCON are parameterized, you can use anonymous functions to % capture the problem-dependent parameters. Suppose you want to minimize % the objective given in the function myobj, subject to the nonlinear % constraint myconstr, where these two functions are parameterized by % their second argument a1 and a2, respectively. Here myfit and myconstr % are MATLAB file functions such as % % % % % and % % % % % % % % To optimize for specific values of a1 and a2, first assign the values % to these two parameters. Then create two one-argument anonymous % functions that capture the values of a1 and a2, and call myobj and % myconstr with two arguments. Finally, pass these anonymous functions to % PATTERNSEARCH: % % % % % % See also PSOPTIMSET, GA, PSOUTPUTFCNTEMPLATE, SEARCHFCNTEMPLATE, @. a1 = 1; a2 = 10; % define parameters first options = psoptimset('Display','iter'); % Display iterative output x = patternsearch (@(x)myobj(x,a1),[1;2],[],[],[],[],[],[],@(x)myconstr(x,a2),options) function [c,ceq] = myconstr(x,a2) c = [1.5 + x(1)*x(2) - x(1) - x(2); -x(1)*x(2) - a2]; % No nonlinear equality constraints: ceq = []; function f = myobj(x,a1) f = exp(x(1))*(4*x(1)^2 + 2*x(2)^2 + 4*x(1)*x(2) + 2*x(2) + a1);

% Copyright 2003-2012 The MathWorks, Inc. % $Revision: 1.1.6.10 $ $Date: 2012/08/21 00:22:21 $

% Old syntax X = PATTERNSEARCH(FUN,X0,A,b,Aeq,beq,LB,UB,OPTIONS) may work % fine but users are encouraged to update to new syntax of PATTERNSEARCH % which takes ninth argument as NONLCON and OPTIONS is passed as tenth % argument. defaultopt = struct('TolMesh', 1e-6, ... 'TolCon', 1e-6, ... 'TolX', 1e-6 , ... 'TolFun',1e-6 , ... 'TolBind',1e-3, ... 'MaxIter', '100*numberofvariables', ... 'MaxFunEvals', '2000*numberofvariables', ... 'TimeLimit', Inf, ... 'MeshContraction', 0.5, ... 'MeshExpansion', 2.0, ... 'MeshAccelerator','off', ... 'MeshRotate','on', ... 'InitialMeshSize', 1.0, ... 'ScaleMesh', 'on', ... 'MaxMeshSize', inf, ... 'InitialPenalty', 10, ... 'PenaltyFactor', 100, ... 'PollMethod', 'gpspositivebasis2n', ... 'CompletePoll','off', ... 'PollingOrder', 'consecutive', ... 'SearchMethod', [], ... 'CompleteSearch','off', ... 'Display', 'final', ... 'OutputFcns', [], ... 'PlotFcns',[], ...

'PlotInterval', 1, ... 'Cache', 'off', ... 'CacheSize',1e4, ... 'CacheTol',eps, ... 'Vectorized','off', ... 'UseParallel','never' ... );

% If just 'defaults' passed in, return the default options in X if nargin == 1 && nargout <= 1 && isequal(FUN,'defaults') X = defaultopt; return end

errmsg = nargchk(1,10,nargin); % At least 1 argument is needed. if ~isempty(errmsg) error(message('globaloptim:patternsearch:atLeastOneInputArg')); end

if nargin < 10, options = []; if nargin < 9, nonlcon = []; if nargin < 8, UB = []; if nargin < 7, LB = []; if nargin <6, Beq = []; if nargin <5, Aeq = []; if nargin < 4, Bineq = []; if nargin <3, Aineq= []; end end end end end

end end end

% Ninth argument (nonlcon) could be options structure (old syntax from ver 1.0) if isstruct(nonlcon) && nargin < 10 options = nonlcon; nonlcon = []; end

% One input argument is for problem structure if nargin == 1 if isa(FUN,'struct') [FUN,initialX,Aineq,Bineq,Aeq,Beq,LB,UB,nonlcon,rngstate,options] = separateOptimStruct(FUN); % Reset the random number generators resetDfltRng(rngstate); else % Single input and non-structure. error(message('globaloptim:patternsearch:inputArg')); end end

% Check for non-double inputs msg = isoptimargdbl('PATTERNSEARCH', {'X0','A', 'b', 'Aeq', 'beq','LB','UB'}, ... initialX, Aineq, Bineq, Aeq, Beq, LB, UB); if ~isempty(msg) error('globaloptim:patternsearch:dataType',msg); end

% If FUN is a cell array with additional arguments, handle them if iscell(FUN) objFcnArg = FUN(2:end); FUN = FUN{1};

else objFcnArg = {}; end

% Only function_handle or inlines are allowed if isempty(FUN) || ~(isa(FUN,'inline') || isa(FUN,'function_handle')) error(message('globaloptim:patternsearch:needFunctionHandleObj')); end

% If NONLCON is a cell array with additional arguments, handle them if iscell(nonlcon) conFcnArg = nonlcon(2:end); nonlcon = nonlcon{1}; else conFcnArg = {}; end % Constraint function must be a function_handle or inline if ~isempty(nonlcon) && ~(isa(nonlcon,'inline') || isa(nonlcon,'function_handle')) error(message('globaloptim:patternsearch:needFunctionHandleConstr')); end

if(~isempty(initialX)) X = initialX; Iterate.x = initialX(:); numberOfVariables = length(Iterate.x); else error(message('globaloptim:patternsearch:initialPoint')); end

% Determine the 'type' of the problem if ~isempty(nonlcon) type = 'nonlinearconstr'; % Determine the sub-problem type for the constrained problem (used in ALPS)

if (~isempty(Aeq) && ~all(Aeq(:) == 0)) || ~isempty(Beq) || ... (~isempty(Aineq) && ~all(Aineq(:) == 0)) || ~isempty(Bineq) subtype = 'linearconstraints'; elseif ~isempty(LB) || any(isfinite(LB)) || ... ~isempty(UB) || any(isfinite(UB)) subtype = 'boundconstraints'; else subtype = 'unconstrained'; end % If Aeq or Aineq is not empty, then problem has linear constraints. elseif (~isempty(Aeq) && ~all(Aeq(:) == 0)) || ~isempty(Beq) || ... (~isempty(Aineq) && ~all(Aineq(:) == 0)) || ~isempty(Bineq) type = 'linearconstraints'; % This condition satisfies bound constraints elseif ~isempty(LB) || any(isfinite(LB)) || ... ~isempty(UB) || any(isfinite(UB)) type = 'boundconstraints'; % If all constraints fields are empty then it is unconstrained else type = 'unconstrained'; end

% Initialize output structure OUTPUT = struct('function',FUN,'problemtype',type,'pollmethod',[], ... 'searchmethod',[],'iterations',0,'funccount',0,'meshsize',[],'rngstate',[]);

% Store the random state dflt = RandStream.getGlobalStream; OUTPUT.rngstate = struct('state',{dflt.State}, 'type',{dflt.Type});

% If nonlinear constraints, then subtype is needed to process linear % constraints (see function preProcessLinearConstr)

if strcmp(type,'nonlinearconstr') type = subtype; end

% Use default options if empty if ~isempty(options) && ~isa(options,'struct') error(message('globaloptim:patternsearch:optionsNotAStruct')); elseif isempty(options) options = defaultopt; end % Save all user options user_options = options; % Validate all options options = checkoptions(options,defaultopt,numberOfVariables);

% Bound correction [LB,UB,msg,EXITFLAG] = checkbound(LB,UB,numberOfVariables); if EXITFLAG < 0 FVAL X(:) = []; = Iterate.x;

OUTPUT.message = msg; if options.Verbosity > 0 fprintf('%s\n',msg) end return end % Linear constraints correction [Iterate.x,Aineq,Bineq,Aeq,Beq,LB,UB,msg,EXITFLAG] = ... preProcessLinearConstr(Iterate.x,Aineq,Bineq,Aeq,Beq,LB,UB,numberOfVariables,type,options.Verbosity); if EXITFLAG < 0 FVAL X(:) = []; = Iterate.x;

OUTPUT.message = msg; if options.Verbosity > 0 fprintf('%s\n',msg) end return end

% Find the null space of equality constraints, required by polling method GSSDirections NullBasisAeq = eqconstrnullspace(Aeq,numberOfVariables); % Number of constraints nineqcstr = size(Aineq,1); neqcstr = size(Aeq,1); ncstr = nineqcstr + neqcstr;

% Check the objective and constraint functions; Evaluate at the start point [Iterate,OUTPUT.funccount] = poptimfcnchk(FUN,nonlcon,initialX,Iterate, ... options.Vectorized,objFcnArg,conFcnArg); % Print some diagnostic information if verbosity > 2 if options.Verbosity > 2 psdiagnose(FUN,nonlcon,initialX,nineqcstr,neqcstr,ncstr,user_options); end % Call appropriate private solver switch(OUTPUT.problemtype) case 'unconstrained' [X,FVAL,EXITFLAG,OUTPUT] = pfminunc(FUN,objFcnArg,initialX,numberOfVariables,Iterate, ... options,defaultopt,OUTPUT); case 'boundconstraints' [X,FVAL,EXITFLAG,OUTPUT] = pfminbnd(FUN,objFcnArg,initialX,numberOfVariables,Iterate, ... LB,UB,options,defaultopt,OUTPUT); case 'linearconstraints' [X,FVAL,EXITFLAG,OUTPUT] = pfminlcon(FUN,objFcnArg,initialX,numberOfVariables,Iterate, ... Aineq,Bineq,Aeq,Beq,NullBasisAeq,LB,UB,options,defaultopt,OUTPUT);

case 'nonlinearconstr' [X,FVAL,EXITFLAG,OUTPUT] = pfmincon(FUN,objFcnArg,initialX,numberOfVariables,Iterate, ... Aineq,Bineq,Aeq,Beq,NullBasisAeq,LB,UB,nonlcon,conFcnArg,options,defaultopt,OUTPUT,subtype); end _____________________________________________________________________________ function [Iterate,count] = poptimfcnchk(FUN,nonlcon,Xin,Iterate,Vectorized,objFcnArg,conFcnArg) %POPTIMFCNCHK Calls objective function 'FUN' and nonlinear constraint. % function 'nonlcon' for the first time at the start point 'Iterate.x'. If % 'Vectorized' option in 'on' the objective function is called with two points % Private to PATTERNSEARCH % Copyright 2003-2012 The MathWorks, Inc. % $Revision: 1.1.6.6 $ $Date: 2012/08/21 00:24:44 $

y = NaN; count = 0; X = Iterate.x; % Check the objective function. FUN = fcnchk(FUN); if strcmpi(Vectorized,'off') % The function is not vectorized. try [y,count] = funevaluate(FUN,Xin,X,'init',[],[],objFcnArg{:}); catch userFcn_ME gads_ME = MException('globaloptim:poptimfcnchk:objfunCheck', ... 'Failure in initial user-supplied objective function evaluation. PATTERNSEARCH cannot continue.'); userFcn_ME = addCause(userFcn_ME,gads_ME); rethrow(userFcn_ME) end if numel(y) ~=1 error(message('globaloptim:poptimfcnchk:objfunCheck')); end elseif strcmpi(Vectorized,'on') % If vectorized is 'on', Completepoll MUST be 'on' too

X2 = [X, X]; try [f,count] = funevaluate(FUN,Xin,X2,'init',[],[],objFcnArg{:}); catch userFcn_ME gads_ME = MException('globaloptim:poptimfcnchk:objfunCheck', ... 'Failure in initial user-supplied objective function evaluation (hint: ''vectorized'' option is ''on''). PATTERNSEARCH cannot continue.'); userFcn_ME = addCause(userFcn_ME,gads_ME); rethrow(userFcn_ME) end if 2 ~=numel(f) error(message('globaloptim:poptimfcnchk:objfunCheckVectorized', ... 'Vectorized','on')); end y = f(1); end % We want the function value to be real if isnan(y) error(message('globaloptim:poptimfcnchk:objfunNaN')); end Iterate.f = y; % Evaluate nonlinear constraints for the first time if ~isempty(nonlcon) try if strcmpi(Vectorized,'on') % Evaluate the nonlinear constraints at two points; X2 = [X,X]. [tmpCineq,tmpCeq] = feval(nonlcon,reshapeinput(Xin,X2),conFcnArg{:}); else [cineq,ceq] = feval(nonlcon,reshapeinput(Xin,X),conFcnArg{:}); end catch userFcn_ME gads_ME = MException('globaloptim:poptimfcnchk:confunCheck', ... 'Failure in initial user-supplied nonlinear constraint function evaluation.

PATTERNSEARCH cannot continue.'); userFcn_ME = addCause(userFcn_ME,gads_ME); rethrow(userFcn_ME) end if strcmpi(Vectorized,'on') % Is the initial point a column or row vector? A scalar is defined % as row vector. Note that we want Xin to be a vector. isXinColumnVector = size(Xin,1) > size(Xin,2); % Check whether row/column dimension of the constraint matrix is % two, corresponding to two points. % We don't perform any additional checks for the two-constraint case. % If Xin is a row vector, 2^isXinColumnVector) = 1, therefore the % number of rows in the constraint matrices should be 2. % If Xin is a column vector, 2^isXinColumnVector) = 2, therefore the % number of columns in the constraint matrices should be 2. if ( ~isempty(tmpCineq) && ( size(tmpCineq,2^isXinColumnVector) ~= 2 ) ) || ... ( ~isempty(tmpCeq) && ( size(tmpCeq,2^isXinColumnVector) ~= 2 ) ) if isXinColumnVector error(message('globaloptim:poptimfcnchk:x0ColConfunCheckVectorized', ... 'Vectorized','on')); else error(message('globaloptim:poptimfcnchk:x0RowConfunCheckVectorized', ... 'Vectorized','on')); end end cineq = []; ceq = []; if isXinColumnVector if ~isempty(tmpCineq) cineq = tmpCineq(:,1); end if ~isempty(tmpCeq) ceq = tmpCeq(:,1);

end else if ~isempty(tmpCineq) cineq = tmpCineq(1,:); end if ~isempty(tmpCeq) ceq = tmpCeq(1,:); end end end Iterate.cineq = zeros(numel(cineq),1); Iterate.ceq = zeros(numel(ceq),1); Iterate.cineq(:) = cineq; Iterate.ceq(:) = ceq; c = [Iterate.cineq;Iterate.ceq]; if ~all(isreal(c) & isfinite(c)) error(message('globaloptim:poptimfcnchk:confunNotReal')); end end _______________________________________________________________________________ function [f,count] = funevaluate(FUN,Xin,X,Cache,cachetol,cachelimit,varargin) %FUNEVALUATE Evaluate objective function FUN at X. % This function takes a vector or matrix X and evaluate FUN at X. % If X is a matrix then FUN must return a vector output. The caller % of this function should do the error checking and make sure % that FUN will be able to handle X which is being passed to this function. % CACHE: A flag for using CACHE. If 'off', no cache is used. % CACHETOL: Tolerance used in cache in order to determine whether two points % are same or not. % CACHELIMIT: Limit the cache size to 'cachelimit'. % Example % If there are 4 points in 2 dimension space then % X is [2 1 9 -2

0 1 -4 5]

% The objective function will get a transpose of X to be evaluated. % Copyright 2003-2007 The MathWorks, Inc. % $Revision: 1.1.6.2 $ $Date: 2012/08/21 00:23:40 $

persistent XCache; if nargin ==1 && strcmpi(FUN,'reset') XCache = []; return; end %Return here if X is empty if isempty(X) f = []; count = 0; return; end if strcmpi(Cache,'init') || strcmpi(Cache,'off') %No CACHE use XCache = []; count = size(X,2); f = feval(FUN,reshapeinput(Xin,X),varargin{:}); Real = isreal(f) & ~isnan(f); f(~Real) = NaN; elseif strcmpi(Cache,'on') CacheSize = size(XCache,2); %Reset Cache after it takes too much memory if CacheSize > cachelimit XCache(:,1:floor(CacheSize/4)) = []; CacheSize = size(XCache,2); end InCache = false(size(X,2),1); count = size(X,2);

f = NaN(count,1);

%Initialize the cache if it is empty if isempty(XCache) XCache end %Check if the point is in the CACHE for i = 1:size(X,2) for j = CacheSize:-1:1 if isequalpoint(X(:,i),XCache(:,j),cachetol) InCache(i)= 1; count = count - 1; break; end end %Point not found, insert in Cache if ~InCache(i) XCache(:,end+1) = X(:,i); end end %Evaluate the function; We will pass transpose of X (in case the function is vectorized) if any(~InCache) f(~InCache) = feval(FUN,reshapeinput(Xin,X(:,~InCache)),varargin{:}); end Real = isreal(f) & ~isnan(f); f(~Real) = NaN; end = X(:,1);

You might also like