www.gusucode.com > mbcmodels 工具箱 matlab 源码程序 > mbcmodels/gamincon.m
function [X,FVAL,EXITFLAG,OUTPUT] = gamincon(FUN,X,LB,UB,A,B,NONLCON,options,DISPFUN,varargin) %GAMINCON Finds the constrained minimum of a function of several variables. % GAMINCON solves problems of the form: % min f(x) % x % subject to: % A*x <= b % C(x) <= 0 % LB <= x <= UB % % Copyright 2000-2011 The MathWorks, Inc. and Ford Global Technologies, Inc. defaultopt = struct('Display','none','LargeScale','on', ... 'TolX',1e-6,'TolFun',1e-6,'TolCon',1e-6,'DerivativeCheck','off',... 'Diagnostics','off','FunValCheck','off',... 'GradObj','off','GradConstr','off',... 'HessMult',[],... 'Hessian','off','HessPattern','sparse(ones(numberOfVariables))',... 'MaxFunEvals','100*numberOfVariables',... 'MaxSQPIter','10*max(numberOfVariables,numberOfInequalities+numberOfBounds)',... 'DiffMaxChange',1e-1,'DiffMinChange',1e-8,... 'PrecondBandWidth',0,'TypicalX','ones(numberOfVariables,1)',... 'MaxPCGIter','max(1,floor(numberOfVariables/2))', ... 'TolPCG',0.1,'MaxIter', 10,'OutputFcn',[],'PlotFcns',[],... 'RelLineSrchBnd',[],'RelLineSrchBndDuration',1,'NoStopIfFlatInfeas','off', ... 'PhaseOneTotalScaling','off', ... 'MaxGAIter',200,... 'MaxNoChange',30,... 'MaxSimilarity',0.95,... 'PopSize',20,... 'Hybridization',struct('name','sorted','option',[10,10]),... 'Fitness',struct('name','scaling','option',[]),... 'Selection',struct('name','normGeometric','option',0.08),... 'Crossover',struct('name',{'simple','arithmetic','heuristic'},... 'option',{1,1,[1 3]}),... 'Mutation',struct('name',{'boundary','multiNonUniform','nonUniform','uniform'},... 'option',{2,[3,3],[2,3],2})); if nargin == 1 && nargout <= 1 && isequal(FUN,'defaults') X = defaultopt; return end if nargin < 4 error(message('mbc:gamincon:TooFewInputs')); end if nargin < 9 DISPFUN = []; if nargin < 8 options = []; if nargin < 7 NONLCON = []; if nargin < 6 B = []; if nargin < 5 A = []; end end end end end [msg,x,lb,ub] = checkbounds(X,LB,UB); if ~isempty(msg) error('mbc:gamincon:InvalidArgument', msg); end popSize = getgaopt(options,'PopSize',defaultopt,'fast'); numVars = length(x); range = ub-lb; X0 = [x range(:,ones(1,popSize-1)).*rand(numVars,popSize-1)+lb(:,ones(1,popSize-1))]; gradflag = strcmp(getgaopt(options,'GradObj',defaultopt,'fast'),'on'); gradconstflag = strcmp(getgaopt(options,'GradConstr',defaultopt,'fast'),'on'); if isempty(NONLCON) constflag = false; else constflag = true; end if isempty(DISPFUN) displflag = false; else displflag = true; end if ~isempty(FUN) funfcn = optimfcnchk(FUN,'gamincon',length(varargin),gradflag); else error(message('mbc:gamincon:InvalidArgument1')); end if constflag confcn = optimfcnchk(NONLCON,'gamincon',length(varargin),gradconstflag,1); else confcn{1} = ''; end if (displflag) disfcn = optimfcnchk(DISPFUN,'gamincon',length(varargin)+2); else disfcn{1} = ''; end %----- Integer variables not excluded TO DO x = checkOptimProblem(A,B,x,X0,numVars,funfcn,confcn,varargin{:}); global OPT_STOP OPT_STEP OPT_STEP = 1; OPT_STOP = 0; %----------------- suphybrid = {'sorted','random'}; supfitness = {'scaling','ranking'}; supselect = {'normGeometric','tournament','roulette'}; supxover = {'simple','arithmetic','heuristic'}; supmutat = {'boundary','multiNonUniform','nonUniform','uniform'}; %--------- hybridization, fitness and select must be scalars opt = getgaopt(options,'Hybridization',defaultopt,'fast'); [hybrid,opthybrid] = opermatch(opt,suphybrid); opt = getgaopt(options,'Fitness',defaultopt,'fast'); fitness = opermatch(opt,supfitness); opt = getgaopt(options,'Selection',defaultopt,'fast'); [select,optselect] = opermatch(opt,supselect); opt = getgaopt(options,'Crossover',defaultopt,'fast'); [xover,optxover] = opermatch(opt,supxover); opt = getgaopt(options,'Mutation',defaultopt,'fast'); [mutat,optmutat] = opermatch(opt,supmutat); nxover = length(xover); nmutat = length(mutat); L0 = zeros(1,popSize); for k = 1:popSize x(:) = X0(:,k); L0(k) = feval(funfcn{3},x,varargin{:}); end iter = 0; switch disfcn{1} case 'fun' try feval(disfcn{3},iter,X0,L0,varargin{:}); catch ME error(message('mbc:gamincon:InvalidArgument13', 'GAMINCON cannot continue. User supplied display function', 'failed with the following error:', ME.message)); end case '' otherwise error(message('mbc:gamincon:InvalidState2')); end F0 = zeros(size(L0)); L1 = zeros(size(L0)); X1 = zeros(size(X0)); c1 = zeros(numVars,1); c2 = zeros(numVars,1); p1 = zeros(numVars,1); p2 = zeros(numVars,1); bestx = zeros(numVars,1); done = false; tolfun = getgaopt(options,'TolFun',defaultopt,'fast'); maxgen = getgaopt(options,'MaxGAIter',defaultopt,'fast'); maxnoc = getgaopt(options,'MaxNoChange',defaultopt,'fast'); maxsim = getgaopt(options,'MaxSimilarity',defaultopt,'fast'); bufnoc = rand(maxnoc,1); topnoc = 1; iter = 1; hciter = opthybrid{1}(1); hcsize = opthybrid{1}(2); hindex = zeros(1,hcsize); switch hybrid case 1 hcpind = zeros(1,popSize); case 2 otherwise end switch fitness case 1 case 2 rankfun = zeros(1,popSize); rankfun(:) = 2*(0:popSize-1)/(popSize-1); rankind = zeros(1,popSize); otherwise end switch select case 1 q = optselect{1}; r = q/(1-(1-q)^popSize); indices = zeros(1,popSize); indices(:) = popSize-1:-1:0; gprob = r*(1-q).^indices; fit = zeros(1,popSize); urn = zeros(1,popSize); case 2 trnSize = optselect{1}; tourind = zeros(popSize,trnSize); indices = zeros(1,popSize); case 3 rprob = zeros(1,popSize); urn = zeros(1,popSize); otherwise end for k = 1:nmutat job = mutat(k); mopt = optmutat{k}; switch (job) case 1 case 2 MD = zeros(numVars,1); CPOINT = false(numVars,1); case 3 smshape = mopt(2); case 4 otherwise end end for k = 1:nxover job = xover(k); xopt = optxover{k}; switch (job) case 1 case 2 case 3 retry = xopt(2); t1 = zeros(numVars,1); t2 = zeros(numVars,1); otherwise end end % Record number of calls to fmincon for output structure NumberOfFminconCalls = 0; while (~done) if (rem(iter,hciter) == 0) OPT_STEP = 1; switch (hybrid) case 1 [~,hcpind(:)] = sort(L0); hindex(:) = hcpind(1:hcsize); case 2 hindex(:) = floor(rand(1,hcsize)*popSize)+1; otherwise end for k = hindex x(:) = X0(:,k); if isempty(options) options = optimset('fmincon'); end % Always want to use medium scale algorithm fmcoptions = optimset(options,... 'largescale','off',... 'Algorithm','active-set'); [x,f,exitflag] = ... fmincon(FUN,x,A,B,[],[],lb,ub,NONLCON, fmcoptions, varargin{:}); NumberOfFminconCalls = NumberOfFminconCalls + 1; if exitflag >= 0 % Only use results if fmincon converges X0(:,k) = x; L0(k) = f; end if OPT_STOP break end end end if displflag feval(disfcn{3},iter,X0,L0,varargin{:}); end OPT_STEP = 0; if OPT_STOP break end switch fitness case 1 F0(:) = 1+max(L0)-L0; case 2 [~,rankind(:)] = sort(-L0); L1(:) = L0(rankind); i1 = 1; for i2 = [find(L1(1:popSize-1) ~= L1(2:popSize)),popSize] F0(i1:i2) = sum(rankfun(i1:i2))/(i2-i1+1); i1 = i2+1; end [~,rankind(:)] = sort(rankind); F0(:) = F0(rankind); otherwise end [~,ind] = max(F0); bestx(:) = X0(:,ind); bestl = L0(ind); bufnoc(topnoc) = bestl; topnoc = topnoc+1; if topnoc > maxnoc topnoc = 1; end if (iter > maxgen) || all(abs(bufnoc-bestl) <= tolfun) || ... (sum(abs(L0-bestl) <= tolfun) >= maxsim*popSize) done = true; else switch (select) case 1 [~,indices(:)] = sort(F0); fit(indices) = gprob; fit(:) = cumsum(fit); urn(:) = sort(rand(1,popSize)); i1 = 1; i2 = 1; while i2 <= popSize if (urn(i2) < fit(i1)) X1(:,i2) = X0(:,i1); L1(i2) = L0(i1); i2 = i2+1; else i1 = i1+1; end end case 2 tourind(:) = floor(rand(popSize,trnSize)*popSize)+1; [~,indices(:)] = max(reshape(F0(tourind),trnSize,popSize)); indices(:) = diag(tourind(:,indices)); X1(:) = X0(:,indices); L1(:) = L0(indices); case 3 rprob(:) = cumsum(F0/sum(F0)); urn(:) = sort(rand(1,popSize)); i1 = 1; i2 = 1; while i2 <= popSize if (urn(i2) < rprob(i1)) X1(:,i2) = X0(:,i1); L1(i2) = L0(i1); i2 = i2+1; else i1 = i1+1; end end otherwise end for k = 1:nxover job = xover(k); xopt = optxover{k}; nx = xopt(1); for l = 1:nx i1 = round(rand*(popSize-1)+1); i2 = round(rand*(popSize-1)+1); p1(:) = X1(:,i1); p2(:) = X1(:,i2); switch job case 1 cpoint = round(rand*(numVars-2)+1); c1(:) = [p1(1:cpoint);p2(cpoint+1:end)]; c2(:) = [p2(1:cpoint);p1(cpoint+1:end)]; case 2 alfa = rand; beta = 1-alfa; c1(:) = alfa*p1+beta*p2; c2(:) = beta*p1+alfa*p2; case 3 feasible = false; l1 = 0; if (F0(i1) > F0(i2)) t2(:) = p1; t1(:) = p2; else t2(:) = p2; t1(:) = p1; end while l1 < retry alfa = rand; beta = 1+alfa; c1(:) = beta*t2-alfa*t1; if all(c1 <= ub) && all(c1 >= lb) l1 = retry; feasible = true; else l1 = l1+1; end end if ~feasible c1(:) = t1; end c2(:) = t2; otherwise end if all(c1 == p1) l1 = L1(i1); elseif all(c1 == p2) l1 = L1(i2); else l1 = feval(funfcn{3},c1,varargin{:}); end if all(c2 == p1) l2 = L1(i1); elseif all(c2 == p2) l2 = L1(i2); else l2 = feval(funfcn{3},c2,varargin{:}); end X1(:,[i1,i2]) = [c1,c2]; L1([i1,i2]) = [l1;l2]; if OPT_STOP break end end if OPT_STOP break end end if ~OPT_STOP for k = 1:nmutat job = mutat(k); mopt = optmutat{k}; nm = mopt(1); for l = 1:nm i1 = round(rand*(popSize-1)+1); p1(:) = X1(:,i1); c1(:) = p1; switch job case 1 cpoint = round(rand*(numVars-1)+1); if (rand >= 0.5) c1(cpoint) = ub(cpoint); else c1(cpoint) = lb(cpoint); end case 2 ratio = iter/maxgen; alfa = (rand*(1-ratio)).^smshape; beta = 1-alfa; MD = rand(numVars,1); CPOINT(:) = MD >= 0.5; c1(CPOINT) = beta*p1(CPOINT)+alfa*ub(CPOINT); CPOINT(:) = ~CPOINT; c1(CPOINT) = beta*p1(CPOINT)+alfa*lb(CPOINT); case 3 cpoint = round(rand*(numVars-1)+1); ratio = iter/maxgen; alfa = (rand*(1-ratio)).^smshape; beta = 1-alfa; if (rand >= 0.5) c1(cpoint) = beta*p1(cpoint)+alfa*ub(cpoint); else c1(cpoint) = beta*p1(cpoint)+alfa*lb(cpoint); end case 4 cpoint = round(rand*(numVars-1)+1); c1(cpoint) = lb(cpoint)+rand*range(cpoint); otherwise end if all(c1 == p1) l1 = L1(i1); elseif all(c1 == p2) l1 = L1(i2); else l1 = feval(funfcn{3},c1,varargin{:}); end X1(:,i1) = c1; L1(i1) = l1; if OPT_STOP break end end if OPT_STOP break end end end X0(:) = X1; L0(:) = L1; [~,ind] = max(L0); X0(:,ind) = bestx; L0(ind) = bestl; iter = iter+1; if OPT_STOP break; end end end if ~OPT_STOP OPT_STEP = 1; % Run optimization one more time if the GA has still not converged. x(:) = bestx; if isempty(options) options = optimset('fmincon'); end % Always want to use medium scale algorithm fmcoptions = optimset(options, ... 'largescale','off',... 'Algorithm','active-set',... 'MaxIter', 30*numVars); [bestx,FVAL,EXITFLAG] = ... fmincon(FUN,x,A,B,[],[],lb,ub,NONLCON, fmcoptions, varargin{:}); X(:) = bestx; NumberOfFminconCalls = NumberOfFminconCalls + 1; else % GA has found a solution. X(:) = bestx; FVAL = bestl; EXITFLAG = 1; end OUTPUT = struct('iterations',iter,... 'population',X0,... 'fitness',L0, ... 'numberoffminconcalls',NumberOfFminconCalls); function [msg,xout,lbout,ubout] = checkbounds(x,lbin,ubin) %CHECKBOUNDS Move the initial points within the (valid) bounds. % msg = ''; xout = x(:); lbout = lbin(:); ubout = ubin(:); lenlb = length(lbout); lenub = length(ubout); nvars = length(x); if (lenlb ~= nvars) || (lenub ~= nvars) msg = 'Length of lower/upper bounds not equal to the number of variables.'; elseif any(~isfinite(lbout)) || any(~isfinite(ubout)) msg = 'Lower/upper bounds are not finite.'; elseif any(lbout >= ubout) msg = 'Lower bounds exceed the corresponding upper bounds.'; else if any(xout < lbout) || any(xout > ubout) msg = 'Initial solution is not feasible.'; end end function [oper,opts] = opermatch(options,FIELDS) %OPERMATCH Get operators and the associated parameters. % if ~isempty(options) && ~isstruct(options) error(message('mbc:gamincon:InvalidState3')); end names = fieldnames(options); if ~any( strncmp( 'name',names,4 ) ) || ~any( strncmp( 'option',names,6 ) ) error(message('mbc:gamincon:InvalidArgument14')); end NAMES = {options.name}; nop = length(NAMES); oper = zeros(1,nop); opts = cell(1,nop); for k = 1:nop name = NAMES{k}; ind = find( strncmpi( name,FIELDS,length(name) ) ); if isempty(ind) error(message('mbc:gamincon:InvalidState4', NAMES{ k })); elseif length(ind) > 1 ind = find( strcmpi( name,FIELDS ) ); if length(ind) ~= 1 error(message('mbc:gamincon:InvalidState5', NAMES{ k })); end end oper(k) = ind; opts{k} = options(k).option; end function x = checkOptimProblem(A,B,x,X0,numVars,funfcn,confcn,varargin) x(:) = X0(:,1); % Evaluate function GRAD = zeros(numVars,1); switch (funfcn{1}) case 'fun' try f = feval(funfcn{3},x,varargin{:}); catch ME error(message('mbc:gamincon:InvalidArgument2', 'GAMINCON cannot continue. User supplied objective function', 'failed with the following error:', ME.message)); end case 'fungrad' try [f,GRAD(:)] = feval(funfcn{3},x,varargin{:}); catch ME error(message('mbc:gamincon:InvalidArgument3', 'GAMINCON cannot continue. User supplied objective/gradient function', 'failed with the following error:', ME.message)); end case 'fun_then_grad' try f = feval(funfcn{3},x,varargin{:}); catch ME error(message('mbc:gamincon:InvalidArgument4', 'GAMINCON cannot continue. User supplied objective function', 'failed with the following error:', ME.message)); end try GRAD(:) = feval(funfcn{4},x,varargin{:}); catch ME error(message('mbc:gamincon:InvalidArgument5', 'GAMINCON cannot continue. User supplied objective gradient function', 'failed with the following error:', ME.message)); end otherwise error(message('mbc:gamincon:InvalidArgument6')); end % Evaluate constraints switch (confcn{1}) case 'fun' try ctmp = feval(confcn{3},x,varargin{:}); c = ctmp(:); cGRAD = zeros(numVars,length(c)); catch ME error(message('mbc:gamincon:InvalidArgument7', 'GAMINCON cannot continue. User supplied nonlinear constraint function', 'failed with the following error:', ME.message)); end case 'fungrad' try [ctmp,cGRAD] = feval(confcn{3},x,varargin{:}); c = ctmp(:); catch ME error(message('mbc:gamincon:InvalidArgument8', 'GAMINCON cannot continue. User supplied nonlinear constraint/gradient function', 'failed with the following error:', ME.message)); end case 'fun_then_grad' try ctmp = feval(confcn{3},x,varargin{:}); c = ctmp(:); catch ME error(message('mbc:gamincon:InvalidArgument9', 'GAMINCON cannot continue. User supplied nonlinear constraint', 'function failed with the following error:', ME.message)); end try cGRAD = feval(confcn{4},x,varargin{:}); catch ME error(message('mbc:gamincon:InvalidArgument10', 'GAMINCON cannot continue. User supplied nonlinear constraint', 'gradient function failed with the following error:', ME.message)); end case '' c = []; cGRAD = zeros(numVars,length(c)); otherwise error(message('mbc:gamincon:InvalidState')); end nonIneq = length(c); [linIneq,Acol] = size(A); [cgrow,cgcol]= size(cGRAD); if ~isempty(A) && (Acol ~= numVars) error(message('mbc:gamincon:InvalidArgument11')) end if ~isempty(A) && (linIneq ~= length(B)) error(message('mbc:gamincon:InvalidArgument12')); end if (cgrow ~= numVars) && (cgcol ~= nonIneq) error(message('mbc:gamincon:InvalidState1')); end