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