Skip to content

Commit c28490d

Browse files
authored
Add tests for structured matrices (#137)
* Structured decompression * Store graph in result to allow generic matrices * Use `fill!` whenever possible * More tests * Record useless BipartiteGraph * Fix docs * Fix cycling inferrability * More tests * Add BandedMatrices * Reactivate lts * Extras * Fix LTS * Ignore unloaded Requires * Add BlockBandedMatrices * Row coloring * Fix LTS * No fail fast * BandedBlockBandedMatrices * Infinite width * Import * Fix * Fix version * Remove optimized structured implementations * Min diff * Remove cycle range tests * Fix import
1 parent 8430561 commit c28490d

8 files changed

Lines changed: 175 additions & 11 deletions

File tree

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
1515
[compat]
1616
ADTypes = "1.2.1"
1717
Compat = "3.46,4.2"
18-
DocStringExtensions = "0.8,0.9"
1918
DataStructures = "0.18"
2019
LinearAlgebra = "<0.0.1, 1"
20+
DocStringExtensions = "0.8,0.9"
2121
Random = "<0.0.1, 1"
2222
SparseArrays = "<0.0.1, 1"
2323
julia = "1.6"

src/check.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ function structurally_orthogonal_columns(
3636
group = group_by_color(color)
3737
for (c, g) in enumerate(group)
3838
Ag = view(A, :, g)
39-
nonzeros_per_row = dropdims(count(!iszero, Ag; dims=2); dims=2)
39+
nonzeros_per_row = only(eachcol(count(!iszero, Ag; dims=2)))
4040
max_nonzeros_per_row, i = findmax(nonzeros_per_row)
4141
if max_nonzeros_per_row > 1
4242
if verbose

test/Project.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
[deps]
22
ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b"
33
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
4+
ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
5+
BandedMatrices = "aae01518-5342-5314-be14-df237901396f"
6+
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
7+
BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0"
48
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
59
Chairmarks = "0ca39b1e-fe0b-4e98-acfc-b1656634c4de"
610
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"

test/allocations.jl

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ using Chairmarks
22
using LinearAlgebra
33
using SparseArrays
44
using SparseMatrixColorings
5-
using SparseMatrixColorings: partial_distance2_coloring!
5+
using SparseMatrixColorings: BipartiteGraph, partial_distance2_coloring!
66
using StableRNGs
77
using Test
88

@@ -21,7 +21,7 @@ end
2121
test_noallocs_distance2_coloring(1000)
2222
end;
2323

24-
function test_noallocs_decompression(
24+
function test_noallocs_sparse_decompression(
2525
n::Integer; structure::Symbol, partition::Symbol, decompression::Symbol
2626
)
2727
A = sparse(Symmetric(sprand(rng, n, n, 5 / n)))
@@ -75,7 +75,27 @@ function test_noallocs_decompression(
7575
end
7676
end
7777

78-
@testset "Decompression" begin
78+
function test_noallocs_structured_decompression(
79+
n::Integer; structure::Symbol, partition::Symbol, decompression::Symbol
80+
)
81+
@testset "$(nameof(typeof(A)))" for A in [
82+
Diagonal(rand(n)),
83+
Bidiagonal(rand(n), rand(n - 1), 'U'),
84+
Bidiagonal(rand(n), rand(n - 1), 'L'),
85+
Tridiagonal(rand(n - 1), rand(n), rand(n - 1)),
86+
]
87+
result = coloring(
88+
A,
89+
ColoringProblem(; structure, partition),
90+
GreedyColoringAlgorithm(; decompression),
91+
)
92+
B = compress(A, result)
93+
bench = @be similar(A) decompress!(_, B, result) evals = 1
94+
@test minimum(bench).allocs == 0
95+
end
96+
end
97+
98+
@testset "Sparse decompression" begin
7999
@testset "$structure - $partition - $decompression" for (
80100
structure, partition, decompression
81101
) in [
@@ -84,6 +104,16 @@ end
84104
(:symmetric, :column, :direct),
85105
(:symmetric, :column, :substitution),
86106
]
87-
test_noallocs_decompression(1000; structure, partition, decompression)
107+
test_noallocs_sparse_decompression(1000; structure, partition, decompression)
108+
end
109+
end;
110+
111+
@testset "Structured decompression" begin
112+
@testset "$structure - $partition - $decompression" for (
113+
structure, partition, decompression
114+
) in [
115+
(:nonsymmetric, :column, :direct), (:nonsymmetric, :row, :direct)
116+
]
117+
test_noallocs_structured_decompression(1000; structure, partition, decompression)
88118
end
89119
end;

test/runtests.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ include("utils.jl")
1111
@testset verbose = true "Code quality" begin
1212
if VERSION >= v"1.10"
1313
@testset "Aqua" begin
14-
Aqua.test_all(SparseMatrixColorings)
14+
Aqua.test_all(SparseMatrixColorings; stale_deps=(; ignore=[:Requires],))
1515
end
1616
@testset "JET" begin
1717
JET.test_package(SparseMatrixColorings; target_defined_modules=true)
@@ -56,6 +56,9 @@ include("utils.jl")
5656
@testset "Random instances" begin
5757
include("random.jl")
5858
end
59+
@testset "Structured matrices" begin
60+
include("structured.jl")
61+
end
5962
@testset "Instances with known colorings" begin
6063
include("theory.jl")
6164
end

test/structured.jl

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using ArrayInterface: ArrayInterface
2+
using BandedMatrices: BandedMatrix, brand
3+
using BlockBandedMatrices: BandedBlockBandedMatrix, BlockBandedMatrix
4+
using LinearAlgebra
5+
using SparseMatrixColorings
6+
using Test
7+
8+
@testset "Diagonal" begin
9+
for n in (1, 2, 10, 100)
10+
A = Diagonal(rand(n))
11+
test_structured_coloring_decompression(A)
12+
end
13+
end;
14+
15+
@testset "Bidiagonal" begin
16+
for n in (2, 10, 100)
17+
A1 = Bidiagonal(rand(n), rand(n - 1), :U)
18+
A2 = Bidiagonal(rand(n), rand(n - 1), :L)
19+
test_structured_coloring_decompression(A1)
20+
test_structured_coloring_decompression(A2)
21+
end
22+
end;
23+
24+
@testset "Tridiagonal" begin
25+
for n in (2, 10, 100)
26+
A = Tridiagonal(rand(n - 1), rand(n), rand(n - 1))
27+
test_structured_coloring_decompression(A)
28+
end
29+
end;
30+
31+
@testset "BandedMatrices" begin
32+
@testset for (m, n) in [(10, 20), (20, 10)], l in 0:5, u in 0:5
33+
A = brand(m, n, l, u)
34+
test_structured_coloring_decompression(A)
35+
end
36+
end;
37+
38+
@testset "BlockBandedMatrices" begin
39+
for (mb, nb) in [(10, 20), (20, 10)], lb in 0:3, ub in 0:3, _ in 1:10
40+
rows = rand(1:5, mb)
41+
cols = rand(1:5, nb)
42+
A = BlockBandedMatrix{Float64}(rand(sum(rows), sum(cols)), rows, cols, (lb, ub))
43+
test_structured_coloring_decompression(A)
44+
end
45+
end;
46+
47+
@testset "BandedBlockBandedMatrices" begin
48+
for (mb, nb) in [(10, 20), (20, 10)], lb in 0:3, ub in 0:3, _ in 1:10
49+
rows = rand(5:10, mb)
50+
cols = rand(5:10, nb)
51+
λ = rand(0:5)
52+
μ = rand(0:5)
53+
A = BandedBlockBandedMatrix{Float64}(
54+
rand(sum(rows), sum(cols)), rows, cols, (lb, ub), (λ, μ)
55+
)
56+
test_structured_coloring_decompression(A)
57+
end
58+
end;

test/type_stability.jl

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ using JET
33
using LinearAlgebra
44
using SparseArrays
55
using SparseMatrixColorings
6-
using SparseMatrixColorings: respectful_similar
6+
using SparseMatrixColorings: matrix_versions, respectful_similar
77
using StableRNGs
88
using Test
99

1010
rng = StableRNG(63)
1111

12-
@testset "Coloring" begin
12+
@testset "Sparse coloring" begin
1313
n = 10
1414
A = sprand(rng, n, n, 5 / n)
1515

@@ -40,9 +40,28 @@ rng = StableRNG(63)
4040
GreedyColoringAlgorithm(; decompression),
4141
)
4242
end
43-
end
43+
end;
4444

45-
@testset "Decompression" begin
45+
@testset "Structured coloring" begin
46+
n = 10
47+
@testset "$(nameof(typeof(A))) - $structure - $partition - $decompression" for A in [
48+
Diagonal(rand(n)),
49+
Bidiagonal(rand(n), rand(n - 1), 'U'),
50+
Bidiagonal(rand(n), rand(n - 1), 'L'),
51+
Tridiagonal(rand(n - 1), rand(n), rand(n - 1)),
52+
],
53+
(structure, partition, decompression) in
54+
[(:nonsymmetric, :column, :direct), (:nonsymmetric, :row, :direct)]
55+
56+
@test_opt target_modules = (SparseMatrixColorings,) coloring(
57+
A,
58+
ColoringProblem(; structure, partition),
59+
GreedyColoringAlgorithm(; decompression),
60+
)
61+
end
62+
end;
63+
64+
@testset "Sparse decompression" begin
4665
n = 10
4766
A0 = sparse(Symmetric(sprand(rng, n, n, 5 / n)))
4867

@@ -92,3 +111,24 @@ end
92111
end
93112
end
94113
end;
114+
115+
@testset "Structured decompression" begin
116+
n = 10
117+
@testset "$(nameof(typeof(A))) - $structure - $partition - $decompression" for A in [
118+
Diagonal(rand(n)),
119+
Bidiagonal(rand(n), rand(n - 1), 'U'),
120+
Bidiagonal(rand(n), rand(n - 1), 'L'),
121+
Tridiagonal(rand(n - 1), rand(n), rand(n - 1)),
122+
],
123+
(structure, partition, decompression) in
124+
[(:nonsymmetric, :column, :direct), (:nonsymmetric, :row, :direct)]
125+
126+
result = coloring(
127+
A,
128+
ColoringProblem(; structure, partition),
129+
GreedyColoringAlgorithm(; decompression);
130+
)
131+
B = compress(A, result)
132+
@test_opt decompress(B, result)
133+
end
134+
end;

test/utils.jl

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
using ArrayInterface: ArrayInterface
2+
using BandedMatrices: BandedMatrix
3+
using BlockBandedMatrices: BlockBandedMatrix
14
using LinearAlgebra
25
using SparseMatrixColorings
36
using SparseMatrixColorings:
@@ -138,3 +141,29 @@ function test_coloring_decompression(
138141
@test all(color_vec .== Ref(color_vec[1]))
139142
end
140143
end
144+
145+
function test_structured_coloring_decompression(A::AbstractMatrix)
146+
column_problem = ColoringProblem(; structure=:nonsymmetric, partition=:column)
147+
row_problem = ColoringProblem(; structure=:nonsymmetric, partition=:row)
148+
algo = GreedyColoringAlgorithm()
149+
150+
# Column
151+
result = coloring(A, column_problem, algo)
152+
color = column_colors(result)
153+
B = compress(A, result)
154+
D = decompress(B, result)
155+
@test D == A
156+
@test nameof(typeof(D)) == nameof(typeof(A))
157+
@test structurally_orthogonal_columns(A, color)
158+
if VERSION >= v"1.10" || A isa Union{Diagonal,Bidiagonal,Tridiagonal}
159+
# banded matrices not supported by ArrayInterface on Julia 1.6
160+
# @test color == ArrayInterface.matrix_colors(A) # TODO: uncomment
161+
end
162+
163+
# Row
164+
result = coloring(A, row_problem, algo)
165+
B = compress(A, result)
166+
D = decompress(B, result)
167+
@test D == A
168+
@test nameof(typeof(D)) == nameof(typeof(A))
169+
end

0 commit comments

Comments
 (0)