Chapter 7 M-File
Script Files
| ShowLSFit | Fits a line to the square root function. |
| ShowLSq | Sensitivity of LS solutions. |
| ShowSparseLS | Examines "\" LS solving with sparse arrays. |
| ShowQR | Illustrates QRrot. |
| ShowBVP | Solves a two-point boundary value problem. |
| CholBench | Benchmarks various Cholesky implementations. |
| CholErr | Sensitivity of symmetric positive definite systems. |
| ShowCholBlock | Explores block size selection in CholBlock. |
Function Files
| Rotate | Computes a rotation to zero bottom of 2-vector. |
| QRrot | QR factorization via rotations. |
| LSq | Least squares solution via QR factorization. |
| CholTrid | Cholesky factorization (tridiagonal version). |
| CholTridSol | Solves a factored tridiagonal system. |
| CholScalar | Cholesky factorization (scalar version). |
| CholDot | Cholesky factorization (dot product version). |
| CholSax | Cholesky factorization (saxpy version). |
| CholGax | Cholesky factorization (gaxpy version). |
| CholRecur | Cholesky factorization (recursive version). |
| CholBlock | Cholesky factorization (block version). |
| MakeScalar | Makes a block matrix a scalar matrix. |
% Script File: ShowLSFit
% Displays two LS fits to the function f(x) = sqrt(x) on [.25,1].
close all
z = linspace(.25,1);
fz = sqrt(z);
for m = [2 100 ]
x = linspace(.25,1,m)';
A = [ones(m,1) x];
b = sqrt(x);
xLS = A\b;
alpha = xLS(1);
beta = xLS(2);
figure
plot(z,fz,z,alpha+beta*z,'--')
title(sprintf('m = %2.0f, alpha = %10.6f, beta = %10.6f',m,alpha,beta))
end
% Script File: Show LSq
% Illustrates LSq on problems with user-specified
% dimension and condition.
m = input('Enter m: ');
n = input('Enter n: ');
logcond = input('Enter the log of the desired condition number: ');
condA = 10^logcond;
[Q1,R1] = qr(randn(m,m));
[Q2,R2] = qr(randn(n,n));
A = Q1(:,1:n)*diag(linspace(1,1/condA,n))*Q2;
clc
disp(sprintf('m = %2.0f, n = %2.0f, cond(A) = %5.3e',m,n,condA))
b = A*ones(n,1);
[x,res] = LSq(A,b);
disp(' ')
disp('Nonzero residual problem.')
disp(' ')
disp(' Exact Solution Computed Solution')
disp('-----------------------------------------')
for i=1:n
disp(sprintf(' %20.16f %20.16f',1,x(i)))
end
b = b+Q1(:,m);
[x,res] = LSq(A,b);
disp(' ')
disp(' ')
disp(' ')
disp('Zero residual problem.')
disp(' ')
disp(' Exact Solution Computed Solution')
disp('-----------------------------------------')
for i=1:n
disp(sprintf(' %20.16f %20.16f',1,x(i)))
end
% Script File: ShowSparseLS
% Illustrate sparse backslash solving for LS problems
clc
n = 50;
disp(' m n full A flops sparse A flops')
disp('----------------------------------------')
for m = 100:100:1000
A = tril(triu(rand(m,m),-5),5);
p = m/n;
A = A(:,1:p:m);
A_sparse = sparse(A);
b = rand(m,1);
% Solve an m-by-n LS problem where the A matrix has about
% 10 nonzeros per column. In column j these nonzero entries
% are more or less A(j*m/n+k,j), k=-5:5.
flops(0)
x = A\b;
f1 = flops;
flops(0)
x = A_sparse\b;
f2 = flops;
disp(sprintf('%4d %4d %10d %10d ',m,n,f1,f2))
end
% Script File: ShowQR
% Illustrates how the QR factorization is found via Givens Rotations.
m = 5;
n = 3;
disp(' ')
disp('Show upper triangularization of ')
A = rand(m,n);
for j=1:n
for i=m:-1:j+1
input('Strike Any Key to Continue');
clc
%Zero A(i,j)
Before = A
[c,s] = Rotate(A(i-1,j),A(i,j));
A(i-1:i,j:n) = [c s; -s c] *A(i-1:i,j:n);
disp(sprintf('Zero A(%g,%g)',i,j))
After = A
end
end
disp('Upper Triangularization Complete.')
% Script File: ShowBVP
% Illustrates the numerical solution to
%
% -D^2 u + u(x) = 2xsin(x) - 2cos(x) u(0) = u(pi) = 0.
%
% Exact solution = u(x) = x*sin(x).
close all
n = 100;
x = linspace(0,pi,n)';
hx = pi/(n-1);
d = 2*ones(n-2,1) + hx^2;
e = -ones(n-2,1);
[g,h] = CholTrid(d,e);
b = hx^2*( 2*x(2:n-1).*sin(x(2:n-1)) - 2*cos(x(2:n-1)));
umid = CholTridSol(g,h,b);
u = [0;umid;0];
plot(x,u,x,x.*sin(x))
err = norm(u - x.*sin(x),'inf');
title('Solution to -D^2 u + u = 2xsin(x) - 2cos(x), u(0)=u(pi)=0')
xlabel(sprintf(' n = %3.0f norm(u - xsin(x),''inf'') = %10.6f',n,err))
% Script File: CholBench
% Benchmarks five different Cholesky implemntations.
clc
n = input('Enter n: ');
X = rand(2*n,n);
A = X'*X;
disp(' ');
disp(sprintf('n = %2.0f',n))
disp(' ');
disp('Algorithm Relative Time Flops')
disp('-----------------------------------')
flops(0); tic; G = CholScalar(A); t1 = toc; f = flops;
disp(sprintf('CholScalar %6.3f %5.0f',t1/t1,f));
flops(0); tic; G = CholDot(A); t2 = toc; f = flops;
disp(sprintf('CholDot %6.3f %5.0f',t2/t1,f));
flops(0); tic; G = CholSax(A); t3 = toc; f = flops;
disp(sprintf('CholSax %6.3f %5.0f',t3/t1,f));
flops(0); tic; G = CholGax(A); t4 = toc; f = flops;
disp(sprintf('CholGax %6.3f %5.0f',t4/t1,f));
flops(0); tic; G = CholRecur(A); t5 = toc; f = flops;
disp(sprintf('CholRecur %6.3f %5.0f',t5/t1,f));
disp(' ')
disp('Relative time = Time/CholScalar Time')
% Script File: CholErr
% Error when solving a Hilbert Matrix System.
clc
disp(' n cond(A) relerr ')
disp('----------------------------------')
for n = 2:12
A = hilb(n);
b = randn(n,1);
G = CholScalar(A);
y = LTriSol(G,b);
x = UTriSol(G',y);
condA = cond(A);
xTrue = invhilb(n)*b;
relerr = norm(x-xTrue)/norm(xTrue);
disp(sprintf(' %2.0f %10.3e %10.3e ',n,condA,relerr))
end
% Script File: ShowCholBlock
% Effect of block size on performance of block Cholesky.
n = 192;
A = randn(n,n);
A = A'*A;
G0 = chol(A)';
clc
disp(sprintf('n = %2.0f',n))
disp(' ')
disp(' Block Size Time / Unblocked Time ')
disp('---------------------------------------')
k =0;
for p=[ 8 12 16 24 32 48 96]
tic;
G = CholBlock(A,p);
k=k+1;
t(k) = toc;
disp(sprintf(' %2.0f %6.3f ',p,t(k)/t(1)))
end
function [c,s] = Rotate(x1,x2)
% [c,s] = Rotate(x1,x2)
% x1 and x2 are real scalars and c and s is a cosine-sine pair so
% -s*x1 + c*x2 = 0.
if x2==0
c = 1;
s = 0;
else
if abs(x2)>=abs(x1)
cotangent = x1/x2;
s = 1/sqrt(1+cotangent^2);
c = s*cotangent;
else
tangent = x2/x1;
c = 1/sqrt(1+tangent^2);
s = c*tangent;
end
end
function [Q,R] = QRRot(A)
% [Q,R] = QRRot(A)
% The QR factorization of an m-by-n matrix A. (m>=n).
% Q is m-by-m orthogonal and R is m-by-n upper triangular.
[m,n] = size(A);
Q = eye(m,m);
for j=1:n
for i=m:-1:j+1
%Zero A(i,j)
[c,s] = Rotate(A(i-1,j),A(i,j));
A(i-1:i,j:n) = [c s; -s c]*A(i-1:i,j:n);
Q(:,i-1:i) = Q(:,i-1:i)*[c s; -s c]';
end
end
R = triu(A);
function [xLS,res] = LSq(A,b)
% [xLS,res] = LSq(A,b)
% Solution to the LS problem min norm(Ax-b) where A is a full
% rank m-by-n matrix with m>=n and b is a column m-vector.
% xLS is the n-by-1 vector that minimizes the norm(Ax-b) and
% res = norm(A*xLS-b).
[m,n] = size(A);
for j=1:n
for i=m:-1:j+1
%Zero A(i,j)
[c,s] = Rotate(A(i-1,j),A(i,j));
A(i-1:i,j:n) = [c s; -s c]*A(i-1:i,j:n);
b(i-1:i) = [c s; -s c]*b(i-1:i);
end
end
xLS = UTriSol(A(1:n,1:n),b(1:n));
if m==n
res = 0;
else
res = norm(b(n+1:m));
end
function [g,h] = CholTrid(d,e) % G = CholTrid(d,e) % Cholesky factorization of a symmetric, tridiagonal positive definite matrix A. % d and e are column n-vectors with the property that % A = diag(d) + diag(e(2:n),-1) + diag(e(2:n),1) % % g and h are column n-vectors with the property that the lower bidiagonal % G = diag(g) + diag(h(2:n),-1) satisfies A = GG^T. n = length(d); g = zeros(n,1); h = zeros(n,1); g(1) = sqrt(d(1)); for i=2:n h(i) = e(i)/g(i-1); g(i) = sqrt(d(i) - h(i)^2); end
function x = CholTridSol(g,h,b) % x = CholTridSol(g,h,b) % Solves the linear system G*G'x = b where b is a column n-vector and % G is a nonsingular lower bidiagonal matrix. g and h are column n-vectors % with G = diag(g) + diag(h(2:n),-1). n = length(g); y = zeros(n,1); % Solve Gy = b y(1) = b(1)/g(1); for k=2:n y(k) = (b(k) - h(k)*y(k-1))/g(k); end % Solve G'x = y x = zeros(n,1); x(n) = y(n)/g(n); for k=n-1:-1:1 x(k) = (y(k) - h(k+1)*x(k+1))/g(k); end
function G = CholScalar(A)
% G = CholScalar(A)
% Cholesky factorization of a symmetric and positive definite matrix A.
% G is lower triangular so A = G*G'.
[n,n] = size(A);
G = zeros(n,n);
for i=1:n
% Compute G(i,1:i)
for j=1:i
s = A(j,i);
for k=1:j-1
s = s - G(j,k)*G(i,k);
end
if j < i
G(i,j) = s/G(j,j);
else
G(i,i) = sqrt(s);
end
end
end
function G = CholDot(A)
% G = CholDot(A)
% Cholesky factorization of a symmetric and positive definite matrix A.
% G is lower triangular so A = G*G'.
[n,n] = size(A);
G = zeros(n,n);
for i=1:n
% Compute G(i,1:i)
for j=1:i
if j==1
s = A(j,i);
else
s = A(j,i) - G(j,1:j-1)*G(i,1:j-1)';
end
if j < i
G(i,j) = s/G(j,j);
else
G(i,i) = sqrt(s);
end
end
end
function G = CholSax(A)
% G = CholSax(A)
% Cholesky factorization of a symmetric and positive definite matrix A.
% G is lower triangular so A = G*G'.
[n,n] = size(A);
G = zeros(n,n);
s = zeros(n,1);
for j=1:n
s(j:n) = A(j:n,j);
for k=1:j-1
s(j:n) = s(j:n) - G(j:n,k)*G(j,k);
end
G(j:n,j) = s(j:n)/sqrt(s(j));
end
function G = CholGax(A)
% G = CholGax(A)
% Cholesky factorization of a symmetric and positive definite matrix A.
% G is lower triangular so A = G*G'.
[n,n] = size(A);
G = zeros(n,n);
s = zeros(n,1);
for j=1:n
if j==1
s(j:n) = A(j:n,j);
else
s(j:n) = A(j:n,j) - G(j:n,1:j-1)*G(j,1:j-1)';
end
G(j:n,j) = s(j:n)/sqrt(s(j));
end
function G = CholRecur(A) % G = CholRecur(A) % Cholesky factorization of a symmetric and positive definite matrix A. % G is lower triangular so A = G*G'. [n,n] = size(A); G = zeros(n,n); if n==1 G = sqrt(A); else G(1:n-1,1:n-1) = CholRecur(A(1:n-1,1:n-1)); G(n,1:n-1) = LTriSol(G(1:n-1,1:n-1),A(1:n-1,n))'; G(n,n) = sqrt(A(n,n) - G(n,1:n-1)*G(n,1:n-1)'); end
function G = CholBlock(A,p)
% G = CholBlock(A,p)
% Cholesky factorization of a symmetric and positive definite n-by-n matrix A.
% G is lower triangular so A = G*G'. p is the block size and must divide n.
% Represent A and G as m-by-m block matrices where m = n/p.
[n,n] = size(A);
m = n/p;
A = MakeBlock(A,p);
G = cell(m,m);
for i=1:m
for j=1:i
S = A{i,j};
for k=1:j-1
S = S - G{i,k}*G{j,k}';
end
if j < i
G{i,j} = (G{j,j}\S')';
else
G{i,i} = CholScalar(S);
end
end
end
% Convert G to a scalar matrix.
G = MakeScalar(G);
function A = MakeScalar(A_block)
% A = MakeScalar(A_block)
% Represents the m-by-m block matrix A_block as an n-by-n matrix of scalrs with
% where each block is p-by-p and n=mp.
[m,m] = size(A_block);
[p,p] = size(A_block{1,1});
for i=1:m
for j=1:m
if ~isempty(A_block{i,j})
A(1+(i-1)*p:i*p,1+(j-1)*p:j*p) = A_block{i,j};
end
end
end