129 lines
3.5 KiB
Matlab
Executable File
129 lines
3.5 KiB
Matlab
Executable File
%%*******************************************************************
|
|
%% detect_diag: detect diagonal blocks in the SDP data.
|
|
%%
|
|
%% [blk,At,C,b,iidxdiag] = detect_diag(blk,At,C,b);
|
|
%%
|
|
%% SDPT3: version 3.0
|
|
%% Copyright (c) 1997 by
|
|
%% K.C. Toh, M.J. Todd, R.H. Tutuncu
|
|
%% Last modified: 2 Feb 01
|
|
%%******************************************************************
|
|
|
|
function [blk,At,C,b,iidxdiag] = detect_diag(blk,At,C,b);
|
|
|
|
m = length(b); numblk = size(blk,1);
|
|
idx_keepblk = [];
|
|
%%
|
|
%% convert At{p}(:,k) to A{p,k}
|
|
%%
|
|
if size(At,2) ~=m
|
|
A = cell(size(blk,1),m);
|
|
for p = 1:size(blk,1);
|
|
pblk = blk(p,:);
|
|
if strcmp(pblk{1},'s');
|
|
for k = 1:m
|
|
A{p,k} = mexsmat(blk,At,1,p,k);
|
|
end
|
|
elseif strcmp(pblk{1},'l');
|
|
for k = 1:m
|
|
A{p,k} = At{p}(:,k);
|
|
end
|
|
end
|
|
end
|
|
conversion = 1;
|
|
else
|
|
A = At;
|
|
conversion = 0;
|
|
end
|
|
%%
|
|
%% dectect diagonal sub-block in nondiagonal blocks.
|
|
%%
|
|
blkchanged = 0;
|
|
for p = 1:size(blk,1);
|
|
blktmp = blk{p,2};
|
|
n = sum(blktmp);
|
|
if strcmp(blk{p,1},'s');
|
|
Acum = abs(C{p});
|
|
for k = 1:m
|
|
Acum = Acum + abs(A{p,k});
|
|
end;
|
|
Acum = Acum - spdiags(diag(Acum),0,n,n);
|
|
rownorm = sum(Acum.*Acum);
|
|
idxdiag = find(rownorm < 1e-13);
|
|
idxnondiag = setdiff([1:n],idxdiag);
|
|
iidxdiag{p} = idxdiag;
|
|
if ~isempty(idxdiag);
|
|
if (blkchanged == 0)
|
|
blkchanged = 1;
|
|
diagblk = numblk+1;
|
|
A(diagblk,:) = cell(1,size(A,2));
|
|
C(diagblk,1) = cell(1,1);
|
|
blk{diagblk,1} = 'l';
|
|
blk{diagblk,2} = 0;
|
|
idx_keepblk = [idx_keepblk, diagblk];
|
|
end;
|
|
blk{diagblk,2} = blk{diagblk,2} + length(idxdiag);
|
|
blk{p,2} = length(idxnondiag);
|
|
for k = 1:size(A,2);
|
|
tmp = diag(A{p,k});
|
|
A{diagblk,k} = [A{diagblk,k} ; tmp(idxdiag)];
|
|
A{p,k} = A{p,k}(idxnondiag,idxnondiag);
|
|
end;
|
|
tmp = diag(C{p,1});
|
|
C{diagblk,1} = [C{diagblk,1}; tmp(idxdiag)];
|
|
C{p,1} = C{p,1}(idxnondiag,idxnondiag);
|
|
end;
|
|
if ~isempty(idxnondiag);
|
|
idx_keepblk = [idx_keepblk, p];
|
|
end;
|
|
elseif strcmp(blk{p,1},'l');
|
|
idx_keepblk = [idx_keepblk, p];
|
|
end;
|
|
end;
|
|
if (blkchanged);
|
|
blk = blk(idx_keepblk,:);
|
|
A = A(idx_keepblk,:);
|
|
C = C(idx_keepblk,:);
|
|
end;
|
|
%%
|
|
%% concatenate diagonal blocks.
|
|
%%
|
|
diagblk = []; idx_keepblk = [];
|
|
for p = 1:size(blk,1)
|
|
if strcmp(blk{p,1},'l');
|
|
diagblk = [diagblk, p];
|
|
else;
|
|
idx_keepblk = [idx_keepblk, p];
|
|
end;
|
|
end;
|
|
if ~isempty(diagblk);
|
|
idx1 = diagblk(1);
|
|
idx_keepblk = [idx_keepblk, idx1];
|
|
end;
|
|
if (length(diagblk) >= 2);
|
|
for p = 2:length(diagblk);
|
|
idxp = diagblk(p);
|
|
for k = 1:size(A,2);
|
|
A{idx1,k} = [A{idx1,k}; A{idxp,k}];
|
|
end;
|
|
C{idx1,1} = [C{idx1,1}; C{idxp,1}];
|
|
blk{idx1,2} = blk{idx1,2} + blk{idxp,2};
|
|
end;
|
|
blk = blk(idx_keepblk,:);
|
|
A = A(idx_keepblk,:);
|
|
C = C(idx_keepblk,:);
|
|
end;
|
|
%%
|
|
%%
|
|
%%
|
|
if conversion;
|
|
At = svec(blk,A,ones(size(blk,1),1));
|
|
else
|
|
At = A;
|
|
end
|
|
%%
|
|
%%******************************************************************
|
|
|
|
|
|
|