This package computes covers of matrices: non-negative vectors a and b
such that a[i] * b[j] >= abs(A[i, j]) for all i, j. Covers are the
natural scale-covariant representation of a matrix, making them a useful
building block for scale-invariant numerical analysis. In particular,
i and j, this simple construct finds applications that range from
statistical normalization
of data to the design of well-behaved numerical algorithms (thanks, e.g.,
to bounds on
The package provides O(mn) heuristics (symcover, cover), soft covers that
penalize violations (soft_symcover, soft_cover), and objective-minimal hard
covers (symcover_min, cover_min). The default squared-log penalty uses a
built-in solver; other penalties use JuMP with HiGHS or Ipopt.
julia> using MatrixCovers, LinearAlgebra
julia> A = [4.0 2.0; 2.0 16.0];
julia> a = symcover(A) # a[i] * a[j] >= abs(A[i, j])
2-element Vector{Float64}:
2.0
4.0
julia> a * a' # dominates A entrywise
2×2 Matrix{Float64}:
4.0 8.0
8.0 16.0
julia> iscover(a, A)
trueCovers are scale-covariant:
julia> D = Diagonal([10.0, 0.5]);
julia> symcover(D * A * D) ≈ D * a
trueFor nonsymmetric matrices, cover returns separate row and column scales.
cover_min minimizes a penalty subject to the coverage constraint:
julia> M = [1.0 2.0 3.0; 6.0 5.0 4.0];
julia> a, b = cover(M);
julia> iscover(a, b, M)
true
julia> aq, bq = cover_min(AbsLog{2}(), M);
julia> cover_objective(AbsLog{2}(), aq, bq, M) <= cover_objective(AbsLog{2}(), a, b, M)
trueSee the documentation for the algorithm guide and API reference.