2023-09-07
Definition 1.2 contains a working definition of the condition number but it does not apply to the case of vectors and matrices.
Four things to observe / note:
\(\kappa\left(\mathbf{A}\right)\) is then called the condition number. It has a closed form: \[\kappa\left(\mathbf{A}\right)=||\mathbf{A}^{-1}|| \cdot ||\mathbf{A}||\]
Special structures of matrices can help reduce computational times, but their special structure has to be incorporated into the algorithm.
Let \(\mathbf{L}\) be a unit lower triangular matrix. It seems that \(\mathbf{L}\mathbf{L}^T\) is a good candidate to preserve symmetry.
So an option would be to use \(\mathbf{LDL}^T\) instead, where \(\mathbf{D}\) is a diagonal matrix.
If you have a symmetric positive definite (SPD) matrix, you can use a similar argument as earlier.
Contrast computing times (\(n\) being the order of a square matrix):
For last three: No slope change, but a parallel intercept shift on a log10-log10 plot of computational time vs \(n\)
“Numerically nice”: diagonally dominant, symmetric positive definite
Sparse: diagonal, lower triangular, upper triangular, tridiagonal, banded
“Deadly”: Vandermonde, Hilbert (different from Hilbertian, refer also to Exercise 2.8.1)
rand()
, randn()
norm()
, opnorm()
, normalize()
diag()
FNC.spdiagm()
FNC.cholesky()
Problem: Consider the following system of linear equations: \[\underbrace{\begin{bmatrix}1 & -1 & 0 & \alpha-\beta & \beta \\ 0 & 1 & -1 & 0 & 0 \\ 0 & 0 & 1 & -1 & 0 \\ 0 & 0 &0 &1 & -1 \\ 0 & 0 & 0 & 0 & 1\end{bmatrix}}_{\mathbf{A}}\underbrace{\begin{bmatrix}x_1\\x_2\\x_3\\x_4\\x_5\end{bmatrix}}_{\mathbf{x}}=\underbrace{\begin{bmatrix}\alpha \\0 \\ 0 \\ 0 \\ 1\end{bmatrix}}_{\mathbf{b}}\]
Recall:
using FundamentalsNumericalComputation
AbsAcc = [];
CondNum = [];
α = 0.1;
β = 10 .^ (1:12);
for β in β
A = FNC.diagm(0 => ones(5), 1 => [-1,-1,-1,-1], 3 => [α-β,0], 4 => [β])
x = FNC.backsub(A, [α, 0, 0, 0, 1])
push!(AbsAcc, abs(x[1] - 1.))
push!(CondNum, FNC.cond(A))
end
FNC.pretty_table((β=β,AbsAcc=AbsAcc, CondNum=CondNum),["β" "|x₁-1|" "κ(A)"])
┌───────────────┬─────────────┬────────────┐
│ β │ |x₁-1| │ κ(A) │
├───────────────┼─────────────┼────────────┤
│ 10 │ 4.44089e-16 │ 160.421 │
│ 100 │ 5.77316e-15 │ 14268.9 │
│ 1000 │ 2.27596e-14 │ 1.41542e6 │
│ 10000 │ 3.6382e-13 │ 1.41433e8 │
│ 100000 │ 5.82079e-12 │ 1.41423e10 │
│ 1000000 │ 2.32832e-11 │ 1.41421e12 │
│ 10000000 │ 3.72529e-10 │ 1.41421e14 │
│ 100000000 │ 5.96046e-9 │ 1.41421e16 │
│ 1000000000 │ 2.38419e-8 │ 1.41421e18 │
│ 10000000000 │ 3.8147e-7 │ 1.41421e20 │
│ 100000000000 │ 6.10352e-6 │ 1.41421e22 │
│ 1000000000000 │ 2.44141e-5 │ 1.41421e24 │
└───────────────┴─────────────┴────────────┘
Problem: Let \[\mathbf{A}=\begin{bmatrix}-\epsilon & 1 \\ 1 & -1\end{bmatrix}.\] Without pivoting, an LU factorization (done by hand) is given by \[\mathbf{L}=\begin{bmatrix}1 & 0 \\ -\epsilon^{-1} & 1\end{bmatrix},\ \ \mathbf{U}=\begin{bmatrix}-\epsilon & 1 \\ 0 & \epsilon^{-1}-1\end{bmatrix}.\]
For \(\epsilon = 10^{-2},10^{-4},\ldots,10^{-10}\), make a table with columns for \(\epsilon\), \(\kappa(\mathbf{A})\), \(\kappa(\mathbf{L})\), and \(\kappa(\mathbf{U})\).
using FundamentalsNumericalComputation
CondNumA = []; CondNumL = []; CondNumU = [];
ϵ = 10. .^ (-2:-2:-10);
for ϵ in ϵ
A = [-ϵ 1; 1 -1];
L, U = FNC.lufact(A);
push!(CondNumA, FNC.cond(A));
push!(CondNumL, FNC.cond(L));
push!(CondNumU, FNC.cond(U));
end
FNC.pretty_table((ϵ=ϵ,CondNumA=CondNumA, CondNumL=CondNumL,CondNumU=CondNumU),["ϵ" "κ(A)" "κ(L)" "κ(U)"])
┌─────────┬─────────┬─────────┬────────────┐
│ ϵ │ κ(A) │ κ(L) │ κ(U) │
├─────────┼─────────┼─────────┼────────────┤
│ 0.01 │ 2.65355 │ 10002.0 │ 9901.01 │
│ 0.0001 │ 2.61839 │ 1.0e8 │ 9.999e7 │
│ 1.0e-6 │ 2.61804 │ 1.0e12 │ 9.99999e11 │
│ 1.0e-8 │ 2.61803 │ 1.0e16 │ 1.0e16 │
│ 1.0e-10 │ 2.61803 │ 1.0e20 │ 1.0e20 │
└─────────┴─────────┴─────────┴────────────┘
Not sure about your experience but… Last part of Demo 2.8.3 stating
relative_error = norm(Δx) / norm(x) = 2.3271868502658917
Are incompatible statements!
14×14 Matrix{Float64}:
0.5 0.333333 0.25 … 0.0769231 0.0714286 0.0666667
0.333333 0.25 0.2 0.0714286 0.0666667 0.0625
0.25 0.2 0.166667 0.0666667 0.0625 0.0588235
0.2 0.166667 0.142857 0.0625 0.0588235 0.0555556
0.166667 0.142857 0.125 0.0588235 0.0555556 0.0526316
0.142857 0.125 0.111111 … 0.0555556 0.0526316 0.05
0.125 0.111111 0.1 0.0526316 0.05 0.047619
0.111111 0.1 0.0909091 0.05 0.047619 0.0454545
0.1 0.0909091 0.0833333 0.047619 0.0454545 0.0434783
0.0909091 0.0833333 0.0769231 0.0454545 0.0434783 0.0416667
0.0833333 0.0769231 0.0714286 … 0.0434783 0.0416667 0.04
0.0769231 0.0714286 0.0666667 0.0416667 0.04 0.0384615
0.0714286 0.0666667 0.0625 0.04 0.0384615 0.037037
0.0666667 0.0625 0.0588235 0.0384615 0.037037 0.0357143
16.957912978061536
Problem. Demonstrate the inequality \[\frac{||\Delta x||}{||x||} \leq \kappa\left(\mathbf{A}\right) \frac{||\Delta\mathbf{b}||}{||\mathbf{b}||}\] using
What the matrix \(\mathbf{A}\) looks like for this problem:
using FundamentalsNumericalComputation
n = 10:10:70;
RelErr = []; RHS = [];
for n in n
A = FNC.matrixdepot("prolate", n, 0.4);
x = (1:n)/n;
b = A*x;
xtilde = A \ b;
push!(RelErr, norm(x - xtilde) / norm(x));
push!(RHS, FNC.cond(A)*eps());
end
FNC.pretty_table((n=n,RelErr=RelErr,RHS=RHS),["n" "Relative error of x" "Error bound"])
┌────┬─────────────────────┬─────────────┐
│ n │ Relative error of x │ Error bound │
├────┼─────────────────────┼─────────────┤
│ 10 │ 1.25186e-15 │ 2.42709e-14 │
│ 20 │ 3.89761e-13 │ 1.98397e-11 │
│ 30 │ 6.3531e-15 │ 2.29054e-13 │
│ 40 │ 1.28347e-14 │ 5.56033e-13 │
│ 50 │ 4.65616e-14 │ 8.94772e-13 │
│ 60 │ 5.84773e-14 │ 6.93715e-12 │
│ 70 │ 8.35051e-14 │ 4.13638e-12 │
└────┴─────────────────────┴─────────────┘
using FundamentalsNumericalComputation;
n = 1000:200:3000;
t1 = []; t2 = [];
for n in n
A = triu( tril(rand(n,n),1), -1);
b = ones(n);
AltA = FNC.Tridiagonal(rand(n,n))
time1 = @elapsed for j in 1:50; x = A \ b; end
time2 = @elapsed for j in 1:50; x = AltA \b; end
push!(t1,time1);
push!(t2,time2);
end
TriDiagonal
really help in reducing computational time.