📄 tcsub.m
字号:
function [x,lagrange,status] = tcsub(A,b,G,d,x,nEqCstr,caller,nCstr,nVars)%TCSUB Active set algorithm used by mtsvdcstr and tikhcstr%% [x,lagrange,status] = tcsub(A,b,G,d,x,nEqCstr,caller,nCstr,nVars);%% Solves the constrained least squares problem:% min || A x - b || s.t. G x >= d% using an active set algorithm.%% The first nEqCstr constraints of G are equality constraints.% Modified and simplified version of function ??? from Optimization Toolbox.
% Ann-Charlotte Berglund, IMM & UNI-C, June 28, 1999.
phase2 = 0;status = 'feasible'; errNorm = 0.01*sqrt(eps); tolDep = 1000*nVars*eps; lagrange = zeros(nCstr,1);showActInact = zeros(nCstr,1);% The number of constraints in the active set.actCnt = 0;% The active set matrix.actSet = [];%Index vector.actInd = 0;% Vector to keep track of the equality constraints.eqVec = 1:nEqCstr; Q = zeros(nVars,nVars);R = []; indepInd = 1:nCstr;if strcmp(caller, 'mtsvdcstr') | strcmp(caller, 'tikhcstr') phase2 = 1; [mA,n] = size(A);endsimplex = 0;if nEqCstr>0 tolCons = 1e-10; showActInact(eqVec) = ones(nEqCstr,1); actSet = G(eqVec,:); actInd = eqVec; actCnt = nEqCstr; Z = []; % Find the linearly dependent equality constraints if any. [QG,RG,EG] = qr(G(eqVec,:)); if min(size(RG)) == 1 depInd = find( abs(RG(1,1)) < tolDep); else depInd = find( abs(diag(RG)) < tolDep ); end if ~isempty(depInd) if nEqCstr > nVars depInd = [depInd; ((nVars+1):nEqCstr)']; end bdepInd = abs(QG(:,depInd)'*d(eqVec)) >= tolDep ; if any( bdepInd ) % Not consistent status = 'incons'; return % The equality constraints are consistent. Delete the dependent % constraint/-s from the active set. end [QAct,RAct,EAct] = qr(actSet'); [i,j] = find(EAct); % Find the dependent equality constraint/-s. remove = i(depInd); G(eqVec(remove),:) = []; d(eqVec(remove)) = []; indepInd(remove) = []; nEqCstr = nEqCstr-nnz(remove); nCstr = nCstr-nnz(remove); eqVec = 1:nEqCstr; showActInact = [ones(nEqCstr,1); zeros(nCstr-nEqCstr,1)]; actInd = eqVec; actSet = G(eqVec,:); actCnt = nEqCstr; end % if ~isempty(depInd) [Q,R] = qr(actSet'); Z = Q(:,nEqCstr+1:nVars); Y = Q(:,1:nEqCstr); err = 0; % Overdetermind active set matix. The equality constrints are % linearly dependent, but we have not been able to identify the % independent equality constraints. if nEqCstr > nVars status = 'overdet'; return elseif nEqCstr == nVars x = actSet\d(eqVec); [mG,nG] = size(G) [md,nd] = size(d) cstr = G*x-d(nEqCstr+1:nCstr); if min(cstr) > -eps return end end % end overdet. active set matrix. else Z = 1; Y = Q;end cstr = G*x-d;if phase2 res = b-A*x;else gb = b; dirType = 'StD'; simplex = 1;endminInact = 0;delCstr = 0;%-------------------------------------------------% Main part.%------------------------------------------------while 1 %Find search direction. if phase2 AZ = A*Z; [mm,nn] = size(AZ); if mm >= nn [QAZ, RAZ] = qr(AZ); Pd = QAZ'*res; c = Pd(1:nn,1); if min(size(RAZ))==1 depInd = find( abs(RAZ(1,1)) < tolDep); else depInd = find( abs(diag(RAZ)) < tolDep ); end end if mm >= nn & isempty(depInd) p = Z*(RAZ(1:nn, 1:nn)\c); dirType = 'NS'; end else % Phase 1 if strcmp(dirType,'StD') p = -Z*(Z'*gb); end end %End If phase2 % Find the steplength. Gp = G*p; indNew = find((Gp < -errNorm*norm(p)) & ~showActInact); if isempty(indNew) % Did not hit a constraint. alpha = inf; dist = []; indVec = []; indMin = 0; else % Did hit a constraint. dist = abs(cstr(indNew)./Gp(indNew)); [alpha,indVec] = min(dist); indVec = find(dist == alpha); indMin = indNew(min(indVec)); end % Update x. if ~isempty(indNew) & isfinite(alpha) % Did hit a constraint and steplength < inf. if strcmp(dirType, 'NS') if alpha > 1 alpha = 1; delCstr = 1; indMin = 0; end end a = alpha; x = x+alpha*p; else % Did not hit a constraint or steplength = inf. if strcmp(dirType,'NS') % If a Newton step, reset steplength. alpha = 1; x = x + p; delCstr = 1; indMin = 0; else %Unbounded problem. status = 'unbounded'; disp('unbounded') return end % if strcmp(dirType, 'NS') end % if ~isempty(indnew)& isfinite(alpha) if phase2 res = b-A*x; end cstr = G*x-d; cstr(eqVec) = abs(cstr(eqVec)); % If in Phase 1, searching for initial feasible point. % For finding a feasible point, the artificial variable % must tend to zero. if ~phase2 if x(nVars,1) < eps return end end % Check for optimality if the active set is not equal to the % empty set. % If optimum => stop. % else => a constraint in the active set is now inactive. if delCstr if actCnt > 0 % Test for optimality. if phase2 AY = A*Y; U = QAZ'*AY; [mU,nU] = size(U); U = U(nn+1:mU,:); cn = Pd(nn+1:mU,1); rlagrange = -(R(1:actCnt,1:actCnt))\(U'*cn); actlagrange = rlagrange; actlagrange(eqVec) = abs(rlagrange(eqVec)); indInact = find(actlagrange < 0); if (~length(indInact)) lagrange(indepInd(actInd)) = rlagrange; return end % Remove constraint. minInact = find(actInd == min(actInd(indInact))); minInact = minInact(1); end actSet(minInact,:) = []; showActInact(actInd(minInact)) = 0; [Q,R] = qrdelete(Q,R,minInact); actCnt = actCnt-1; Y = Q(:,1:actCnt); Z = Q(:,1+actCnt:nVars); actInd(minInact) = []; else % Exact Newton step. lagrange = zeros(size(d)); return end delCstr = 0; end % If hit a constraint, add the new constraint to the active set. if indMin showActInact(indMin) = 1; actSet(actCnt+1,:) = G(indMin,:); actInd(actCnt+1) = indMin; % Insert constraint to the active set. [Q,R] = qrinsert(Q,R,actCnt+1,G(indMin,:)'); actCnt = actCnt+1; Y = Q(:,1:actCnt); Z = Q(:,1+actCnt:nVars); end if simplex % Test for optimality. if actCnt > nEqCstr if norm(Z'*b) < eps Qb = (Q(:,1:actCnt))'*b; rlagrange = R(1:actCnt,1:actCnt)\Qb; actlagrange = rlagrange; actlagrange(eqVec) = abs(rlagrange(eqVec)); indInact = find(actlagrange < 0); if (~length(indInact)) lagrange(indepInd(actInd)) = rlagrange; return end % Remove constraint. minInact = find(actInd == min(actInd(indInact))); minInact = minInact(1); if actCnt == nVars es = zeros(size(actSet,1),1); es(minInact,1) = 1; p = actSet\es; dirType = 'inActStep'; else dirType = 'StD'; end delCstr = 1; end else minInact = 0; delCstr = 0; end endend % while 1%-------------------------------------------------% END OF TCSUB%-------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -