Some fun uses of the QR decomposition
Contents
Computing the QR decomposition
Here's the matrix we played with in class, together with it's QR decomposition.
A = [-1,3;2,6;2,3]; [Q,R] = qr(A)
Q =
-0.3333 -0.8666 0.3714
0.6667 -0.4952 -0.5571
0.6667 0.0619 0.7428
R =
3.0000 5.0000
0 -5.3852
0 0
Note that the first column of Q and the first row of R agree with our computations. qr returns the full QR decomposition. You can get get the reduced QR decomposition as follows.
[Q1,R1] = qr(A,0)
Q1 =
-0.3333 -0.8666
0.6667 -0.4952
0.6667 0.0619
R1 =
3.0000 5.0000
0 -5.3852
Cleve Moler's qrsteps function lets us see the evolution of the matrix A.
qrsteps(A);
A =
-1 3
2 6
2 3
A =
3 5
0 5
0 2
A =
3.0000 5.0000
0 -5.3852
0 0
We can also automate the procedure ourselves.
a1 = A(:,1); v = zeros(length(a1),1); v(1) = norm(a1); v = v-a1; Q1 = eye(length(a1)) - 2*v*v'/(v'*v) Q1*A
Q1 =
-0.3333 0.6667 0.6667
0.6667 0.6667 -0.3333
0.6667 -0.3333 0.6667
ans =
3.0000 5.0000
0.0000 5.0000
0.0000 2.0000
Computing eigenvalues
It turns out that the QR decomposition is the basis of a very important technique for computing eigenvalues. Here, for example, is a matrix together with some of its eigenvalues.
rand('seed',1);
A = round(10*rand(5)-5);
eig(A)'
ans = Columns 1 through 4 1.1874 0.6528 -0.5414 -5.1494 - 1.4426i Column 5 -5.1494 + 1.4426i
And here's an iterative process using the QR decomposition.
B = A; for i = 1:100 [Q,R] = qr(B); B = R*Q; end; B
B =
-4.3415 4.1922 1.6496 -0.4477 0.2405
-0.6521 -5.9573 3.8484 -3.7543 -3.0515
0.0000 0.0000 1.1874 -2.1253 1.5801
0.0000 0.0000 0.0000 0.6528 4.9318
-0.0000 -0.0000 -0.0000 -0.0000 -0.5414
Note how the real eigenvalues of A lie on the diagonal of B. The complex eigenvalues are the eigenvalues of the obvious block.
eig(B(1:2,1:2))'
ans = -5.1494 - 1.4426i -5.1494 + 1.4426i
Our next step in this class is to try to figure out why this works. The first thing we need to come to grips with is the fact that it doesn't always work!
rand('seed',2); A = round(10*rand(5)-5); B = A; for i = 1:1000 [Q,R] = qr(B); B = R*Q; end; eig(A)' B
ans =
Columns 1 through 4
4.4338 -3.1369 - 3.1162i -3.1369 + 3.1162i -4.5800 - 0.6594i
Column 5
-4.5800 + 0.6594i
B =
-4.7444 -5.5839 1.1236 3.8530 5.7388
0.0827 -4.4156 -3.2431 -6.4272 1.9030
-0.0000 0.0000 4.2094 1.7134 1.5066
-0.0000 0.0000 0.6950 -4.4060 4.9983
-0.0000 0.0000 0.4548 -2.3675 -1.6434
There are however situations where it works exceedingly well.
rand('seed',2); A = round(10*rand(5)-5); A = A*A'; % Ensure that input is symmetric. B = A; for i = 1:100 [Q,R] = qr(B); B = R*Q; end; eig(A)' B
ans =
1.4680 6.8778 29.2699 101.1661 115.2182
B =
115.2182 0.0000 0.0000 0.0000 -0.0000
0.0000 101.1661 -0.0000 -0.0000 -0.0000
-0.0000 0.0000 29.2699 0.0000 0.0000
0.0000 -0.0000 -0.0000 6.8778 0.0000
-0.0000 0.0000 0.0000 -0.0000 1.4680
There are also techniques to accelerate the convergence.
rand('seed',1);
A = round(10*rand(5)-5);
eig(A)'
ans = Columns 1 through 4 1.1874 0.6528 -0.5414 -5.1494 - 1.4426i Column 5 -5.1494 + 1.4426i
B = A; n = length(B); for i = 1:10 [Q,R] = qr(B); B = R*Q; end; B
B =
-3.3171 3.0790 3.0166 -2.0590 -0.4402
-1.7674 -6.9796 2.9117 -3.9308 -1.9386
0.0013 0.0058 1.1869 -1.6333 2.0805
0.0000 0.0000 0.0003 1.8194 4.2902
-0.0000 -0.0000 -0.0000 -0.6430 -1.7096
B = A; n = length(B); for i = 1:10 mu = B(n,n); [Q,R] = qr(B - eye(n)); B = R*Q + eye(n); end; B
B =
-4.1354 -4.0850 -1.1381 -1.5944 0.3535
0.7615 -6.1608 1.3881 3.8827 -4.4980
-0.0015 0.0105 -0.5440 2.9729 3.2846
0.0000 -0.0000 -0.0000 0.6513 -3.4234
0.0000 -0.0000 -0.0000 0.0002 1.1889