Dynamic-Calibration/utils/SDPT3-4.0/Solver/Oldmfiles/schursysolve.m

111 lines
3.4 KiB
Mathematica
Raw Normal View History

2019-12-18 11:25:45 +00:00
%%*********************************************************************
%% schursysolve: solve
%% [H U][x1] = [b1]
%% [V' -E][x2] [b2]
%% via the Schur complement method as follows:
%% SMWmat*x2 = V'*inv(H)*b1 - b2, where SMWmat = V'*inv(H)*U + E,
%% x1 = inv(H)*(b1 - U*x2).
%%
%% Here H is symmetric positive definite
%% and U, V are low-rank, possibly [].
%%
%% [x,solve_ok,SMWmat] = schursysolve(H,L,U,V,E,b,matfct_options,SMWmat)
%%
%% if matfct_options == 'chol'
%% L is the Cholesky factor of H computed by Matlab's rountine
%% Note H = L'*L
%% On entry, H has already been overwritten by L.
%% elseif matfct_options == 'spchol'
%% L contains the sparse LDL' factorization of H computed
%% via the sparse Cholesky routines in Spchol
%% Note H = L*D*L'
%% end
%%
%% SDPT3: version 3.0
%% Copyright (c) 1997 by
%% K.C. Toh, M.J. Todd, R.H. Tutuncu
%% Last modified: 2 Feb 01
%%*********************************************************************
function [x,solve_ok,SMWmat] = schursysolve(H,L,U,V,E,b,matfct_options,SMWmat)
if (nargin <= 7); SMWmat = []; end;
ismtU = isempty(U);
m = length(H); n = size(U,2);
if (length(b) < m+n)
b = [b; zeros(m+n-length(b),1)];
end
%%
if ismtU
solve_ok = 1;
x = linslv(L,b,matfct_options);
else
solve_ok = -1;
if isempty(SMWmat)
n = size(U,2);
HinvU = zeros(size(U));
for i = 1:n
HinvU(:,i) = linslv(L,U(:,i),matfct_options);
end
[SMWmat.l,SMWmat.u,SMWmat.p] = lu(E+V'*HinvU);
end
b1 = b(1:m); b2 = b(m+[1:n]);
btmp = V'*linslv(L,b1,matfct_options) - b2;
x2 = SMWmat.u \ (SMWmat.l \ (SMWmat.p*btmp));
x1 = linslv(L,b1-U*x2,matfct_options);
x = [x1; x2];
%%
%% Iterative refinement. This step is crucial to ensure
%% that computed solution is sufficiently accuraete.
%%
rtol = 1e-4;
if length(b) > 5000;
maxit = 50;
else
maxit = 25;
end
bnorm = max(1,norm(b));
for k = 1:maxit
x0 = x;
if strcmp(matfct_options,'chol');
tmp = L*x1; Hx1 = (tmp'*L)';
elseif strcmp(matfct_options,'spchol');
Hx1 = H*x1;
end
r1 = b1 - (Hx1 + U*x2);
r2 = b2 - (V'*x1 - E*x2);
%%
rrnrm(k) = sqrt(norm(r1)^2 + norm(r2)^2)/bnorm;
if (rrnrm(k) < rtol); solve_ok = 1; break; end;
if (k > 1) & (rrnrm(k)/rrnrm(k-1) > 0.8);
x = x0; break;
end
rtmp = V'*linslv(L,r1,matfct_options) -r2;
d2 = SMWmat.u \ (SMWmat.l \ (SMWmat.p*rtmp));
d1 = linslv(L,r1-U*d2,matfct_options);
x1 = x1 + d1;
x2 = x2 + d2;
x = [x1; x2];
end
end
%%
%%*************************************************************************
%% linslv: Solve a linear system H*x = b
%% where H is symmetric positive definite.
%%
%% L is the Cholesky factor of H.
%%*************************************************************************
function x = linslv(L,b,matfct_options)
if strcmp(matfct_options,'chol')
if issparse(b); b = full(b); end;
tmp = mexbsolve(L,b,2);
x = mexbsolve(L,tmp,1);
elseif strcmp(matfct_options,'spchol')
x = bwblkslvfun(L, fwblkslvfun(L,b) ./ L.d);
end
%%
%%*************************************************************************