401 lines
10 KiB
Matlab
Executable File
401 lines
10 KiB
Matlab
Executable File
function p = propagate_bounds_from_equalities(p)
|
|
|
|
LU = [p.lb p.ub];
|
|
|
|
p_F_struc = p.F_struc;
|
|
n_p_F_struc_cols = size(p_F_struc,2);
|
|
|
|
fixedVars = find(p.lb == p.ub & p.variabletype(:) == 0);
|
|
if ~isempty(fixedVars)
|
|
p_F_struc_forbilin = p_F_struc;
|
|
p_F_struc_forbilin(:,1) = p_F_struc(:,1) + p_F_struc(:,1+fixedVars)*p.lb(fixedVars);
|
|
p_F_struc_forbilin(:,1+fixedVars) = 0;
|
|
else
|
|
p_F_struc_forbilin=p_F_struc;
|
|
end
|
|
|
|
usedVariables = find(any(p.F_struc(:,2:end)));
|
|
if all(isinf(p.lb(usedVariables))) & all(isinf(p.ub(usedVariables)))
|
|
return
|
|
end
|
|
|
|
if p.K.f >0
|
|
interestingRows = find(p_F_struc(1:p.K.f,1));
|
|
if ~isempty(interestingRows)
|
|
S = p_F_struc(interestingRows,:);
|
|
S(:,1)=0;
|
|
S = sum(S|S,2) - abs(sum(S,2));
|
|
interestingRows = interestingRows(find(S==0));
|
|
for j = interestingRows(:)'
|
|
thisrow = p_F_struc(j,:);
|
|
if thisrow(1)<0
|
|
thisrow = -thisrow;
|
|
end
|
|
[row,col,val] = find(thisrow);
|
|
% Find bounds from sum(xi) = 1, xi>0
|
|
if all(val(2:end) < 0)
|
|
usedVars = col(2:end)-1;
|
|
if all(p.lb(usedVars)>=0)
|
|
p.ub(usedVars) = min( p.ub(usedVars) , val(1)./abs(val(2:end)'));
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
% Presolve from bilinear x*y == k
|
|
if any(p.variabletype == 1)
|
|
for j = 1:p.K.f
|
|
if p_F_struc_forbilin(j,1)~=0
|
|
[row,col,val] = find(p_F_struc_forbilin(j,:));
|
|
|
|
% Find bounds from sum(xi) = 1, xi>0
|
|
if length(col)==2
|
|
val = val/val(2); % val(1) + x==0
|
|
var = col(2)-1;
|
|
if p.variabletype(var)==1
|
|
[ij] = find(p.monomtable(var,:));
|
|
if p.lb(ij(1))>=0 & p.lb(ij(2))>=0
|
|
% xi*xj == val(1)
|
|
if -val(1)<0
|
|
p.feasible = 0;
|
|
return
|
|
else
|
|
p.ub(ij(2)) = min( p.ub(ij(2)),-val(1)/p.lb(ij(1)));
|
|
p.ub(ij(1)) = min( p.ub(ij(1)),-val(1)/p.lb(ij(2)));
|
|
p.lb(ij(2)) = max( p.lb(ij(2)),-val(1)/p.ub(ij(1)));
|
|
p.lb(ij(1)) = max( p.lb(ij(1)),-val(1)/p.ub(ij(2)));
|
|
end
|
|
elseif -val(1)>0 & p.lb(ij(1))>=0
|
|
p.lb(ij(2)) = max(0,p.lb(ij(2)));
|
|
elseif -val(1)>0 & p.lb(ij(2))>=0
|
|
p.lb(ij(1)) = max(0,p.lb(ij(1)));
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
A = p.F_struc(1:p.K.f,2:end);
|
|
AT = A';
|
|
Ap = max(0,A);ApT = Ap';
|
|
Am = min(0,A);AmT = Am';
|
|
|
|
two_terms = sum(p.F_struc(1:p.K.f,2:end) | p.F_struc(1:p.K.f,2:end),2)==2;
|
|
|
|
for j = find(sum(p.F_struc(1:p.K.f,2:end) | p.F_struc(1:p.K.f,2:end),2)>1)'
|
|
% Simple x == y
|
|
done = 0;
|
|
b = full(p_F_struc(j,1));
|
|
if b==0 & two_terms(j)
|
|
[row,col,val] = find(p_F_struc(j,:));
|
|
if length(row) == 2
|
|
if val(1) == -val(2)
|
|
p.lb(col(1)-1) = max(p.lb(col(1)-1),p.lb(col(2)-1));
|
|
p.lb(col(2)-1) = max(p.lb(col(1)-1),p.lb(col(2)-1));
|
|
p.ub(col(1)-1) = min(p.ub(col(1)-1),p.ub(col(2)-1));
|
|
p.ub(col(2)-1) = min(p.ub(col(1)-1),p.ub(col(2)-1));
|
|
done = 1;
|
|
elseif val(1) == val(2)
|
|
p.lb(col(1)-1) = max(p.lb(col(1)-1),-p.ub(col(2)-1));
|
|
p.lb(col(2)-1) = max(-p.ub(col(1)-1),p.lb(col(2)-1));
|
|
p.ub(col(1)-1) = min(p.ub(col(1)-1),-p.lb(col(2)-1));
|
|
p.ub(col(2)-1) = min(-p.lb(col(1)-1),p.ub(col(2)-1));
|
|
done = 1;
|
|
end
|
|
end
|
|
end
|
|
if ~done
|
|
a = AT(:,j)';
|
|
ap = (ApT(:,j)');
|
|
am = (AmT(:,j)');
|
|
find_a = find(a);
|
|
|
|
p_ub = p.ub(find_a);
|
|
p_lb = p.lb(find_a);
|
|
|
|
inflb = isinf(p_lb);
|
|
infub = isinf(p_ub);
|
|
if ~all(inflb & infub)
|
|
if any(inflb) | any(infub)
|
|
[p_lb,p_ub] = propagatewINFreduced(full(a(find_a)),full(ap(find_a)),full(am(find_a)),p_lb,p_ub,b);
|
|
p.lb(find_a) = p_lb;
|
|
p.ub(find_a) = p_ub;
|
|
else
|
|
[p_lb,p_ub] = propagatewoINFreduced(full(a(find_a)),full(ap(find_a)),full(am(find_a)),p_lb,p_ub,b);
|
|
p.lb(find_a) = p_lb;
|
|
p.ub(find_a) = p_ub;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
close = find(abs(p.lb - p.ub) < 1e-12);
|
|
p.lb(close) = (p.lb(close)+p.ub(close))/2;
|
|
p.ub(close) = p.lb(close);
|
|
|
|
p = update_integer_bounds(p);
|
|
|
|
if ~isequal(LU,[p.lb p.ub])
|
|
p.changedbounds = 1;
|
|
end
|
|
|
|
if any(p.lb > p.ub)
|
|
p.feasible = 0;
|
|
end
|
|
|
|
|
|
|
|
function [p_lb,p_ub] = propagatewINFreduced(a,ap,am,p_lb,p_ub,b);
|
|
%a = AT(:,j)';
|
|
%ap = (ApT(:,j)');
|
|
%am = (AmT(:,j)');
|
|
|
|
%p_ub = p.ub;
|
|
%p_lb = p.lb;
|
|
|
|
%find_a = find(a);
|
|
% find_a = find_a(min(find(isinf(p.lb(find_a)) | isinf(p.ub(find_a)))):end);
|
|
for k = 1:length(a)%find_a
|
|
|
|
p_ub_k = p_ub(k);
|
|
p_lb_k = p_lb(k);
|
|
|
|
if (p_ub_k-p_lb_k) > 1e-8
|
|
L = p_lb;
|
|
U = p_ub;
|
|
L(k) = 0;
|
|
U(k) = 0;
|
|
ak = a(k);
|
|
|
|
if ak < 0
|
|
ak = -ak;
|
|
aa = am;
|
|
am = -ap;
|
|
ap = -aa;
|
|
b = -b;
|
|
a = -a;
|
|
end
|
|
|
|
if ak > 0
|
|
use1 = find(ap'~=0);
|
|
use2 = find(am'~=0);
|
|
newlower = (-b - ap(use1)*U(use1) - am(use2)*L(use2))/ak;
|
|
newupper = (-b - am(use2)*U(use2) - ap(use1)*L(use1))/ak;
|
|
%newlower = (-b - ap*U - am*L)/ak;
|
|
%newupper = (-b - am*U - ap*L)/ak;
|
|
else
|
|
newlower = (-b - am*U - ap*L)/ak;
|
|
newupper = (-b - ap*U - am*L)/ak;
|
|
end
|
|
if p_ub_k>newupper
|
|
p_ub(k) = newupper;
|
|
end
|
|
if p_lb_k<newlower
|
|
p_lb(k) = newlower;
|
|
end
|
|
end
|
|
end
|
|
p.ub = p_ub;
|
|
p.lb = p_lb;
|
|
|
|
function [p_lb,p_ub] = propagatewoINFreduced(a,ap,am,p_lb,p_ub,b);
|
|
|
|
L = p_lb;
|
|
U = p_ub;
|
|
|
|
apU = ap*U;
|
|
amU = am*U;
|
|
apL = ap*L;
|
|
amL = am*L;
|
|
|
|
papU = ap.*U';
|
|
pamU = am.*U';
|
|
papL = ap.*L';
|
|
pamL = am.*L';
|
|
|
|
minusbminusapUminusamL = -b-apU-amL;
|
|
minusbminusamUminusapL = -b-amU-apL;
|
|
for k = 1:length(a)%find_a
|
|
|
|
p_ub_k = p_ub(k);
|
|
p_lb_k = p_lb(k);
|
|
|
|
if (p_ub_k-p_lb_k) > 1e-8
|
|
ak = a(k);
|
|
if ak > 0
|
|
%newlower = (-b-apU+papU(k)-amL+pamL(k) )/ak;
|
|
%newupper = (-b-amU+pamU(k)-apL+papL(k) )/ak;
|
|
newlower = -1e-15 + (minusbminusapUminusamL+papU(k)+pamL(k) )/ak;
|
|
newupper = 1e-15 + (minusbminusamUminusapL+pamU(k)+papL(k) )/ak;
|
|
else
|
|
newlower = -1e-15 + (minusbminusamUminusapL+pamU(k)+papL(k) )/ak;
|
|
newupper = 1e-15 + (minusbminusapUminusamL+papU(k)+pamL(k) )/ak;
|
|
end
|
|
if p_ub_k>newupper
|
|
p_ub(k) = newupper;
|
|
U(k) = newupper;
|
|
apU = ap*U;
|
|
amU = am*U;
|
|
papU = ap.*U';
|
|
pamU = am.*U';
|
|
minusbminusapUminusamL = -b-apU-amL;
|
|
minusbminusamUminusapL = -b-amU-apL;
|
|
end
|
|
if p_lb_k<newlower
|
|
p_lb(k) = newlower;
|
|
L(k) = newlower;
|
|
apL = ap*L;
|
|
amL = am*L;
|
|
papL = ap.*L';
|
|
pamL = am.*L';
|
|
minusbminusapUminusamL = -b-apU-amL;
|
|
minusbminusamUminusapL = -b-amU-apL;
|
|
end
|
|
end
|
|
end
|
|
%p.ub = p_ub;
|
|
%p.lb = p_lb;
|
|
|
|
function p = propagatewINF(p,AT,ApT,AmT,j,b);
|
|
a = AT(:,j)';
|
|
ap = (ApT(:,j)');
|
|
am = (AmT(:,j)');
|
|
|
|
|
|
p_ub = p.ub;
|
|
p_lb = p.lb;
|
|
|
|
find_a = find(a);
|
|
% find_a = find_a(min(find(isinf(p.lb(find_a)) | isinf(p.ub(find_a)))):end);
|
|
for k = find_a
|
|
|
|
p_ub_k = p_ub(k);
|
|
p_lb_k = p_lb(k);
|
|
|
|
if (p_ub_k-p_lb_k) > 1e-8
|
|
L = p_lb;
|
|
U = p_ub;
|
|
L(k) = 0;
|
|
U(k) = 0;
|
|
ak = a(k);
|
|
if ak > 0
|
|
newlower = (-b - ap*U - am*L)/ak;
|
|
newupper = (-b - am*U - ap*L)/ak;
|
|
else
|
|
newlower = (-b - am*U - ap*L)/ak;
|
|
newupper = (-b - ap*U - am*L)/ak;
|
|
end
|
|
% if isinf(newlower) | isinf(newupper)
|
|
% z = newlower;
|
|
% end
|
|
if p_ub_k>newupper
|
|
p_ub(k) = newupper;
|
|
end
|
|
if p_lb_k<newlower
|
|
p_lb(k) = newlower;
|
|
end
|
|
end
|
|
end
|
|
p.ub = p_ub;
|
|
p.lb = p_lb;
|
|
|
|
function p = propagatewoINF(p,AT,ApT,AmT,j,b);
|
|
a = full(AT(:,j)');
|
|
ap = full((ApT(:,j)'));
|
|
am = full((AmT(:,j)'));
|
|
|
|
|
|
p_ub = p.ub;
|
|
p_lb = p.lb;
|
|
|
|
find_a = find(a);
|
|
|
|
L = p_lb;
|
|
U = p_ub;
|
|
|
|
apU = ap*U;
|
|
amU = am*U;
|
|
apL = ap*L;
|
|
amL = am*L;
|
|
|
|
papU = ap.*U';
|
|
pamU = am.*U';
|
|
papL = ap.*L';
|
|
pamL = am.*L';
|
|
|
|
|
|
minusbminusapUminusamL = -b-apU-amL;
|
|
minusbminusamUminusapL = -b-amU-apL;
|
|
for k = find_a
|
|
|
|
p_ub_k = p_ub(k);
|
|
p_lb_k = p_lb(k);
|
|
|
|
if (p_ub_k-p_lb_k) > 1e-8
|
|
ak = a(k);
|
|
if ak > 0
|
|
%newlower = (-b-apU+papU(k)-amL+pamL(k) )/ak;
|
|
%newupper = (-b-amU+pamU(k)-apL+papL(k) )/ak;
|
|
newlower = (minusbminusapUminusamL+papU(k)+pamL(k) )/ak;
|
|
newupper = (minusbminusamUminusapL+pamU(k)+papL(k) )/ak;
|
|
else
|
|
newlower = (minusbminusamUminusapL+pamU(k)+papL(k) )/ak;
|
|
newupper = (minusbminusapUminusamL+papU(k)+pamL(k) )/ak;
|
|
end
|
|
if p_ub_k>newupper
|
|
p_ub(k) = newupper;
|
|
U(k) = newupper;
|
|
apU = ap*U;
|
|
amU = am*U;
|
|
papU = ap.*U';
|
|
pamU = am.*U';
|
|
minusbminusapUminusamL = -b-apU-amL;
|
|
minusbminusamUminusapL = -b-amU-apL;
|
|
end
|
|
if p_lb_k<newlower
|
|
p_lb(k) = newlower;
|
|
L(k) = newlower;
|
|
apL = ap*L;
|
|
amL = am*L;
|
|
papL = ap.*L';
|
|
pamL = am.*L';
|
|
minusbminusapUminusamL = -b-apU-amL;
|
|
minusbminusamUminusapL = -b-amU-apL;
|
|
end
|
|
end
|
|
end
|
|
p.ub = p_ub;
|
|
p.lb = p_lb;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|