Equilibration algorithm
The equilibration algorithm scales a matrix so that its rows and columns have an infinite norm of 1.
using LinearAlgebra, SparseArrays
using OperatorScaling
T = Float64
ϵ = 1.0e-4 # tolerance
m, n = 7, 5
A = sprand(T, m, n, 0.6)
A_scaled, D1, D2 = equilibrate(A, ϵ = ϵ)
norm(D1 * A * D2 - A_scaled) ≤ sqrt(eps(T)) * norm(A)trueDisplay of the input matrix A:
A7×5 SparseArrays.SparseMatrixCSC{Float64, Int64} with 24 stored entries:
⋅ ⋅ 0.191601 0.41821 0.359767
0.222009 0.467676 ⋅ 0.167912 0.347202
0.549691 0.909353 0.803885 ⋅ 0.772499
⋅ ⋅ 0.828975 0.987188 ⋅
⋅ 0.828249 0.29727 0.81902 0.507742
0.860259 ⋅ 0.5879 ⋅ 0.361506
0.885582 ⋅ 0.466837 0.135045 0.390669Display of the scaled matrix A_scaled:
A_scaled7×5 SparseArrays.SparseMatrixCSC{Float64, Int64} with 24 stored entries:
⋅ ⋅ 0.512453 0.949043 1.0
0.480996 0.999919 ⋅ 0.344561 0.87268
0.612546 1.0 0.999981 ⋅ 0.998663
⋅ ⋅ 0.989705 1.0 ⋅
⋅ 0.999989 0.40599 0.949062 0.720661
0.999996 ⋅ 0.762871 ⋅ 0.487514
1.0 ⋅ 0.588458 0.144432 0.511779The in-place version uses storage diagonal matrices, and updates A, D1 and D2 in-place.
D1, R_k = Diagonal(Vector{T}(undef, m)), Diagonal(Vector{T}(undef, m))
D2, C_k = Diagonal(Vector{T}(undef, n)), Diagonal(Vector{T}(undef, n))
A_scaled2 = copy(A)
equilibrate!(A_scaled2, D1, D2, R_k, C_k, ϵ = ϵ)
# A_scaled2, D1 and D2 are now updated
norm(D1 * A * D2 - A_scaled2) ≤ sqrt(eps(T)) * norm(A)trueThis packages also features an implementation for symmetric matrices:
A = sprand(Float64, m, m, 0.3)
Q = Symmetric(tril(A + A'), :L)
Q_scaled, D = equilibrate(Q, ϵ = ϵ)
norm(D * Q * D - Q_scaled) ≤ sqrt(eps(T)) * norm(Q)trueDisplay of the input matrix Q:
Q7×7 LinearAlgebra.Symmetric{Float64, SparseArrays.SparseMatrixCSC{Float64, Int64}}:
0.0 0.0 0.0 0.109324 0.7919 0.0 0.0
0.0 1.01896 1.23837 0.723549 0.0 0.0 1.15952
0.0 1.23837 1.22586 0.0 0.289815 0.0 0.0
0.109324 0.723549 0.0 0.0 0.0 0.0 0.0775407
0.7919 0.0 0.289815 0.0 0.0 0.0989077 0.0
0.0 0.0 0.0 0.0 0.0989077 0.0 0.0
0.0 1.15952 0.0 0.0775407 0.0 0.0 0.126391Display of the scaled matrix Q_scaled:
Q_scaled7×7 LinearAlgebra.Symmetric{Float64, SparseArrays.SparseMatrixCSC{Float64, Int64}}:
0.0 0.0 0.0 0.188943 1.0 0.0 0.0
0.0 0.822822 1.0 0.999984 0.0 0.0 0.999998
0.0 1.0 0.989899 0.0 0.292658 0.0 0.0
0.188943 0.999984 0.0 0.0 0.0 0.0 0.114452
1.0 0.0 0.292658 0.0 0.0 0.999937 0.0
0.0 0.0 0.0 0.0 0.999937 0.0 0.0
0.0 0.999998 0.0 0.114452 0.0 0.0 0.116414Q_scaled2 = copy(Q)
# D diagonal matrix and storage diagonal matrix (same size as Q)
D, C_k = Diagonal(Vector{T}(undef, m)), Diagonal(Vector{T}(undef, m))
equilibrate!(Q_scaled2, D, C_k, ϵ = ϵ)
norm(D * Q * D - Q_scaled2) ≤ sqrt(eps(T)) * norm(Q)true