Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests for structured matrices #137

Merged
merged 30 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
[compat]
ADTypes = "1.2.1"
Compat = "3.46,4.2"
DocStringExtensions = "0.8,0.9"
DataStructures = "0.18"
LinearAlgebra = "<0.0.1, 1"
DocStringExtensions = "0.8,0.9"
Random = "<0.0.1, 1"
SparseArrays = "<0.0.1, 1"
julia = "1.6"
2 changes: 1 addition & 1 deletion src/check.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function structurally_orthogonal_columns(
group = group_by_color(color)
for (c, g) in enumerate(group)
Ag = view(A, :, g)
nonzeros_per_row = dropdims(count(!iszero, Ag; dims=2); dims=2)
nonzeros_per_row = only(eachcol(count(!iszero, Ag; dims=2)))
max_nonzeros_per_row, i = findmax(nonzeros_per_row)
if max_nonzeros_per_row > 1
if verbose
Expand Down
4 changes: 4 additions & 0 deletions test/Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
[deps]
ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b"
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
BandedMatrices = "aae01518-5342-5314-be14-df237901396f"
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0"
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
Chairmarks = "0ca39b1e-fe0b-4e98-acfc-b1656634c4de"
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
Expand Down
38 changes: 34 additions & 4 deletions test/allocations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ using Chairmarks
using LinearAlgebra
using SparseArrays
using SparseMatrixColorings
using SparseMatrixColorings: partial_distance2_coloring!
using SparseMatrixColorings: BipartiteGraph, partial_distance2_coloring!
using StableRNGs
using Test

Expand All @@ -21,7 +21,7 @@ end
test_noallocs_distance2_coloring(1000)
end;

function test_noallocs_decompression(
function test_noallocs_sparse_decompression(
n::Integer; structure::Symbol, partition::Symbol, decompression::Symbol
)
A = sparse(Symmetric(sprand(rng, n, n, 5 / n)))
Expand Down Expand Up @@ -75,7 +75,27 @@ function test_noallocs_decompression(
end
end

@testset "Decompression" begin
function test_noallocs_structured_decompression(
n::Integer; structure::Symbol, partition::Symbol, decompression::Symbol
)
@testset "$(nameof(typeof(A)))" for A in [
Diagonal(rand(n)),
Bidiagonal(rand(n), rand(n - 1), 'U'),
Bidiagonal(rand(n), rand(n - 1), 'L'),
Tridiagonal(rand(n - 1), rand(n), rand(n - 1)),
]
result = coloring(
A,
ColoringProblem(; structure, partition),
GreedyColoringAlgorithm(; decompression),
)
B = compress(A, result)
bench = @be similar(A) decompress!(_, B, result) evals = 1
@test minimum(bench).allocs == 0
end
end

@testset "Sparse decompression" begin
@testset "$structure - $partition - $decompression" for (
structure, partition, decompression
) in [
Expand All @@ -84,6 +104,16 @@ end
(:symmetric, :column, :direct),
(:symmetric, :column, :substitution),
]
test_noallocs_decompression(1000; structure, partition, decompression)
test_noallocs_sparse_decompression(1000; structure, partition, decompression)
end
end;

@testset "Structured decompression" begin
@testset "$structure - $partition - $decompression" for (
structure, partition, decompression
) in [
(:nonsymmetric, :column, :direct), (:nonsymmetric, :row, :direct)
]
test_noallocs_structured_decompression(1000; structure, partition, decompression)
end
end;
5 changes: 4 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ include("utils.jl")
@testset verbose = true "Code quality" begin
if VERSION >= v"1.10"
@testset "Aqua" begin
Aqua.test_all(SparseMatrixColorings)
Aqua.test_all(SparseMatrixColorings; stale_deps=(; ignore=[:Requires],))
end
@testset "JET" begin
JET.test_package(SparseMatrixColorings; target_defined_modules=true)
Expand Down Expand Up @@ -53,6 +53,9 @@ include("utils.jl")
@testset "Random instances" begin
include("random.jl")
end
@testset "Structured matrices" begin
include("structured.jl")
end
@testset "Instances with known colorings" begin
include("theory.jl")
end
Expand Down
58 changes: 58 additions & 0 deletions test/structured.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using ArrayInterface: ArrayInterface
using BandedMatrices: BandedMatrix, brand
using BlockBandedMatrices: BandedBlockBandedMatrix, BlockBandedMatrix
using LinearAlgebra
using SparseMatrixColorings
using Test

@testset "Diagonal" begin
for n in (1, 2, 10, 100)
A = Diagonal(rand(n))
test_structured_coloring_decompression(A)
end
end;

@testset "Bidiagonal" begin
for n in (2, 10, 100)
A1 = Bidiagonal(rand(n), rand(n - 1), :U)
A2 = Bidiagonal(rand(n), rand(n - 1), :L)
test_structured_coloring_decompression(A1)
test_structured_coloring_decompression(A2)
end
end;

@testset "Tridiagonal" begin
for n in (2, 10, 100)
A = Tridiagonal(rand(n - 1), rand(n), rand(n - 1))
test_structured_coloring_decompression(A)
end
end;

@testset "BandedMatrices" begin
@testset for (m, n) in [(10, 20), (20, 10)], l in 0:5, u in 0:5
A = brand(m, n, l, u)
test_structured_coloring_decompression(A)
end
end;

@testset "BlockBandedMatrices" begin
for (mb, nb) in [(10, 20), (20, 10)], lb in 0:3, ub in 0:3, _ in 1:10
rows = rand(1:5, mb)
cols = rand(1:5, nb)
A = BlockBandedMatrix{Float64}(rand(sum(rows), sum(cols)), rows, cols, (lb, ub))
test_structured_coloring_decompression(A)
end
end;

@testset "BandedBlockBandedMatrices" begin
for (mb, nb) in [(10, 20), (20, 10)], lb in 0:3, ub in 0:3, _ in 1:10
rows = rand(5:10, mb)
cols = rand(5:10, nb)
λ = rand(0:5)
μ = rand(0:5)
A = BandedBlockBandedMatrix{Float64}(
rand(sum(rows), sum(cols)), rows, cols, (lb, ub), (λ, μ)
)
test_structured_coloring_decompression(A)
end
end;
48 changes: 44 additions & 4 deletions test/type_stability.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ using JET
using LinearAlgebra
using SparseArrays
using SparseMatrixColorings
using SparseMatrixColorings: respectful_similar
using SparseMatrixColorings: matrix_versions, respectful_similar
using StableRNGs
using Test

rng = StableRNG(63)

@testset "Coloring" begin
@testset "Sparse coloring" begin
n = 10
A = sprand(rng, n, n, 5 / n)

Expand Down Expand Up @@ -40,9 +40,28 @@ rng = StableRNG(63)
GreedyColoringAlgorithm(; decompression),
)
end
end
end;

@testset "Decompression" begin
@testset "Structured coloring" begin
n = 10
@testset "$(nameof(typeof(A))) - $structure - $partition - $decompression" for A in [
Diagonal(rand(n)),
Bidiagonal(rand(n), rand(n - 1), 'U'),
Bidiagonal(rand(n), rand(n - 1), 'L'),
Tridiagonal(rand(n - 1), rand(n), rand(n - 1)),
],
(structure, partition, decompression) in
[(:nonsymmetric, :column, :direct), (:nonsymmetric, :row, :direct)]

@test_opt target_modules = (SparseMatrixColorings,) coloring(
A,
ColoringProblem(; structure, partition),
GreedyColoringAlgorithm(; decompression),
)
end
end;

@testset "Sparse decompression" begin
n = 10
A0 = sparse(Symmetric(sprand(rng, n, n, 5 / n)))

Expand Down Expand Up @@ -92,3 +111,24 @@ end
end
end
end;

@testset "Structured decompression" begin
n = 10
@testset "$(nameof(typeof(A))) - $structure - $partition - $decompression" for A in [
Diagonal(rand(n)),
Bidiagonal(rand(n), rand(n - 1), 'U'),
Bidiagonal(rand(n), rand(n - 1), 'L'),
Tridiagonal(rand(n - 1), rand(n), rand(n - 1)),
],
(structure, partition, decompression) in
[(:nonsymmetric, :column, :direct), (:nonsymmetric, :row, :direct)]

result = coloring(
A,
ColoringProblem(; structure, partition),
GreedyColoringAlgorithm(; decompression);
)
B = compress(A, result)
@test_opt decompress(B, result)
end
end;
29 changes: 29 additions & 0 deletions test/utils.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
using ArrayInterface: ArrayInterface
using BandedMatrices: BandedMatrix
using BlockBandedMatrices: BlockBandedMatrix
using LinearAlgebra
using SparseMatrixColorings
using SparseMatrixColorings:
Expand Down Expand Up @@ -138,3 +141,29 @@ function test_coloring_decompression(
@test all(color_vec .== Ref(color_vec[1]))
end
end

function test_structured_coloring_decompression(A::AbstractMatrix)
column_problem = ColoringProblem(; structure=:nonsymmetric, partition=:column)
row_problem = ColoringProblem(; structure=:nonsymmetric, partition=:row)
algo = GreedyColoringAlgorithm()

# Column
result = coloring(A, column_problem, algo)
color = column_colors(result)
B = compress(A, result)
D = decompress(B, result)
@test D == A
@test nameof(typeof(D)) == nameof(typeof(A))
@test structurally_orthogonal_columns(A, color)
if VERSION >= v"1.10" || A isa Union{Diagonal,Bidiagonal,Tridiagonal}
# banded matrices not supported by ArrayInterface on Julia 1.6
# @test color == ArrayInterface.matrix_colors(A) # TODO: uncomment
end

# Row
result = coloring(A, row_problem, algo)
B = compress(A, result)
D = decompress(B, result)
@test D == A
@test nameof(typeof(D)) == nameof(typeof(A))
end