Skip to content

Commit 66acbca

Browse files
committed
BandedBlockBandedMatrices
1 parent 116691d commit 66acbca

3 files changed

Lines changed: 61 additions & 40 deletions

File tree

ext/SparseMatrixColoringsBlockBandedMatricesExt.jl

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module SparseMatrixColoringsBlockBandedMatricesExt
33
if isdefined(Base, :get_extension)
44
using BlockArrays: blockaxes, blockfirsts, blocklasts, blocksize, blocklengths
55
using BlockBandedMatrices:
6+
BandedBlockBandedMatrix,
67
BlockBandedMatrix,
78
blockbandrange,
89
blockbandwidths,
@@ -22,6 +23,7 @@ if isdefined(Base, :get_extension)
2223
else
2324
using ..BlockArrays: blockaxes, blockfirsts, blocklasts, blocksize, blocklengths
2425
using ..BlockBandedMatrices:
26+
BandedBlockBandedMatrix,
2527
BlockBandedMatrix,
2628
blockbandrange,
2729
blockbandwidths,
@@ -46,9 +48,14 @@ https://github.com/JuliaArrays/ArrayInterface.jl
4648
https://github.com/JuliaDiff/FiniteDiff.jl
4749
=#
4850

49-
## BlockBandedMatrix
51+
function subblockbandrange(A::BandedBlockBandedMatrix)
52+
u, l = subblockbandwidths(A)
53+
return (-l):u
54+
end
5055

51-
function blockbanded_coloring(A::BlockBandedMatrix, dim::Integer)
56+
function blockbanded_coloring(
57+
A::Union{BlockBandedMatrix,BandedBlockBandedMatrix}, dim::Integer
58+
)
5259
# consider blocks of columns or rows (let's call them vertices) depending on `dim`
5360
nb_blocks = blocksize(A, dim)
5461
nb_in_block = blocklengths(axes(A, dim))
@@ -61,27 +68,34 @@ function blockbanded_coloring(A::BlockBandedMatrix, dim::Integer)
6168
nb_macrocolors = length(blockbandrange(A))
6269
macrocolor = cycle_range(nb_macrocolors, nb_blocks)
6370

71+
width = if A isa BandedBlockBandedMatrix
72+
# vertices within a block are colored cleverly using bands
73+
length(subblockbandrange(A))
74+
else
75+
# vertices within a block are colored naively with distinct micro colors (~ infinite band width)
76+
minimum(size(A))
77+
end
78+
6479
# for each macroscopic color, count how many microscopic colors will be needed
65-
# vertices within a block are colored naively with all distinct micro colors
66-
nb_colors_in_macrocolor = [
67-
maximum(nb_in_block[mc:nb_macrocolors:nb_blocks]; init=0) for mc in 1:nb_macrocolors
68-
]
80+
nb_colors_in_macrocolor = zeros(Int, nb_macrocolors)
81+
for mc in 1:nb_macrocolors
82+
largest_nb_in_macrocolor = maximum(nb_in_block[mc:nb_macrocolors:nb_blocks]; init=0)
83+
nb_colors_in_macrocolor[mc] = min(width, largest_nb_in_macrocolor)
84+
end
6985
color_shift_in_macrocolor = vcat(0, cumsum(nb_colors_in_macrocolor)[1:(end - 1)])
7086

7187
# assign a microscopic color to each column as a function of its macroscopic color and its position within the block
7288
for b in 1:nb_blocks
73-
mc = macrocolor[b]
74-
shift = color_shift_in_macrocolor[mc]
75-
for k in first_in_block[b]:last_in_block[b]
76-
color[k] = shift + (k - first_in_block[b] + 1)
77-
end
89+
block_color = cycle_range(width, nb_in_block[b])
90+
shift = color_shift_in_macrocolor[macrocolor[b]]
91+
color[first_in_block[b]:last_in_block[b]] .= shift .+ block_color
7892
end
7993

8094
return color
8195
end
8296

8397
function SMC.coloring(
84-
A::BlockBandedMatrix,
98+
A::Union{BlockBandedMatrix,BandedBlockBandedMatrix},
8599
::ColoringProblem{:nonsymmetric,:column},
86100
algo::GreedyColoringAlgorithm;
87101
kwargs...,
@@ -92,7 +106,7 @@ function SMC.coloring(
92106
end
93107

94108
function SMC.coloring(
95-
A::BlockBandedMatrix,
109+
A::Union{BlockBandedMatrix,BandedBlockBandedMatrix},
96110
::ColoringProblem{:nonsymmetric,:row},
97111
algo::GreedyColoringAlgorithm;
98112
kwargs...,
@@ -102,6 +116,4 @@ function SMC.coloring(
102116
return RowColoringResult(A, bg, color)
103117
end
104118

105-
106-
107119
end

test/structured.jl

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ using Test
1818
end;
1919

2020
@testset "Diagonal" begin
21-
@testset for n in (1, 2, 10, 100)
21+
for n in (1, 2, 10, 100)
2222
A = Diagonal(rand(n))
2323
test_structured_coloring_decompression(A)
2424
end
2525
end;
2626

2727
@testset "Bidiagonal" begin
28-
@testset for n in (2, 10, 100)
28+
for n in (2, 10, 100)
2929
A1 = Bidiagonal(rand(n), rand(n - 1), :U)
3030
A2 = Bidiagonal(rand(n), rand(n - 1), :L)
3131
test_structured_coloring_decompression(A1)
@@ -48,10 +48,23 @@ end;
4848
end;
4949

5050
@testset "BlockBandedMatrices" begin
51-
@testset for (mb, nb) in [(10, 20), (20, 10)], lb in 0:3, ub in 0:3, bs in 1:3
52-
rows = rand(1:bs, mb)
53-
cols = rand(1:bs, nb)
51+
for (mb, nb) in [(10, 20), (20, 10)], lb in 0:3, ub in 0:3, _ in 1:10
52+
rows = rand(1:5, mb)
53+
cols = rand(1:5, nb)
5454
A = BlockBandedMatrix{Float64}(rand(sum(rows), sum(cols)), rows, cols, (l, u))
5555
test_structured_coloring_decompression(A)
5656
end
5757
end;
58+
59+
@testset "BandedBlockBandedMatrices" begin
60+
for (mb, nb) in [(10, 20), (20, 10)], lb in 0:3, ub in 0:3, _ in 1:10
61+
rows = rand(5:10, mb)
62+
cols = rand(5:10, nb)
63+
λ = rand(0:5)
64+
μ = rand(0:5)
65+
A = BandedBlockBandedMatrix{Float64}(
66+
rand(sum(rows), sum(cols)), rows, cols, (lb, ub), (λ, μ)
67+
)
68+
test_structured_coloring_decompression(A)
69+
end
70+
end;

test/utils.jl

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -127,24 +127,20 @@ function test_structured_coloring_decompression(A::AbstractMatrix)
127127
row_problem = ColoringProblem(; structure=:nonsymmetric, partition=:row)
128128
algo = GreedyColoringAlgorithm()
129129

130-
@testset "Column" begin
131-
result = coloring(A, column_problem, algo)
132-
color = column_colors(result)
133-
B = compress(A, result)
134-
D = decompress(B, result)
135-
@test D == A
136-
@test D isa typeof(A)
137-
@test structurally_orthogonal_columns(A, color)
138-
if A isa OptimalColoringKnown
139-
@test color == ArrayInterface.matrix_colors(A)
140-
end
141-
end
142-
143-
@testset "Row" begin
144-
result = coloring(A, row_problem, algo)
145-
B = compress(A, result)
146-
D = decompress(B, result)
147-
@test D == A
148-
@test D isa typeof(A)
149-
end
130+
# Column
131+
result = coloring(A, column_problem, algo)
132+
color = column_colors(result)
133+
B = compress(A, result)
134+
D = decompress(B, result)
135+
@test D == A
136+
@test nameof(typeof(D)) == nameof(typeof(A))
137+
@test structurally_orthogonal_columns(A, color)
138+
@test color == ArrayInterface.matrix_colors(A)
139+
140+
# Row
141+
result = coloring(A, row_problem, algo)
142+
B = compress(A, result)
143+
D = decompress(B, result)
144+
@test D == A
145+
@test nameof(typeof(D)) == nameof(typeof(A))
150146
end

0 commit comments

Comments
 (0)