248 lines
6.8 KiB
Matlab
Executable File
248 lines
6.8 KiB
Matlab
Executable File
function [dualUpper,L,U] = derivedualBounds(H,c,A,b,E,f,ops,parametricDomain)
|
|
|
|
if isempty(A)
|
|
dualUpper = [];
|
|
L = [];
|
|
U = [];
|
|
return
|
|
end
|
|
|
|
n = length(c);
|
|
m = length(b);
|
|
me = length(f);
|
|
|
|
x = sdpvar(n,1);
|
|
Lambda = sdpvar(m,1);
|
|
mu = sdpvar(me,1);
|
|
|
|
F = [];
|
|
if ~isempty(b)
|
|
F = [F, A*x <= b];
|
|
end
|
|
if ~isempty(f)
|
|
F = [F, E*x == f];
|
|
end
|
|
|
|
% Start by computing primal lower bounds
|
|
if nargin < 7
|
|
ops = sdpsettings('verbose',0);
|
|
end
|
|
ops2 = ops;
|
|
ops2.verbose = max(0,ops.verbose-1);;
|
|
all_bounded = 1;
|
|
if ops.verbose
|
|
disp(['*Computing ' num2str(length(x)) ' primal bounds (required for dual bounds)']);
|
|
end
|
|
|
|
z = recover(unique([depends(c) depends(b)]));
|
|
xz = [x;z];
|
|
nz = length(z);
|
|
nTOT = n + length(z);
|
|
rhs = 0;
|
|
if ~isempty(b)
|
|
rhs = rhs + A'*Lambda;
|
|
end
|
|
if ~isempty(f)
|
|
rhs = rhs + E'*mu;
|
|
end
|
|
|
|
[dummy,L,U] = boundingbox([F,parametricDomain,H*x + c + rhs==0,Lambda>=0],ops2,xz);
|
|
|
|
c0C = full(getbase(c));
|
|
c0 = c0C(:,1);
|
|
C = c0C(:,2:end);
|
|
if nnz(C)==0
|
|
C = spalloc(n,length(z),0);
|
|
else
|
|
if length(z)>0 & size(C,2) < length(z)
|
|
C = [];
|
|
for i = 1:length(z)
|
|
C = [C getbasematrix(c,getvariables(z(i)))];
|
|
end
|
|
end
|
|
end
|
|
|
|
b0B = full(getbase(b));
|
|
b0 = b0B(:,1);
|
|
B = b0B(:,2:end);
|
|
if nnz(B)==0
|
|
B = spalloc(n,length(z),0);
|
|
else
|
|
if length(z)>0 & size(B,2) < length(z)
|
|
B = [];
|
|
for i = 1:length(z)
|
|
B = [B getbasematrix(b,getvariables(z(i)))];
|
|
end
|
|
end
|
|
end
|
|
|
|
if isa(b,'sdpvar')
|
|
if ops.verbose
|
|
disp(['*Computing ' num2str(length(b)) ' bounds on parameterized RHS (required for dual bounds)']);
|
|
end
|
|
[dummy,bmin,bmax] = boundingbox([F,parametricDomain],ops2,b);
|
|
end
|
|
|
|
% Lift
|
|
Hlift = [H C/2;C'/2 zeros(size(C,2))];
|
|
if ops.kkt.dualpresolve.lplift
|
|
XZ = sdpvar(nTOT);
|
|
end
|
|
constraints = [Lambda >= 0,parametricDomain,F];
|
|
constraints = [constraints,H*x + c + rhs==0];
|
|
finiteL = find(~isinf(L));
|
|
if ~isempty(finiteL)
|
|
constraints = [constraints,L(finiteL)<=xz(finiteL)];
|
|
end
|
|
finiteU = find(~isinf(U));
|
|
if ~isempty(finiteU)
|
|
constraints = [constraints,xz(finiteU) <= U(finiteU)];
|
|
end
|
|
|
|
if ~isa(f,'double')
|
|
disp('Parameterized RHS in equality not yet supported in lifting based bounds')
|
|
ops.kkt.dualpresolve.lplift = 0;
|
|
end
|
|
|
|
if ops.kkt.dualpresolve.lplift
|
|
if isempty(f)
|
|
temp = 0;
|
|
else
|
|
temp = f'*mu;
|
|
end
|
|
|
|
if nnz(Hlift)>0
|
|
for i = 1:nTOT
|
|
for j = i:nTOT
|
|
if (L(i)==U(i) & L(j)==U(j)) & ~isinf(L(j))
|
|
XZ(i,j) = L(i)*L(j);
|
|
XZ(j,i) = L(i)*L(j);
|
|
XZ(i,i) = L(i)^2;
|
|
XZ(j,j) = L(j)^2;
|
|
elseif L(i)==U(i) & ~isinf(L(i))
|
|
XZ(i,j) = L(i)*xz(j);
|
|
XZ(j,i) = L(i)*xz(j);
|
|
XZ(i,i) = L(i)^2;
|
|
elseif L(j)==U(j) & ~isinf(L(j))
|
|
XZ(i,j) = L(j)*xz(i);
|
|
XZ(j,i) = L(j)*xz(i);
|
|
XZ(j,j) = L(j)^2;
|
|
else
|
|
% (xi-Li)(xj-Lj)>0
|
|
if ~isinf(L(i)) & ~isinf(L(j))
|
|
constraints = [constraints, XZ(i,j)-L(i)*xz(j)-L(j)*xz(i)+L(i)*L(j)>=0];
|
|
end
|
|
% (xi-Li)(Uj-xj)>0
|
|
if ~isinf(L(i)) & ~isinf(U(j))
|
|
constraints = [constraints, xz(i)*U(j)+L(i)*xz(j)-L(i)*U(j)-XZ(i,j)>=0];
|
|
end
|
|
% (xj-Lj)(Ui-xi)>0
|
|
if ~isinf(U(i)) & ~isinf(L(j))
|
|
constraints = [constraints, xz(j)*U(i)+L(j)*xz(i)-L(j)*U(i)-XZ(j,i)>=0];
|
|
end
|
|
% (Uj-xj)(Ui-xi)>0
|
|
if ~isinf(U(i)) & ~isinf(U(j))
|
|
constraints = [constraints, U(j)*U(i)-U(j)*xz(i)-xz(j)*U(i)+XZ(j,i)>=0];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if isa(b,'sdpvar')
|
|
if ~any(isinf(bmax))
|
|
constraints = [constraints,-(trace(Hlift*XZ) + c0'*x+temp) <= bmax'*Lambda];
|
|
end
|
|
if ~any(isinf(bmin))
|
|
constraints = [constraints,-(trace(Hlift*XZ) + c0'*x+temp) >= bmin'*Lambda];
|
|
end
|
|
else
|
|
constraints = [constraints,trace(Hlift*XZ) + c0'*x + temp + b'*Lambda==0];
|
|
end
|
|
|
|
end
|
|
|
|
if ops.verbose
|
|
disp(['*Computing ' num2str(length(Lambda)) ' dual bounds']);
|
|
end
|
|
ops2.verbose = 0;
|
|
|
|
dualUpper = inf(length(Lambda),1);
|
|
|
|
% always exploit disjoint constraints
|
|
disjoints = zeros(length(b));
|
|
s = sdpvar(length(b),1);
|
|
|
|
% Create an optimizer object which takes no input and returns optimal
|
|
% Lambda. We will use some hacks to update this model and resolving
|
|
% with different objectives and constraints. We cannot use multiple
|
|
% objectives approach since we have different constraints, and we
|
|
% cannot use optimizer object directly since constraints change
|
|
p = optimizer([constraints,s == b-A*x],-sum(Lambda),ops2,[],Lambda);
|
|
|
|
Model = p.model;
|
|
LambdaIndicies = find(Model.c);
|
|
Model.c = Model.c*0;
|
|
sIndicies = [ find(Model.used_variables==getvariables(s(1))): find(Model.used_variables==getvariables(s(end)))];
|
|
|
|
for dualPass = 1:ops.kkt.dualpresolve.passes
|
|
for i = 1:m
|
|
if dualUpper(i)>0
|
|
iModel = Model;
|
|
% Maximize Lambda(i)...
|
|
iModel.c = Model.c*0;
|
|
iModel.c(LambdaIndicies(i))=-1;
|
|
|
|
% s(i) == 0
|
|
iModel.lb(sIndicies(i)) = 0;
|
|
iModel.ub(sIndicies(i)) = 0;
|
|
|
|
% Add known dual bounds
|
|
r = find(~isinf(dualUpper));
|
|
|
|
iModel.ub(LambdaIndicies(r)) = dualUpper(r);
|
|
|
|
% Find disjoint constraints
|
|
a = A(i,:);
|
|
a = setdiff(findrows(A,-a),i);
|
|
iModel.ub(LambdaIndicies(a)) = 0;
|
|
|
|
% Solve this instance
|
|
p = updatemodel(p,iModel);
|
|
[Lambda,isol] = p{[]};
|
|
sol.problem = isol;
|
|
|
|
if sol.problem == 12
|
|
iModel.c = iModel.c*0;
|
|
p = updatemodel(p,iModel);
|
|
[Lambda,isol] = p{[]};
|
|
sol.problem = isol;
|
|
if sol.problem == 1
|
|
dualUpper(i,1) = 0;
|
|
elseif sol.problem == 0
|
|
sol.problem = 2;
|
|
end
|
|
end
|
|
if sol.problem == 0
|
|
dualUpper(i,1) = double(Lambda(i));
|
|
elseif sol.problem == 2
|
|
dualUpper(i,1) = inf;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if ops.verbose
|
|
if all(isinf(dualUpper))
|
|
disp('*Warning: All dual upper bounds are infinite');
|
|
elseif any(isinf(dualUpper))
|
|
disp('*Warning: Some of the dual upper bounds are infinite');
|
|
else
|
|
disp('*Success: All dual upper bounds are finite');
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|