128 lines
4.3 KiB
Mathematica
128 lines
4.3 KiB
Mathematica
|
|
%%*****************************************************************
|
||
|
|
%% detect_lblk: detect diagonal blocks in the SDP data.
|
||
|
|
%%
|
||
|
|
%% [blk,At,C,diagblkinfo,blockchange,parbarrier,X,Z] = ...
|
||
|
|
%% detect_lblk(blk,At,C,b,parbarrier,X,Z);
|
||
|
|
%%*****************************************************************
|
||
|
|
%% SDPT3: version 4.0
|
||
|
|
%% Copyright (c) 1997 by
|
||
|
|
%% Kim-Chuan Toh, Michael J. Todd, Reha H. Tutuncu
|
||
|
|
%% Last Modified: 16 Sep 2004
|
||
|
|
%%*****************************************************************
|
||
|
|
|
||
|
|
function [blk,At,C,diagblkinfo,blockchange,parbarrier,X,Z] = ...
|
||
|
|
detect_lblk(blk,At,C,b,parbarrier,X,Z,printlevel);
|
||
|
|
|
||
|
|
if (nargin < 8); printlevel = 1; end
|
||
|
|
%%
|
||
|
|
%% Acum = abs(C) + sum_{k=1}^m abs(Ak)
|
||
|
|
%% but with diagonal elements removed.
|
||
|
|
%%
|
||
|
|
blkold = blk;
|
||
|
|
m = length(b);
|
||
|
|
ee = ones(m,1);
|
||
|
|
numdiagelt = 0;
|
||
|
|
numblknew = 0;
|
||
|
|
blockchange = zeros(size(blk,1),1);
|
||
|
|
Acum = cell(size(blk,1),1);
|
||
|
|
diagblkinfo = cell(size(blk,1),3);
|
||
|
|
for p=1:size(blk,1)
|
||
|
|
pblk = blk(p,:);
|
||
|
|
n = sum(pblk{2});
|
||
|
|
if strcmp(pblk{1},'s') & (length(pblk{2}) == 1) & (size(At{p,1},2)==m)
|
||
|
|
Acumtmp = smat(blk(p,:),abs(At{p})*ee,1) + abs(C{p});
|
||
|
|
Acum{p} = Acumtmp - spdiags(diag(Acumtmp),0,n,n);
|
||
|
|
rownorm = sqrt(sum(Acum{p}.*Acum{p}))';
|
||
|
|
idxdiag = find(rownorm < 1e-15);
|
||
|
|
if ~isempty(idxdiag)
|
||
|
|
blockchange(p) = 1;
|
||
|
|
numdiagelt = numdiagelt + length(idxdiag);
|
||
|
|
idxnondiag = setdiff([1:n]',idxdiag);
|
||
|
|
diagblkinfo{p,2} = idxdiag;
|
||
|
|
diagblkinfo{p,3} = idxnondiag;
|
||
|
|
if ~isempty(idxnondiag)
|
||
|
|
numblknew = numblknew + 1;
|
||
|
|
diagblkinfo{p,1} = numblknew;
|
||
|
|
end
|
||
|
|
else
|
||
|
|
numblknew = numblknew + 1;
|
||
|
|
diagblkinfo{p,1} = numblknew;
|
||
|
|
end
|
||
|
|
else
|
||
|
|
numblknew = numblknew + 1;
|
||
|
|
diagblkinfo{p,1} = numblknew;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
%%
|
||
|
|
%% extract diagonal sub-blocks in nondiagonal blocks
|
||
|
|
%% into a single linear block
|
||
|
|
%%
|
||
|
|
if any(blockchange)
|
||
|
|
numblk = size(blkold,1);
|
||
|
|
idx_keepblk = [];
|
||
|
|
Atmp = cell(1,m);
|
||
|
|
Adiag = cell(1,m);
|
||
|
|
C(numblk+1,1) = cell(1,1);
|
||
|
|
Cdiag = []; Xdiag = []; Zdiag = [];
|
||
|
|
parbarrierdiag = [];
|
||
|
|
for p = 1:numblk
|
||
|
|
n = sum(blkold{p,2});
|
||
|
|
if (blockchange(p)==1)
|
||
|
|
idxdiag = diagblkinfo{p,2};
|
||
|
|
idxnondiag = diagblkinfo{p,3};
|
||
|
|
if ~isempty(idxdiag);
|
||
|
|
blk{p,2} = length(idxnondiag);
|
||
|
|
len = length(idxdiag);
|
||
|
|
for k = 1:m;
|
||
|
|
Ak = mexsmat(blkold,At,1,p,k);
|
||
|
|
tmp = diag(Ak);
|
||
|
|
Atmp{k} = Ak(idxnondiag,idxnondiag);
|
||
|
|
Adiag{k} = [Adiag{k}; tmp(idxdiag)];
|
||
|
|
end
|
||
|
|
tmp = diag(C{p,1});
|
||
|
|
Cdiag = [Cdiag; tmp(idxdiag)];
|
||
|
|
C{p,1} = C{p,1}(idxnondiag,idxnondiag);
|
||
|
|
At(p) = svec(blk(p,:),Atmp,1);
|
||
|
|
if (nargin >= 7)
|
||
|
|
parbarrierdiag = [parbarrierdiag, parbarrier{p}*ones(1,len)];
|
||
|
|
tmp = diag(X{p,1});
|
||
|
|
Xdiag = [Xdiag; tmp(idxdiag)];
|
||
|
|
tmp = diag(Z{p,1});
|
||
|
|
Zdiag = [Zdiag; tmp(idxdiag)];
|
||
|
|
X{p,1} = X{p,1}(idxnondiag,idxnondiag);
|
||
|
|
Z{p,1} = Z{p,1}(idxnondiag,idxnondiag);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if ~isempty(idxnondiag)
|
||
|
|
idx_keepblk = [idx_keepblk, p];
|
||
|
|
else
|
||
|
|
if (printlevel)
|
||
|
|
fprintf(' %2.0dth semidefinite block is actually diagonal\n',p);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
else
|
||
|
|
idx_keepblk = [idx_keepblk, p];
|
||
|
|
end
|
||
|
|
end
|
||
|
|
blk{numblk+1,1} = 'l';
|
||
|
|
blk{numblk+1,2} = numdiagelt;
|
||
|
|
C{numblk+1,1} = Cdiag;
|
||
|
|
At(numblk+1,1) = svec(blk(numblk+1,:),Adiag,1);
|
||
|
|
idx_keepblk = [idx_keepblk, numblk+1];
|
||
|
|
blk = blk(idx_keepblk,:);
|
||
|
|
C = C(idx_keepblk,:);
|
||
|
|
At = At(idx_keepblk,:);
|
||
|
|
if (nargin >= 7)
|
||
|
|
parbarrier{numblk+1,1} = parbarrierdiag;
|
||
|
|
X{numblk+1,1} = Xdiag;
|
||
|
|
Z{numblk+1,1} = Zdiag;
|
||
|
|
parbarrier = parbarrier(idx_keepblk);
|
||
|
|
X = X(idx_keepblk);
|
||
|
|
Z = Z(idx_keepblk);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
%%******************************************************************
|
||
|
|
|
||
|
|
|
||
|
|
|