Dynamic-Calibration/utils/YALMIP-master/modules/global/propagate_bounds_from_equal...

401 lines
10 KiB
Mathematica
Raw Normal View History

2019-12-18 11:25:45 +00:00
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;