|
| 1 | +module SparseMatrixColoringsBlockBandedMatricesExt |
| 2 | + |
| 3 | +if isdefined(Base, :get_extension) |
| 4 | + using BlockArrays: blockaxes, blockfirsts, blocklasts, blocksize, blocklengths |
| 5 | + using BlockBandedMatrices: |
| 6 | + BandedBlockBandedMatrix, |
| 7 | + BlockBandedMatrix, |
| 8 | + blockbandrange, |
| 9 | + blockbandwidths, |
| 10 | + blocklengths, |
| 11 | + blocksize, |
| 12 | + subblockbandwidths |
| 13 | + using SparseMatrixColorings: |
| 14 | + BipartiteGraph, |
| 15 | + ColoringProblem, |
| 16 | + ColumnColoringResult, |
| 17 | + GreedyColoringAlgorithm, |
| 18 | + RowColoringResult, |
| 19 | + column_colors, |
| 20 | + cycle_range, |
| 21 | + row_colors |
| 22 | + import SparseMatrixColorings as SMC |
| 23 | +else |
| 24 | + using ..BlockArrays: blockaxes, blockfirsts, blocklasts, blocksize, blocklengths |
| 25 | + using ..BlockBandedMatrices: |
| 26 | + BandedBlockBandedMatrix, |
| 27 | + BlockBandedMatrix, |
| 28 | + blockbandrange, |
| 29 | + blockbandwidths, |
| 30 | + blocklengths, |
| 31 | + blocksize, |
| 32 | + subblockbandwidths |
| 33 | + using ..SparseMatrixColorings: |
| 34 | + BipartiteGraph, |
| 35 | + ColoringProblem, |
| 36 | + ColumnColoringResult, |
| 37 | + GreedyColoringAlgorithm, |
| 38 | + RowColoringResult, |
| 39 | + column_colors, |
| 40 | + cycle_range, |
| 41 | + row_colors |
| 42 | + import ..SparseMatrixColorings as SMC |
| 43 | +end |
| 44 | + |
| 45 | +#= |
| 46 | +This code is partly taken from ArrayInterface.jl and FiniteDiff.jl |
| 47 | +https://github.com/JuliaArrays/ArrayInterface.jl |
| 48 | +https://github.com/JuliaDiff/FiniteDiff.jl |
| 49 | +=# |
| 50 | + |
| 51 | +function subblockbandrange(A::BandedBlockBandedMatrix) |
| 52 | + u, l = subblockbandwidths(A) |
| 53 | + return (-l):u |
| 54 | +end |
| 55 | + |
| 56 | +function blockbanded_coloring( |
| 57 | + A::Union{BlockBandedMatrix,BandedBlockBandedMatrix}, dim::Integer |
| 58 | +) |
| 59 | + # consider blocks of columns or rows (let's call them vertices) depending on `dim` |
| 60 | + nb_blocks = blocksize(A, dim) |
| 61 | + nb_in_block = blocklengths(axes(A, dim)) |
| 62 | + first_in_block = blockfirsts(axes(A, dim)) |
| 63 | + last_in_block = blocklasts(axes(A, dim)) |
| 64 | + color = zeros(Int, size(A, dim)) |
| 65 | + |
| 66 | + # give a macroscopic color to each block, so that 2 blocks with the same macro color are orthogonal |
| 67 | + # same idea as for BandedMatrices |
| 68 | + nb_macrocolors = length(blockbandrange(A)) |
| 69 | + macrocolor = cycle_range(nb_macrocolors, nb_blocks) |
| 70 | + |
| 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 | + typemax(Int) |
| 77 | + end |
| 78 | + |
| 79 | + # for each macroscopic color, count how many microscopic colors will be needed |
| 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 |
| 85 | + color_shift_in_macrocolor = vcat(0, cumsum(nb_colors_in_macrocolor)[1:(end - 1)]) |
| 86 | + |
| 87 | + # assign a microscopic color to each column as a function of its macroscopic color and its position within the block |
| 88 | + for b in 1:nb_blocks |
| 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 |
| 92 | + end |
| 93 | + |
| 94 | + return color |
| 95 | +end |
| 96 | + |
| 97 | +function SMC.coloring( |
| 98 | + A::Union{BlockBandedMatrix,BandedBlockBandedMatrix}, |
| 99 | + ::ColoringProblem{:nonsymmetric,:column}, |
| 100 | + algo::GreedyColoringAlgorithm; |
| 101 | + kwargs..., |
| 102 | +) |
| 103 | + color = blockbanded_coloring(A, 2) |
| 104 | + bg = BipartiteGraph(A) |
| 105 | + return ColumnColoringResult(A, bg, color) |
| 106 | +end |
| 107 | + |
| 108 | +function SMC.coloring( |
| 109 | + A::Union{BlockBandedMatrix,BandedBlockBandedMatrix}, |
| 110 | + ::ColoringProblem{:nonsymmetric,:row}, |
| 111 | + algo::GreedyColoringAlgorithm; |
| 112 | + kwargs..., |
| 113 | +) |
| 114 | + color = blockbanded_coloring(A, 1) |
| 115 | + bg = BipartiteGraph(A) |
| 116 | + return RowColoringResult(A, bg, color) |
| 117 | +end |
| 118 | + |
| 119 | +end |
0 commit comments