140 lines
4.5 KiB
Mathematica
140 lines
4.5 KiB
Mathematica
|
|
function [p,feasible,lower] = lpbmitighten(p,lower,upper,lpsolver,xmin,improvethese)
|
||
|
|
|
||
|
|
if nargin<6
|
||
|
|
improvethese = ones(length(p.lb),1);
|
||
|
|
end
|
||
|
|
|
||
|
|
% Don't use LP to propagate variables which only enter as x + other in one
|
||
|
|
% single (in)equality.
|
||
|
|
ind = sum(p.F_struc(1:p.K.f+p.K.l,:) | p.F_struc(1:p.K.f+p.K.l,:),1);
|
||
|
|
oneterm = find(ind(2:end) == 1);
|
||
|
|
for i = 1:length(oneterm)
|
||
|
|
a = p.F_struc(1:p.K.f+p.K.l,oneterm(i)+1);
|
||
|
|
j = find(a);
|
||
|
|
if j <= p.K.f
|
||
|
|
b = p.F_struc(j,:);
|
||
|
|
if nnz(b(2:end))==2
|
||
|
|
improvethese(oneterm(i))=0;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
% Construct problem with only linear terms
|
||
|
|
% and add cuts from lower/ upper bounds
|
||
|
|
|
||
|
|
p_test = p;
|
||
|
|
p_test.F_struc = p.lpcuts;
|
||
|
|
p_test.K.l = size(p.lpcuts,1);
|
||
|
|
p_test.K.f = 0;
|
||
|
|
p_test.K.s = 0;
|
||
|
|
p_test.K.q = 0;
|
||
|
|
if ~isnan(lower) & ~isinf(lower)
|
||
|
|
p_test.F_struc = [-(p.lower-abs(p.lower)*0.01)+p.f p_test.c';p_test.F_struc];
|
||
|
|
if p.diagonalized
|
||
|
|
n = length(p.c)/2;
|
||
|
|
f = p.f;
|
||
|
|
c = p.c(1:n);
|
||
|
|
d = p.c(n+1:end);
|
||
|
|
neg = find(d<0);
|
||
|
|
if length(neg)>0
|
||
|
|
f = f + sum(d(neg).*xmin(neg).^2 - 2*d(neg).*xmin(neg).^2);
|
||
|
|
c(neg) = c(neg) + 2*d(neg).*xmin(neg);
|
||
|
|
d(neg) = 0;
|
||
|
|
p_test.F_struc = [-(p.lower-abs(p.lower)*0.01)+f c' d';p_test.F_struc];
|
||
|
|
p_test.K.l = p_test.K.l + 1;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if upper < inf & ~(nnz(p.c)==0 & nnz(p.Q)==0)
|
||
|
|
if p.diagonalized
|
||
|
|
n = length(p.c)/2;
|
||
|
|
f = p.f;
|
||
|
|
c = p.c(1:n);
|
||
|
|
d = p.c(n+1:end);
|
||
|
|
pos = find(d>0);
|
||
|
|
if length(pos)>0
|
||
|
|
f = f + sum(d(pos).*xmin(pos).^2 - 2*d(pos).*xmin(pos).^2);
|
||
|
|
c(pos) = c(pos) + 2*d(pos).*xmin(pos);
|
||
|
|
d(pos) = 0;
|
||
|
|
p_test.F_struc = [upper+abs(upper)*0.01-f -c' -d';p_test.F_struc];
|
||
|
|
p_test.F_struc = [upper+abs(upper)*0.01-p.f -p_test.c';p_test.F_struc];
|
||
|
|
p_test.K.l = p_test.K.l + 2;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
p_test.F_struc = [upper+abs(upper)*0.01-p.f -p_test.c';p_test.F_struc];
|
||
|
|
p_test.K.l = p_test.K.l + 1;
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
if p.options.bmibnb.cut.evalvariable
|
||
|
|
p_test = addBilinearVariableCuts(p_test);
|
||
|
|
end
|
||
|
|
if p.options.bmibnb.cut.evalvariable
|
||
|
|
p_test = addEvalVariableCuts(p_test);
|
||
|
|
end
|
||
|
|
if p.options.bmibnb.cut.multipliedequality
|
||
|
|
p_test = addMultipliedEqualityCuts(p_test);
|
||
|
|
end
|
||
|
|
|
||
|
|
% Try to get rid of numerical noise (this is far from stringent, but it
|
||
|
|
% works, and help GLPK from crashing in some instances)
|
||
|
|
%p_test.F_struc = unique(round(p_test.F_struc*1e12)/1e12,'rows');
|
||
|
|
p_test.K.l = size(p_test.F_struc,1);
|
||
|
|
p_test.F_struc = [p.F_struc(1:1:p.K.f,:);p_test.F_struc];
|
||
|
|
p_test.K.f = p.K.f;
|
||
|
|
|
||
|
|
feasible = 1;
|
||
|
|
|
||
|
|
% Perform reduction on most violating approximations at current solution
|
||
|
|
if p.options.bmibnb.lpreduce ~= 1
|
||
|
|
n = ceil(max(p.options.bmibnb.lpreduce*length(p_test.linears),1));
|
||
|
|
res = zeros(length(p.lb),1);
|
||
|
|
for i = 1:size(p.bilinears,1)
|
||
|
|
res(p.bilinears(i,2)) = res(p.bilinears(i,2)) + abs( p.x0(p.bilinears(i,1))-p.x0(p.bilinears(i,2)).*p.x0(p.bilinears(i,3)));
|
||
|
|
res(p.bilinears(i,3)) = res(p.bilinears(i,3)) + abs( p.x0(p.bilinears(i,1))-p.x0(p.bilinears(i,2)).*p.x0(p.bilinears(i,3)));
|
||
|
|
end
|
||
|
|
res = res(p.linears);
|
||
|
|
[ii,jj] = sort(abs(res));
|
||
|
|
jj = jj(end-n+1:end);
|
||
|
|
else
|
||
|
|
jj=1:length(p_test.linears);
|
||
|
|
end
|
||
|
|
|
||
|
|
j = 1;
|
||
|
|
while feasible & j<=length(jj)
|
||
|
|
i = p_test.linears(jj(j));
|
||
|
|
if abs(p.ub(i)-p.lb(i)>p.options.bmibnb.vartol) & improvethese(i)
|
||
|
|
p_test.c = eyev(length(p_test.c),i);
|
||
|
|
output = feval(lpsolver,removenonlinearity(p_test));
|
||
|
|
p.counter.lpsolved = p.counter.lpsolved + 1;
|
||
|
|
if output.problem == 0 | output.problem == 2 | output.problem == 12
|
||
|
|
if output.problem == 0
|
||
|
|
if p_test.lb(i) < output.Primal(i)-1e-5
|
||
|
|
p_test.lb(i) = output.Primal(i);
|
||
|
|
p_test = updateonenonlinearbound(p_test,i);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
p_test.c = -p_test.c;
|
||
|
|
output = feval(lpsolver,removenonlinearity(p_test));
|
||
|
|
p.counter.lpsolved = p.counter.lpsolved + 1;
|
||
|
|
if output.problem == 0
|
||
|
|
if p_test.ub(i) > output.Primal(i)+1e-5
|
||
|
|
p_test.ub(i) = output.Primal(i);
|
||
|
|
p_test = updateonenonlinearbound(p_test,i);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if output.problem == 1
|
||
|
|
feasible = 0;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if output.problem == 1
|
||
|
|
feasible = 0;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
j = j + 1;
|
||
|
|
end
|
||
|
|
p_test = clean_bounds(p_test);
|
||
|
|
p.lb = p_test.lb;
|
||
|
|
p.ub = p_test.ub;
|
||
|
|
% Save these for re-use
|
||
|
|
p.evalMap = p_test.evalMap;
|