94 lines
3.7 KiB
Mathematica
94 lines
3.7 KiB
Mathematica
|
|
function p = addImpliedSDP(p)
|
||
|
|
if p.K.q(1)==0 && p.K.s(1) > 0
|
||
|
|
% Search for rows where there is a constant, and a diagonal term
|
||
|
|
% which thus has to be structly positive, we might leads us to a
|
||
|
|
% constraints of the type sum x_i >= 1, if only non-negative integer
|
||
|
|
% variables are involved, entering with positive coefficient (and v.s)
|
||
|
|
newF = [];
|
||
|
|
top = p.K.f + p.K.l + 1;
|
||
|
|
for i = 1:length(p.K.s)
|
||
|
|
F = p.F_struc(top:top + p.K.s(i)^2-1,:);
|
||
|
|
X0 = reshape(F(:,1),p.K.s(i),p.K.s(i));
|
||
|
|
candidates = find(any(X0-diag(diag(X0)),2) & (diag(X0)<=0));
|
||
|
|
if ~isempty(candidates);
|
||
|
|
I = speye(p.K.s(i),p.K.s(i));
|
||
|
|
pos = find(I(:));
|
||
|
|
for j = candidates(1:end)'
|
||
|
|
row = F(pos(j),2:end);
|
||
|
|
used = find(row);
|
||
|
|
if ~isempty(used)
|
||
|
|
if ~any(row(p.noninteger_variables))
|
||
|
|
if all(row <=0) && all(p.ub(used)<=0)
|
||
|
|
row(find(row)) = 1;
|
||
|
|
newF = [newF;-1 -row];
|
||
|
|
elseif all(row >=0) && all(p.lb(used)>=0)
|
||
|
|
row(find(row)) = 1;
|
||
|
|
newF = [newF;-1 row];
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
top = top + p.K.s(i)^2;
|
||
|
|
end
|
||
|
|
if size(newF,1)>0
|
||
|
|
p.F_struc = [p.F_struc(1:p.K.f + p.K.l,:);
|
||
|
|
newF;
|
||
|
|
p.F_struc(1+p.K.f+p.K.l:end,:)];
|
||
|
|
p.K.l = p.K.l + size(newF,1);
|
||
|
|
end
|
||
|
|
|
||
|
|
% Search for trivial variables entering in diagonal elements alone, and
|
||
|
|
% not entering anywhere else in model. Bad modelling?
|
||
|
|
% First, they should not appear in LP cone (can be generalized by
|
||
|
|
% checking that it acts in the correct direction)
|
||
|
|
% TODO: Check for possibility of different signs etc, currently only
|
||
|
|
% implemented for typical test cases
|
||
|
|
candidates = find(~any(p.F_struc(1:p.K.f + p.K.l,2:end),1));
|
||
|
|
fixable = nan(1,length(candidates));
|
||
|
|
|
||
|
|
top = p.K.f + p.K.l + 1;
|
||
|
|
for j = 1:length(p.K.s)
|
||
|
|
F = p.F_struc(top:top + p.K.s(j)^2-1,:);
|
||
|
|
for i = 1:length(candidates(:)')
|
||
|
|
X0 = reshape(F(:,1 + candidates(i)),p.K.s(j),p.K.s(j));
|
||
|
|
% Diagonal matrix?
|
||
|
|
d = diag(X0);
|
||
|
|
if nnz((X0-diag(d)))==0
|
||
|
|
if all(sign(d)<=0) && p.c(i)>=0 && (isnan(fixable(i)) || fixable(i)==-1)
|
||
|
|
fixable(i) = -1;
|
||
|
|
elseif all(sign(d)>=0) && p.c(i)<=0 && (isnan(fixable(i)) || fixable(i)==1)
|
||
|
|
fixable(i) = 1;
|
||
|
|
else
|
||
|
|
fixable(i) = 0;
|
||
|
|
end
|
||
|
|
else
|
||
|
|
fixable(i) = 0;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
top = top + p.K.s(j)^2;
|
||
|
|
end
|
||
|
|
p.adjustable = candidates(find(fixable));
|
||
|
|
for i = candidates(find(~isnan(fixable)))
|
||
|
|
% if fixable(i) == -1
|
||
|
|
% if ~isinf(p.lb(i))
|
||
|
|
% % p.ub(i) = p.lb(i);
|
||
|
|
% % p.F_struc(:,1) = p.F_struc(:,1) + p.F_struc(:,i+1)*p.lb(i);
|
||
|
|
% % p.F_struc(:,i+1) = 0;
|
||
|
|
% % else
|
||
|
|
% % % TODO whole row/column should be removed from the LMI!
|
||
|
|
% end
|
||
|
|
% elseif fixable(i) == 1
|
||
|
|
% if ~isinf(p.ub(i))
|
||
|
|
% % p.ub(i) = p.lb(i);
|
||
|
|
% % p.F_struc(:,1) = p.F_struc(:,1) + p.F_struc(:,i+1)*p.lb(i);
|
||
|
|
% % p.F_struc(:,i+1) = 0;
|
||
|
|
% % else
|
||
|
|
% % % TODO whole row/column should be removed from the LMI!
|
||
|
|
% end
|
||
|
|
% end
|
||
|
|
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|