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 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 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 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