?? qpsub.m
字號:
%---If Simplex Alg. choose leaving constraint---
rlambda = -R\(Q'*gf);
if isinf(rlambda(1)) && rlambda(1) < 0
fprintf(' Working set is singular; results may still be reliable.\n');
[m,n] = size(ACTSET);
rlambda = -(ACTSET + sqrt(eps)*randn(m,n))'\gf;
end
actlambda = rlambda;
actlambda(eqix)=abs(actlambda(eqix));
indlam = find(actlambda<0);
if length(indlam)
if STEPMIN > errnorm
% If there is no chance of cycling then pick the constraint
% which causes the biggest reduction in the cost function.
% i.e the constraint with the most negative Lagrangian
% multiplier. Since the constraints are normalized this may
% result in less iterations.
[minl,lind] = min(actlambda);
else
% Bland's rule for anti-cycling: if there is more than one
% negative Lagrangian multiplier then delete the constraint
% with the smallest index in the active set.
lind = find(ACTIND == min(ACTIND(indlam)));
end
lind = lind(1);
ACTSET(lind,:) = [];
aix(ACTIND(lind)) = 0;
[Q,R]=qrdelete(Q,R,lind);
Z = Q(:,numberOfVariables);
oldind = ACTIND(lind);
ACTIND(lind) = [];
ACTCNT = length(ACTIND);
else
lambda(indepInd(ACTIND))= normf * (rlambda./normA(ACTIND));
ACTIND = indepInd(ACTIND);
output.iterations = iterations;
return
end
end %if ACTCNT<numberOfVariables
%----------Compute Search Direction-------------
if (is_qp)
Zgf = Z'*gf;
if ~isempty(Zgf) && (norm(Zgf) < 1e-15)
SD = zeros(numberOfVariables,1);
dirType = ZeroStep;
else
[SD, dirType] = compdir(Z,H,gf,numberOfVariables,f);
end
elseif (LLS)
Zgf = Z'*gf;
HZ = H*Z;
if (norm(Zgf) < 1e-15)
SD = zeros(numberOfVariables,1);
dirType = ZeroStep;
else
HXf=H*X-f;
gf=H'*(HXf);
[mm,nn]=size(HZ);
if mm >= nn
[QHZ, RHZ] = qr(HZ,0);
Pd = QHZ'*HXf;
% SD = - Z*(RHZ(1:nn, 1:nn) \ Pd(1:nn,:));
% Now need to check which is dependent
if min(size(RHZ))==1 % Make sure RHZ isn't a vector
depInd = find( abs(RHZ(1,1)) < tolDep);
else
depInd = find( abs(diag(RHZ)) < tolDep );
end
end
if mm >= nn && isempty(depInd) % Newton step
SD = - Z*(RHZ(1:nn, 1:nn) \ Pd(1:nn,:));
dirType = NewtonStep;
else % steepest descent direction
SD = -Z*(Z'*gf);
dirType = SteepDescent;
end
end
else % LP
if ~simplex_iter
SD = -Z*(Z'*gf);
gradsd = norm(SD);
else
gradsd = Z'*gf;
if gradsd > 0
SD = -Z;
else
SD = Z;
end
end
if abs(gradsd) < 1e-10 % Search direction null
% Check whether any constraints can be deleted from active set.
% rlambda = -ACTSET'\gf;
if ~oldind
rlambda = -R\(Q'*gf);
ACTINDtmp = ACTIND; Qtmp = Q; Rtmp = R;
else
% Reinsert just deleted constraint.
ACTINDtmp = ACTIND;
ACTINDtmp(lind+1:ACTCNT+1) = ACTIND(lind:ACTCNT);
ACTINDtmp(lind) = oldind;
[Qtmp,Rtmp] = qrinsert(Q,R,lind,A(oldind,:)');
end
actlambda = rlambda;
actlambda(1:neqcstr) = abs(actlambda(1:neqcstr));
indlam = find(actlambda < errnorm);
lambda(indepInd(ACTINDtmp)) = normf * (rlambda./normA(ACTINDtmp));
if ~length(indlam)
ACTIND = indepInd(ACTIND);
output.iterations = iterations;
return
end
cindmax = length(indlam);
cindcnt = 0;
m = length(ACTINDtmp);
while (abs(gradsd) < 1e-10) && (cindcnt < cindmax)
cindcnt = cindcnt + 1;
lind = indlam(cindcnt);
[Q,R]=qrdelete(Qtmp,Rtmp,lind);
Z = Q(:,m:numberOfVariables);
if m ~= numberOfVariables
SD = -Z*Z'*gf;
gradsd = norm(SD);
else
gradsd = Z'*gf;
if gradsd > 0
SD = -Z;
else
SD = Z;
end
end
end
if abs(gradsd) < 1e-10 % Search direction still null
ACTIND = indepInd(ACTIND);
output.iterations = iterations;
return;
else
ACTIND = ACTINDtmp;
ACTIND(lind) = [];
aix = zeros(ncstr,1);
aix(ACTIND) = 1;
ACTCNT = length(ACTIND);
ACTSET = A(ACTIND,:);
end
lambda = zeros(ncstr,1);
end
end % if is_qp
end % while
if iterations >= maxiter
exitflag = 0;
how = 'MaxSQPIter';
msg = ...
sprintf(['Maximum number of iterations exceeded; increase options.MaxIter.\n' ...
'To continue solving the problem with the current solution as the\n' ...
'starting point, set x0 = x before calling quadprog.']);
if verbosity > 0
disp(msg)
end
end
output.iterations = iterations;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [Q,R,A,B,X,Z,how,ACTSET,ACTIND,ACTCNT,aix,eqix,neqcstr, ...
ncstr,remove,exitflag,msg]= ...
eqnsolv(A,B,eqix,neqcstr,ncstr,numberOfVariables,LLS,H,X,f,normf, ...
normA,verbosity,aix,ACTSET,ACTIND,ACTCNT,how,exitflag)
% EQNSOLV Helper function for QPSUB.
% Checks whether the working set is linearly independent and
% finds a feasible point with respect to the working set constraints.
% If the equalities are dependent but not consistent, warning
% messages are given. If the equalities are dependent but consistent,
% the redundant constraints are removed and the corresponding variables
% adjusted.
% set tolerances
tolDep = 100*numberOfVariables*eps;
tolCons = 1e-10;
Z=[]; remove =[];
msg = []; % will be given a value only if appropriate
% First see if the equality constraints form a consistent system.
[Qa,Ra,Ea]=qr(A(eqix,:));
% Form vector of dependent indices.
if min(size(Ra))==1 % Make sure Ra isn't a vector
depInd = find( abs(Ra(1,1)) < tolDep);
else
depInd = find( abs(diag(Ra)) < tolDep );
end
if neqcstr > numberOfVariables
depInd = [depInd; ((numberOfVariables+1):neqcstr)'];
end
if ~isempty(depInd) % equality constraints are dependent
msg = sprintf('The equality constraints are dependent.');
how='dependent';
exitflag = 1;
bdepInd = abs(Qa(:,depInd)'*B(eqix)) >= tolDep ;
if any( bdepInd ) % Not consistent
how='infeasible';
exitflag = -2;
msg = sprintf('%s\nThe system of equality constraints is not consistent.',msg);
if ncstr > neqcstr
msg = sprintf('%s\nThe inequality constraints may or may not be satisfied.',msg);
end
msg = sprintf('%s\nThere is no feasible solution.',msg);
else % the equality constraints are consistent
% Delete the redundant constraints
% By QR factoring the transpose, we see which columns of A'
% (rows of A) move to the end
[Qat,Rat,Eat]=qr(A(eqix,:)');
[i,j] = find(Eat); % Eat permutes the columns of A' (rows of A)
remove = i(depInd);
numDepend = nnz(remove);
if verbosity > 0
disp('The system of equality constraints is consistent. Removing');
disp('the following dependent constraints before continuing:');
disp(remove)
end
A(eqix(remove),:)=[];
B(eqix(remove))=[];
neqcstr = neqcstr - numDepend;
ncstr = ncstr - numDepend;
eqix = 1:neqcstr;
aix(remove) = [];
ACTIND(1:numDepend) = [];
ACTIND = ACTIND - numDepend;
ACTSET = A(ACTIND,:);
ACTCNT = ACTCNT - numDepend;
end % consistency check
end % dependency check
if verbosity > 0
disp(msg)
end
% Now that we have done all we can to make the equality constraints
% consistent and independent we will check the inequality constraints
% in the working set. First we want to make sure that the number of
% constraints in the working set is only greater than or equal to the
% number of variables if the number of (non-redundant) equality
% constraints is greater than or equal to the number of variables.
if ACTCNT >= numberOfVariables
ACTCNT = max(neqcstr, numberOfVariables-1);
ACTIND = ACTIND(1:ACTCNT);
ACTSET = A(ACTIND,:);
aix = zeros(ncstr,1);
aix(ACTIND) = 1;
end
% Now check to see that all the constraints in the working set are
% linearly independent.
if ACTCNT > neqcstr
[Qat,Rat,Eat]=qr(ACTSET');
% Form vector of dependent indices.
if min(size(Rat))==1 % Make sure Rat isn't a vector
depInd = find( abs(Rat(1,1)) < tolDep);
else
depInd = find( abs(diag(Rat)) < tolDep );
end
if ~isempty(depInd)
[i,j] = find(Eat); % Eat permutes the columns of A' (rows of A)
remove2 = i(depInd);
removeEq = remove2(find(remove2 <= neqcstr));
removeIneq = remove2(find(remove2 > neqcstr));
if ~isempty(removeEq)
% Just take equalities as initial working set.
ACTIND = 1:neqcstr;
else
% Remove dependent inequality constraints.
ACTIND(removeIneq) = [];
end
aix = zeros(ncstr,1);
aix(ACTIND) = 1;
ACTSET = A(ACTIND,:);
ACTCNT = length(ACTIND);
end
end
[Q,R]=qr(ACTSET');
Z = Q(:,ACTCNT+1:numberOfVariables);
if ~strcmp(how,'infeasible') && ACTCNT > 0
% Find point closest to the given initial X which satisfies
% working set constraints.
minnormstep = Q(:,1:ACTCNT) * ...
((R(1:ACTCNT,1:ACTCNT)') \ (B(ACTIND) - ACTSET*X));
X = X + minnormstep;
% Sometimes the "basic" solution satisfies Aeq*x= Beq
% and A*X < B better than the minnorm solution. Choose the one
% that the minimizes the max constraint violation.
err = A*X - B;
err(eqix) = abs(err(eqix));
if any(err > eps)
Xbasic = ACTSET\B(ACTIND);
errbasic = A*Xbasic - B;
errbasic(eqix) = abs(errbasic(eqix));
if max(errbasic) < max(err)
X = Xbasic;
end
end
end
% End of eqnsolv.m
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -