|
| 1 | +""" |
| 2 | + CompressedMatrix{dir} |
| 3 | +
|
| 4 | +Compressed representation `B` of a sparse matrix `A ∈ ℝ^{m×n}` obtained by summing some of its columns (if `dir == :col`) or rows (if `dir == :row`), grouped by color. |
| 5 | +
|
| 6 | +# Fields |
| 7 | +
|
| 8 | +- `sparsity::AbstractMatrix{Bool}`: boolean sparsity pattern of the matrix `A` |
| 9 | +- `colors::Vector{Int}`: vector such that |
| 10 | + - if `dir == `:col`, then `colors[j] ∈ 1:c` is the color of column `j` |
| 11 | + - if `dir == `:row`, then `colors[i] ∈ 1:c` is the color of row `i` |
| 12 | +- `groups::Vector{Vector{Int}}`: vector of length `c` such that |
| 13 | + - if `dir == :col`, then `groups[k]` is the vector of column indices assigned to the same color `k ∈ 1:c` |
| 14 | + - if `dir == :row`, then `groups[k]` is the vector of row indices assigned to the same color `k ∈ 1:c` |
| 15 | +- `aggregates::AbstractMatrix`: matrix `B` such that |
| 16 | + - if `dir == :col`, then `size(B) = (m, c)` and `B[:, c] = sum(A[:, k] for k in groups[c])` |
| 17 | + - if `dir == :row`, then `size(B) = (c, n)` and `B[c, :] = sum(A[k, :] for k in groups[c])` |
| 18 | +""" |
| 19 | +mutable struct CompressedMatrix{dir,S<:AbstractMatrix{Bool},M<:AbstractMatrix} |
| 20 | + sparsity::S |
| 21 | + colors::Vector{Int} |
| 22 | + groups::Vector{Vector{Int}} |
| 23 | + aggregates::M |
| 24 | +end |
| 25 | + |
| 26 | +""" |
| 27 | + CompressedMatrix{dir}(sparsity, groups, aggregates) |
| 28 | +
|
| 29 | +Constructor for [`CompressedMatrix`](@ref). |
| 30 | +""" |
| 31 | +function CompressedMatrix{dir}(sparsity, colors, groups, aggregates) where {dir} |
| 32 | + @assert dir in (:col, :row) |
| 33 | + return CompressedMatrix{dir,typeof(sparsity),typeof(aggregates)}( |
| 34 | + sparsity, colors, groups, aggregates |
| 35 | + ) |
| 36 | +end |
| 37 | + |
| 38 | +function decompress!(A::AbstractMatrix, compressed::CompressedMatrix{:col}) |
| 39 | + (; sparsity, colors, aggregates) = compressed |
| 40 | + A .= zero(eltype(A)) |
| 41 | + @views for j in axes(A, 2) |
| 42 | + k = colors[j] |
| 43 | + nz_rows_j = (!iszero).(sparsity[:, j]) |
| 44 | + copyto!(A[nz_rows_j, j], aggregates[nz_rows_j, k]) |
| 45 | + end |
| 46 | + return A |
| 47 | +end |
| 48 | + |
| 49 | +function decompress!(A::AbstractMatrix, compressed::CompressedMatrix{:row}) |
| 50 | + (; sparsity, colors, aggregates) = compressed |
| 51 | + A .= zero(eltype(A)) |
| 52 | + @views for i in axes(A, 1) |
| 53 | + k = colors[i] |
| 54 | + nz_cols_i = (!iszero).(sparsity[i, :]) |
| 55 | + copyto!(A[i, nz_cols_i], aggregates[k, nz_cols_i]) |
| 56 | + end |
| 57 | + return A |
| 58 | +end |
| 59 | + |
| 60 | +function decompress_symmetric!(A::AbstractMatrix, compressed::CompressedMatrix{:col}) |
| 61 | + (; sparsity, colors, groups, aggregates) = compressed |
| 62 | + @views for j in axes(A, 2) |
| 63 | + k = colors[j] |
| 64 | + group = groups[k] |
| 65 | + for i in axes(A, 1) |
| 66 | + if (!iszero(sparsity[i, j]) && count(!iszero, sparsity[i, group]) == 1) |
| 67 | + A[i, j] = aggregates[i, k] |
| 68 | + A[j, i] = aggregates[i, k] |
| 69 | + end |
| 70 | + end |
| 71 | + end |
| 72 | + return A |
| 73 | +end |
0 commit comments