Dynamic-Calibration/utils/YALMIP-master/modules/global/rounder.m

114 lines
4.4 KiB
Mathematica
Raw Permalink Normal View History

2019-12-18 11:25:45 +00:00
function [upper,x_min] = rounder(p,relaxedsolution,prelaxed)
% Extremely simple heuristic for finding integer solutions.
% This was the relaxed solution
x = relaxedsolution.Primal;
% Assume we fail
upper = inf;
x_min = x;
% These should be integer
intvars = [p.integer_variables(:);p.binary_variables(:)];
convars = p.noninteger_variables;
if ismember('shifted round',p.options.bnb.rounding)
% Pre-extract...
if length(convars)==1 && length(p.K.s)==1 && p.K.s(1) > 0
H = p.F_struc(1+p.K.l+p.K.f:end,:);
H0 = reshape(H(:,1),p.K.s(1),p.K.s(1));if nnz(H0)/numel(H0)>0.5;H0 = full(H0);end
Hx = reshape(H(:,1+convars),p.K.s(1),p.K.s(1));if nnz(Hx)/numel(Hx)>0.5;Hx = full(Hx);end
Hz = H(:,1 + intvars);if nnz(Hz)/numel(Hz)>0.5;Hz = full(Hz);end
end
% Round, update nonlinear terms, and compute feasibility
for tt = -.5:0.1:0.5
xtemp = x;xtemp(intvars) = round(xtemp(intvars)+tt);
xtemp(p.binary_variables(:)) = min(1,xtemp(p.binary_variables(:)));
xtemp(p.binary_variables(:)) = max(0,xtemp(p.binary_variables(:)));
xtemp = fix_semivar(p,xtemp);
xtemp = fix_atmost(p,xtemp,x);
xtemp = setnonlinearvariables(p,xtemp);
upperhere = computecost(p.f,p.corig,p.Q,xtemp,p);
if upperhere < upper
if checkfeasiblefast(p,xtemp,p.options.bnb.feastol)%res>-p.options.bnb.feastol
x_min = xtemp;
upper =upperhere;
else
% Check for common SDP case such as maximizing smallest eigenvalue
% or minimizing largest.
% With x fixed, smallest t can be computed by gevp
% TODO: Support and loop over several LMIs
if length(convars) == 1 && length(p.K.s)==1 && p.K.s(1)>0
Hy = H0 + reshape(Hz*xtemp(intvars),p.K.s(1),p.K.s(1));
s = eig(full(Hx),full(Hy));
s(isinf(s))=[];
s(isnan(s))=[];
if any(s)
xtemp(convars) = min(-1./s(s~=0));
if ~isnan(xtemp(convars))
xtemp(convars) = max(xtemp(convars),p.lb(convars));
xtemp(convars) = min(xtemp(convars),p.ub(convars));
upperhere = computecost(p.f,p.corig,p.Q,xtemp,p);
if upperhere < upper && checkfeasiblefast(p,xtemp,p.options.bnb.feastol)%res>-p.options.bnb.feastol
x_min = xtemp;
upper = upperhere;
end
end
end
end
end
end
end
end
if length(prelaxed.sosgroups)>0
xtemp = x;
for i = 1:length(prelaxed.sosgroups)
xi = x(prelaxed.sosgroups{1});
[j,loc] = max(xi);
xtemp(prelaxed.sosgroups{i}) = 0;
xtemp(prelaxed.sosgroups{i}(loc)) = 1;
end
xtemp = setnonlinearvariables(p,xtemp);
upperhere = computecost(p.f,p.corig,p.Q,xtemp,p);
if upperhere < upper & checkfeasiblefast(p,xtemp,p.options.bnb.feastol)
if all(xtemp(p.binary_variables) == fix(xtemp(p.binary_variables))) && all(xtemp(p.integer_variables) == fix(xtemp(p.integer_variables)))
x_min = xtemp;
upper =upperhere;
end
end
end
function x = fix_semivar(p,x);
for i = 1:length(p.semicont_variables)
j = p.semicont_variables(i);
if x(j)>= p.semibounds.lb(i) & x(j)<= p.semibounds.ub(i)
% OK
elseif x(j)==0
% OK
else
s = [abs(x(j)-0); abs(x(j)-p.semibounds.lb(i));abs(x(j)-p.semibounds.ub(i))];
[dummy,index] = min(s);
switch index
case 1
x(j) = 0;
case 2
x(j) = p.semibounds.lb(i);
case 3
x(j) = p.semibounds.lb(i);
end
end
end
function xtemp = fix_atmost(p,xtemp,x);
would = zeros(1,length(x));
for i = 1:length(p.atmost.groups)
k = p.atmost.groups{i};
if nnz(xtemp(k))> p.atmost.bounds(i);
n_should_be_zero = length(p.atmost.groups{i}) - p.atmost.bounds(i);
[y,loc] = sort(abs(x(k)));
xtemp(k(loc(1:n_should_be_zero))) = 0;
end
end