232 lines
8.0 KiB
Mathematica
232 lines
8.0 KiB
Mathematica
|
|
%%*******************************************************************
|
||
|
|
%% HKMpred: Compute (dX,dy,dZ) for the H..K..M direction.
|
||
|
|
%%
|
||
|
|
%% SDPT3: version 3.0
|
||
|
|
%% Copyright (c) 1997 by
|
||
|
|
%% K.C. Toh, M.J. Todd, R.H. Tutuncu
|
||
|
|
%% Last modified: 2 Feb 01
|
||
|
|
%%*******************************************************************
|
||
|
|
|
||
|
|
function [dX,dy,dZ,schur,L,UU,VV,E,SMWmat,hRd] = ...
|
||
|
|
HKMpred(blk,At,par,rp,Rd,sigmu,X,Z,invZchol);
|
||
|
|
|
||
|
|
global matlabversion ispc_hp_ibm
|
||
|
|
global spdensity iter solve_ok existMA47symb existspcholsymb
|
||
|
|
global nnzmat nnzmatold matfct_options matfct_options_old use_SCM
|
||
|
|
global Lsymb cachesize
|
||
|
|
global Zinv gamz dd
|
||
|
|
%%
|
||
|
|
%% compute schur matrix
|
||
|
|
%%
|
||
|
|
m = length(rp);
|
||
|
|
schur = sparse(m,m);
|
||
|
|
UU = []; VV = []; E = []; SMWmat = []; Afree = [];
|
||
|
|
existsdpblk = 0; exist_free_vars = 0;
|
||
|
|
dX = cell(size(blk,1),1); dy = []; dZ = cell(size(blk,1),1);
|
||
|
|
Zinv = cell(size(blk,1),1);
|
||
|
|
%%
|
||
|
|
for p = 1:size(blk,1)
|
||
|
|
pblk = blk(p,:);
|
||
|
|
n = sum(pblk{2});
|
||
|
|
numblk = length(pblk{2});
|
||
|
|
if strcmp(pblk{1},'l')
|
||
|
|
Zinv{p} = 1./Z{p};
|
||
|
|
dd{p} = X{p}./Z{p};
|
||
|
|
[schur,UU,VV] = schurmat_lblkold(blk,At,schur,UU,VV,p,dd);
|
||
|
|
elseif strcmp(pblk{1},'q');
|
||
|
|
gaptmp = qops(pblk,X{p},Z{p},1);
|
||
|
|
gamz2 = qops(pblk,Z{p},Z{p},2);
|
||
|
|
gamz{p} = sqrt(gamz2);
|
||
|
|
Zinv{p} = qops(pblk,-1./gamz2,Z{p},4);
|
||
|
|
dd{p} = qops(pblk,gaptmp./gamz2,ones(n,1),4);
|
||
|
|
[schur,UU,VV] = schurmat_qblkold(blk,At,schur,UU,VV,p,dd,Zinv,X);
|
||
|
|
elseif strcmp(pblk{1},'s')
|
||
|
|
existsdpblk = 1;
|
||
|
|
if (numblk == 1)
|
||
|
|
Zinv{p} = Prod2(pblk,full(invZchol{p}),invZchol{p}',1);
|
||
|
|
else
|
||
|
|
Zinv{p} = Prod2(pblk,invZchol{p},invZchol{p}',1);
|
||
|
|
end
|
||
|
|
schur = schurmat_sblk(blk,At,par,schur,p,X,Zinv);
|
||
|
|
elseif strcmp(pblk{1},'u')
|
||
|
|
exist_free_vars = 1;
|
||
|
|
Afree = [Afree At{p}'];
|
||
|
|
end
|
||
|
|
end
|
||
|
|
diagschur = diag(schur);
|
||
|
|
if (existsdpblk);
|
||
|
|
pertdiag = 1e-16*sqrt(m)*norm(diagschur);
|
||
|
|
for k=1:m; schur(k,k) = abs(schur(k,k)) + pertdiag; end;
|
||
|
|
else
|
||
|
|
pertdiag = 1e-16*max(diagschur);
|
||
|
|
for k=1:m; schur(k,k) = abs(schur(k,k)) + pertdiag; end;
|
||
|
|
end
|
||
|
|
%%
|
||
|
|
[rhs,EinvRc,hRd] = HKMrhsfun(blk,At,par,X,Z,rp,Rd,sigmu);
|
||
|
|
%%
|
||
|
|
%% determine matrix factorization to use
|
||
|
|
%%
|
||
|
|
if (exist_free_vars)
|
||
|
|
tmp = [zeros(size(Afree,2),1); ones(size(UU,2),1)];
|
||
|
|
UU = [Afree UU]; VV = [Afree VV];
|
||
|
|
E = spdiags(tmp,0,length(tmp),length(tmp));
|
||
|
|
else
|
||
|
|
E = speye(size(UU,2));
|
||
|
|
end
|
||
|
|
rhs = [rhs; zeros(m+size(UU,2)-length(rhs),1)];
|
||
|
|
if (iter <= 2)
|
||
|
|
if (size(UU,2) < min(500,0.1*m));
|
||
|
|
use_SCM = 1;
|
||
|
|
else
|
||
|
|
use_SCM = 0;
|
||
|
|
if (norm(UU-VV,'fro') < 1e-13) & (existMA47symb) & (size(UU,2) < 0.25*m)
|
||
|
|
matfct_options = 'MA47';
|
||
|
|
else
|
||
|
|
matfct_options = 'splu';
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
%%
|
||
|
|
%% Cholesky factorization
|
||
|
|
%%
|
||
|
|
if (iter == 1); existMA47symb = 1; nnzmatold = 0; end
|
||
|
|
nnzmat = mexnnz(schur);
|
||
|
|
nnzmatdiff = (nnzmat ~= nnzmatold);
|
||
|
|
if use_SCM
|
||
|
|
if (nnzmat > spdensity*m^2);
|
||
|
|
if issparse(schur); schur = full(schur); end;
|
||
|
|
matfct_options = 'chol';
|
||
|
|
else
|
||
|
|
if ~issparse(schur), schur = sparse(schur); end;
|
||
|
|
matfct_options = 'spchol';
|
||
|
|
end
|
||
|
|
if strcmp(matfct_options,'chol')
|
||
|
|
L = [];
|
||
|
|
if (matlabversion >= 6)
|
||
|
|
if (ispc_hp_ibm), [schur,indef] = chol(schur);
|
||
|
|
else, indef = mexchol_(schur);
|
||
|
|
end
|
||
|
|
else
|
||
|
|
[schur,indef] = chol(schur);
|
||
|
|
end
|
||
|
|
if indef;
|
||
|
|
solve_ok = -2;
|
||
|
|
fprintf(' chol: Schur complement matrix not positive definite.\n');
|
||
|
|
else
|
||
|
|
[xx,solve_ok,SMWmat] = schursysolve(schur,schur,UU,VV,E,rhs,matfct_options);
|
||
|
|
end
|
||
|
|
elseif strcmp(matfct_options,'spchol')
|
||
|
|
if (nnzmatdiff | ~strcmp(matfct_options,matfct_options_old))
|
||
|
|
[Lsymb,flag] = symbcholfun(schur,cachesize);
|
||
|
|
if (flag)
|
||
|
|
solve_ok = -2;
|
||
|
|
existspcholsymb = 0;
|
||
|
|
fprintf(' spchol: symbolic factorization fails.\n');
|
||
|
|
else
|
||
|
|
existspcholsymb = 1;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if (existspcholsymb)
|
||
|
|
L = sparcholfun(Lsymb,schur);
|
||
|
|
L.d(find(L.skip)) = inf;
|
||
|
|
if ~isempty(UU) & any(L.skip);
|
||
|
|
solve_ok = -3;
|
||
|
|
fprintf(' spchol: fail to solve Schur complement equation\n');
|
||
|
|
fprintf(' via the Sherman-Morrison update.\n');
|
||
|
|
else
|
||
|
|
[xx,solve_ok,SMWmat] = schursysolve(schur,L,UU,VV,E,rhs,matfct_options);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if (solve_ok <= 0)
|
||
|
|
if ~(existsdpblk & size(UU,2)==0)
|
||
|
|
use_SCM = 0;
|
||
|
|
matfct_options = 'splu';
|
||
|
|
if (size(UU,2) > 0)
|
||
|
|
fprintf(' switch to augmented system.\n');
|
||
|
|
else
|
||
|
|
fprintf(' switch to LU factorization.\n');
|
||
|
|
end
|
||
|
|
else
|
||
|
|
return;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
%%
|
||
|
|
%% LU or symmetric indefinite factorization
|
||
|
|
%%
|
||
|
|
if ~use_SCM
|
||
|
|
raugmat = [schur UU; VV' -E];
|
||
|
|
if (nnzmat > spdensity*m^2);
|
||
|
|
matfct_options = 'lu';
|
||
|
|
end
|
||
|
|
%%
|
||
|
|
if strcmp(matfct_options,'lu')
|
||
|
|
if issparse(raugmat); raugmat = full(raugmat); end
|
||
|
|
[L.l,L.u,L.p] = lu(raugmat);
|
||
|
|
xx = L.u \ (L.l \ (L.p*rhs));
|
||
|
|
end
|
||
|
|
if strcmp(matfct_options,'MA47')
|
||
|
|
if ~issparse(raugmat); raugmat = sparse(raugmat); end
|
||
|
|
if (nnzmatdiff | ~strcmp(matfct_options,matfct_options_old))
|
||
|
|
nnztmp = (nnz(raugmat) + nnz(diag(raugmat)))/2;
|
||
|
|
[keep,Jcn,flag,info] = mexMA47syb(nnztmp,raugmat);
|
||
|
|
if (flag)
|
||
|
|
existMA47symb = 0;
|
||
|
|
fprintf(' MA47: symbolic factorization fails, switch to LU.\n');
|
||
|
|
matfct_options = 'splu';
|
||
|
|
else
|
||
|
|
existMA47symb = 1;
|
||
|
|
Lsymb.keep = keep; Lsymb.Jcn = Jcn;
|
||
|
|
Lsymb.La = 2*info(1); Lsymb.Liw = 2*info(2);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if (existMA47symb)
|
||
|
|
[L.a,L.iw,flag] = mexMA47fct(raugmat, ...
|
||
|
|
Lsymb.keep,Lsymb.Jcn,Lsymb.La,Lsymb.Liw,[1e-10,0]);
|
||
|
|
xx = mexMA47slv(length(rhs),L.a,L.iw,rhs);
|
||
|
|
if (flag == 0)
|
||
|
|
solve_ok = 1;
|
||
|
|
else
|
||
|
|
existMA47symb = 0;
|
||
|
|
fprintf(' MA47: solver fails, switch to LU. \n');
|
||
|
|
matfct_options = 'splu';
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if strcmp(matfct_options,'splu')
|
||
|
|
if ~issparse(raugmat); raugmat = sparse(raugmat); end
|
||
|
|
if (nnzmatdiff | ~strcmp(matfct_options,matfct_options_old))
|
||
|
|
Lsymb.perm = symmmd(raugmat);
|
||
|
|
end
|
||
|
|
L.perm = Lsymb.perm;
|
||
|
|
if (matlabversion >= 6.5)
|
||
|
|
[L.l,L.u,L.p,L.q] = lu(raugmat(L.perm,L.perm));
|
||
|
|
elseif (exist('umfpack2')==3)
|
||
|
|
[L.l,L.u,pp,qq] = umfpack2(raugmat(L.perm,L.perm));
|
||
|
|
len = length(pp);
|
||
|
|
L.p = spconvert([(1:len)' pp' ones(len,1)]);
|
||
|
|
L.q = spconvert([qq' (1:len)' ones(len,1)]);
|
||
|
|
else
|
||
|
|
[L.l,L.u,L.p] = lu(raugmat(L.perm,L.perm));
|
||
|
|
L.q = speye(length(raugmat));
|
||
|
|
end
|
||
|
|
xx(L.perm,1) = L.q*( L.u \ (L.l \ (L.p*rhs(L.perm))));
|
||
|
|
if any(xx == inf)
|
||
|
|
solve_ok = 0;
|
||
|
|
fprintf(' LU: fails to solve the augmented system.\n');
|
||
|
|
else
|
||
|
|
solve_ok = 1;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
nnzmatold = nnzmat; matfct_options_old = matfct_options;
|
||
|
|
%%
|
||
|
|
%% compute (dX,dZ)
|
||
|
|
%%
|
||
|
|
if (any(isnan(xx)) | any(isinf(xx)))
|
||
|
|
error(' solution of linear system contains NaN or inf');
|
||
|
|
end
|
||
|
|
[dX,dy,dZ] = HKMdirfun(blk,At,par,Rd,EinvRc,X,xx);
|
||
|
|
%%*******************************************************************
|