📄 qpsub.m
字号:
Z = Q(:,ACTCNT+1:numberOfVariables);
end
end
end
if ACTCNT >= numberOfVariables - 1
simplex_iter = 1;
end
[m,n]=size(ACTSET);
if (is_qp)
gf=H*X+f;
% SD=-Z*((Z'*H*Z)\(Z'*gf));
[SD, dirType] = compdir(Z,H,gf,numberOfVariables,f);
% Check for -ve definite problems:
% if SD'*gf>0, is_qp = 0; SD=-SD; end
elseif (LLS)
HXf=H*X-f;
gf=H'*(HXf);
HZ= H*Z;
[mm,nn]=size(HZ);
if mm >= nn
% SD =-Z*((HZ'*HZ)\(Z'*gf));
[QHZ, RHZ] = qr(HZ,0);
Pd = QHZ'*HXf;
% 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
else % lp
gf = f;
SD=-Z*Z'*gf;
dirType = SteepDescent;
if norm(SD) < 1e-10 && neqcstr
% This happens when equality constraint is perpendicular
% to objective function f.x.
actlambda = -R\(Q'*(gf));
lambda(indepInd(ACTIND)) = normf * (actlambda ./ normA(ACTIND));
ACTIND = indepInd(ACTIND);
output.iterations = iterations;
return;
end
end
oldind = 0;
% The maximum number of iterations for a simplex type method is when ncstr >=n:
% maxiters = prod(1:ncstr)/(prod(1:numberOfVariables)*prod(1:max(1,ncstr-numberOfVariables)));
%--------------Main Routine-------------------
while iterations < maxiter
iterations = iterations + 1;
if isinf(verbosity)
curr_out = sprintf('Iter: %5.0f, Active: %5.0f, step: %s, proc: %s',iterations,ACTCNT,dirType,how);
disp(curr_out);
end
% Find distance we can move in search direction SD before a
% constraint is violated.
% Gradient with respect to search direction.
GSD=A*SD;
% Note: we consider only constraints whose gradients are greater
% than some threshold. If we considered all gradients greater than
% zero then it might be possible to add a constraint which would lead to
% a singular (rank deficient) working set. The gradient (GSD) of such
% a constraint in the direction of search would be very close to zero.
indf = find((GSD > errnorm * norm(SD)) & ~aix);
if isempty(indf) % No constraints to hit
STEPMIN=1e16;
dist=[]; ind2=[]; ind=[];
else % Find distance to the nearest constraint
dist = abs(cstr(indf)./GSD(indf));
[STEPMIN,ind2] = min(dist);
ind2 = find(dist == STEPMIN);
% Bland's rule for anti-cycling: if there is more than one
% blocking constraint then add the one with the smallest index.
ind=indf(min(ind2));
% Non-cycling rule:
% ind = indf(ind2(1));
end
%----------------Update X---------------------
% Assume we do not delete a constraint
delete_constr = 0;
if ~isempty(indf) && isfinite(STEPMIN) % Hit a constraint
if strcmp(dirType, NewtonStep)
% Newton step and hit a constraint: LLS or is_qp
if STEPMIN > 1 % Overstepped minimum; reset STEPMIN
STEPMIN = 1;
delete_constr = 1;
end
X = X+STEPMIN*SD;
else
% Not a Newton step and hit a constraint: is_qp or LLS or maybe lp
X = X+STEPMIN*SD;
end
else % isempty(indf) | ~isfinite(STEPMIN)
% did not hit a constraint
if strcmp(dirType, NewtonStep)
% Newton step and no constraint hit: LLS or maybe is_qp
STEPMIN = 1; % Exact distance to the solution. Now delete constr.
X = X + SD;
delete_constr = 1;
else % Not a Newton step: is_qp or lp or LLS
if (~is_qp && ~LLS) || strcmp(dirType, NegCurv) % LP or neg def (implies is_qp)
% neg def -- unbounded
if norm(SD) > errnorm
if normalize < 0
STEPMIN=abs((X(numberOfVariables)+1e-5)/(SD(numberOfVariables)+eps));
else
STEPMIN = 1e16;
end
X=X+STEPMIN*SD;
how='unbounded';
exitflag = -3;
msg = sprintf(['Exiting: the solution is unbounded and at infinity;\n' ...
' the constraints are not restrictive enough.']);
if verbosity > 0
disp(msg)
end
else % norm(SD) <= errnorm
how = 'ill posed';
exitflag = -7;
msg = ...
sprintf(['Exiting: the search direction is close to zero; the problem\n' ...
' is ill-posed. The gradient of the objective function may be\n' ...
' zero or the problem may be badly conditioned.']);
if verbosity > 0
disp(msg)
end
end
ACTIND = indepInd(ACTIND);
output.iterations = iterations;
return
else % singular: solve compatible system for a solution: is_qp or LLS
if is_qp
projH = Z'*H*Z;
Zgf = Z'*gf;
projSD = pinv(projH)*(-Zgf);
else % LLS
projH = HZ'*HZ;
Zgf = Z'*gf;
projSD = pinv(projH)*(-Zgf);
end
% Check if compatible
if norm(projH*projSD+Zgf) > 10*eps*(norm(projH) + norm(Zgf))
% system is incompatible --> it's a "chute": use SD from compdir
% unbounded in SD direction
if norm(SD) > errnorm
if normalize < 0
STEPMIN=abs((X(numberOfVariables)+1e-5)/(SD(numberOfVariables)+eps));
else
STEPMIN = 1e16;
end
X=X+STEPMIN*SD;
how='unbounded';
exitflag = -3;
msg = sprintf(['Exiting: the solution is unbounded and at infinity;\n' ...
' the constraints are not restrictive enough.']);
if verbosity > 0
disp(msg)
end
else % norm(SD) <= errnorm
how = 'ill posed';
exitflag = -7;
msg = ...
sprintf(['Exiting: the search direction is close to zero; the problem\n' ...
' is ill-posed. The gradient of the objective function may be\n' ...
' zero or the problem may be badly conditioned.']);
if verbosity > 0
disp(msg)
end
end
ACTIND = indepInd(ACTIND);
output.iterations = iterations;
return
else % Convex -- move to the minimum (compatible system)
SD = Z*projSD;
if gf'*SD > 0
SD = -SD;
end
dirType = 'singular';
% First check if constraint is violated.
GSD=A*SD;
indf = find((GSD > errnorm * norm(SD)) & ~aix);
if isempty(indf) % No constraints to hit
STEPMIN=1;
delete_constr = 1;
dist=[]; ind2=[]; ind=[];
else % Find distance to the nearest constraint
dist = abs(cstr(indf)./GSD(indf));
[STEPMIN,ind2] = min(dist);
ind2 = find(dist == STEPMIN);
% Bland's rule for anti-cycling: if there is more than one
% blocking constraint then add the one with the smallest index.
ind=indf(min(ind2));
end
if STEPMIN > 1 % Overstepped minimum; reset STEPMIN
STEPMIN = 1;
delete_constr = 1;
end
X = X + STEPMIN*SD;
end
end % if ~is_qp | smallRealEig < -eps
end % if strcmp(dirType, NewtonStep)
end % if ~isempty(indf)& isfinite(STEPMIN) % Hit a constraint
%----Check if reached minimum in current subspace-----
if delete_constr
% Note: only reach here if a minimum in the current subspace found
% LP's do not enter here.
if ACTCNT>0
if is_qp
rlambda = -R\(Q'*(H*X+f));
elseif LLS
rlambda = -R\(Q'*(H'*(H*X-f)));
% else: lp does not reach this point
end
actlambda = rlambda;
actlambda(eqix) = abs(rlambda(eqix));
indlam = find(actlambda < 0);
if (~length(indlam))
lambda(indepInd(ACTIND)) = normf * (rlambda./normA(ACTIND));
ACTIND = indepInd(ACTIND);
output.iterations = iterations;
return
end
% Remove constraint
lind = find(ACTIND == min(ACTIND(indlam)));
lind = lind(1);
ACTSET(lind,:) = [];
aix(ACTIND(lind)) = 0;
[Q,R]=qrdelete(Q,R,lind);
ACTIND(lind) = [];
ACTCNT = length(ACTIND);
simplex_iter = 0;
ind = 0;
else % ACTCNT == 0
output.iterations = iterations;
return
end
delete_constr = 0;
end
% If we are in the Phase-1 procedure check if the slack variable
% is zero indicating we have found a feasible starting point.
if normalize < 0
if X(numberOfVariables,1) < eps
ACTIND = indepInd(ACTIND);
output.iterations = iterations;
return;
end
end
% Calculate gradient w.r.t objective at this point
if is_qp
gf=H*X+f;
elseif LLS % LLS
gf=H'*(H*X-f);
% else gf=f still true.
end
% Update constraints
cstr = A*X-B;
cstr(eqix) = abs(cstr(eqix));
if max(cstr) > 1e5 * errnorm
if max(cstr) > norm(X) * errnorm
if exitflag == 1
msg = ...
sprintf('Note: the problem is badly conditioned; the solution may not be reliable.');
if verbosity > 0
disp(msg)
end
end
how='unreliable';
exitflag = -8;
end
end
%----Add blocking constraint to working set----
if ind % Hit a constraint
aix(ind)=1;
CIND = length(ACTIND) + 1;
ACTSET(CIND,:)=A(ind,:);
ACTIND(CIND)=ind;
[m,n]=size(ACTSET);
[Q,R] = qrinsert(Q,R,CIND,A(ind,:)');
ACTCNT = length(ACTIND);
end
if ~simplex_iter
% Z = null(ACTSET);
[m,n]=size(ACTSET);
Z = Q(:,m+1:n);
if ACTCNT == numberOfVariables - 1, simplex_iter = 1; end
oldind = 0;
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -