MATLAB tests for Cholesky scaling and preconditioning
parent
a6df33b15f
commit
60f29fde15
|
@ -0,0 +1,100 @@
|
|||
|
||||
badscale = 1e-14;
|
||||
|
||||
% Create random Jacobian
|
||||
A = [
|
||||
badscale.*(rand(3)-.5) zeros(3) zeros(3,6)
|
||||
zeros(3) (rand(3)-.5) zeros(3,6)
|
||||
badscale.*(rand(2,6)-.5) zeros(2,6)
|
||||
zeros(2,6) badscale.*(rand(2,6)-.5)
|
||||
eye(6) -eye(6)
|
||||
];
|
||||
b = [
|
||||
repmat(badscale, 3,1)
|
||||
repmat(1, 3,1)
|
||||
repmat(badscale, 2,1)
|
||||
repmat(badscale, 2,1)
|
||||
repmat(1, 6,1)
|
||||
];
|
||||
|
||||
% Solve with MATLAB
|
||||
x_true = A \ b;
|
||||
|
||||
% Form Hessian
|
||||
L = A'*A;
|
||||
l = A'*b;
|
||||
|
||||
% Eliminate badly-conditioned system. Use this custom choleskyNaive function
|
||||
% that does no internal pivoting or scaling to simulate the case where the
|
||||
% bad conditioning occurs between fronts.
|
||||
R = choleskyNaive(L);
|
||||
if isempty(R)
|
||||
fprintf('Cholesky failed on badly-scaled system with a negative pivot\n');
|
||||
else
|
||||
clear opts
|
||||
opts.LT = true;
|
||||
d = linsolve(R', l, opts);
|
||||
|
||||
% Solve badly-conditioned system.
|
||||
clear opts
|
||||
opts.UT = true;
|
||||
x = linsolve(R, d, opts);
|
||||
|
||||
% Compute error
|
||||
fprintf('Solution error with Cholesky on badly-scaled system: %g\n', ...
|
||||
max(abs(x - x_true)));
|
||||
end
|
||||
|
||||
% Form scaled system from Jacobian
|
||||
%Si = full(qr(sparse(A)));
|
||||
%Si = diag(sqrt(diag(L)));
|
||||
S = [
|
||||
eye(6) zeros(6)
|
||||
eye(6) eye(6) ];
|
||||
Ap = A * S;
|
||||
Lp = Ap'*Ap;
|
||||
lp = Ap'*b;
|
||||
|
||||
% Eliminate scaled system
|
||||
Rp = choleskyNaive(Lp);
|
||||
if isempty(Rp)
|
||||
fprintf('Cholesky failed on scaled system with a negative pivot\n');
|
||||
else
|
||||
clear opts
|
||||
opts.LT = true;
|
||||
dp = linsolve(Rp', lp, opts);
|
||||
|
||||
% Solve rescaled system.
|
||||
clear opts
|
||||
opts.UT = true;
|
||||
xp = S * linsolve(Rp, dp, opts);
|
||||
|
||||
% Compute error
|
||||
fprintf('Solution error with Cholesky from rescaled Jacobian: %g\n', ...
|
||||
max(abs(xp - x_true)));
|
||||
end
|
||||
|
||||
|
||||
% Form scaled system from Hessian
|
||||
Lph = S' * (L * S);
|
||||
lph = S' * l;
|
||||
|
||||
% Eliminate scaled system
|
||||
Rph = choleskyNaive(Lph);
|
||||
if isempty(Rph)
|
||||
fprintf('Cholesky failed on scaled system with a negative pivot\n');
|
||||
else
|
||||
clear opts
|
||||
opts.LT = true;
|
||||
dph = linsolve(Rph', lph, opts);
|
||||
|
||||
% Solve rescaled system.
|
||||
clear opts
|
||||
opts.UT = true;
|
||||
xph = S * linsolve(Rph, dph, opts);
|
||||
|
||||
% Compute error
|
||||
fprintf('Solution error with Cholesky from rescaled Hessian: %g\n', ...
|
||||
max(abs(xph - x_true)));
|
||||
end
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
function A = choleskyNaive(A)
|
||||
%ELIMINATEPP Gaussian elimination with partial pivoting. Eliminates a
|
||||
%matrix A (sparse or full) into an upper-triangular factor R.
|
||||
|
||||
% Loop over rows of A
|
||||
q = min(size(A,2), size(A,1));
|
||||
for i = 1:q
|
||||
% Check for valid pivot
|
||||
if A(i,i) <= 0.0
|
||||
A = [];
|
||||
return;
|
||||
end
|
||||
|
||||
% Scale row to be the square-root factor
|
||||
A(i,i) = sqrt(A(i,i));
|
||||
A(i,i+1:end) = A(i,i+1:end) ./ A(i,i);
|
||||
|
||||
% Apply low-rank update to remanining lower-right submatrix
|
||||
A(i+1:end, i+1:end) = A(i+1:end, i+1:end) - ...
|
||||
A(i, i+1:end)' * A(i, i+1:end);
|
||||
|
||||
% Zero-out the column below the current row
|
||||
A(i+1:end, i) = 0;
|
||||
end
|
||||
|
||||
end
|
||||
|
Loading…
Reference in New Issue