Skip to content

Commit 451cb51

Browse files
committed
[bicoloring] Use Br and Bc directly for the decompression
1 parent 398490d commit 451cb51

File tree

4 files changed

+56
-41
lines changed

4 files changed

+56
-41
lines changed

docs/src/dev.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ SparseMatrixColorings.StarSetColoringResult
4040
SparseMatrixColorings.TreeSetColoringResult
4141
SparseMatrixColorings.LinearSystemColoringResult
4242
SparseMatrixColorings.BicoloringResult
43+
```
44+
45+
## Decompression
46+
47+
```@docs
48+
SparseMatrixColorings.JoinCompressed
4349
SparseMatrixColorings.remap_colors
4450
```
4551

src/decompression.jl

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -701,56 +701,70 @@ end
701701

702702
## BicoloringResult
703703

704-
function _join_compressed!(result::BicoloringResult, Br::AbstractMatrix, Bc::AbstractMatrix)
705-
#=
706-
Say we have an original matrix `A` of size `(n, m)` and we build an augmented matrix `A_and_Aᵀ = [zeros(n, n) Aᵀ; A zeros(m, m)]`.
707-
Its first `1:n` columns have the form `[zeros(n); A[:, j]]` and its following `n+1:n+m` columns have the form `[A[i, :]; zeros(m)]`.
708-
The symmetric column coloring is performed on `A_and_Aᵀ` and the column-wise compression of `A_and_Aᵀ` should return a matrix `Br_and_Bc`.
709-
But in reality, `Br_and_Bc` is computed as two partial compressions: the row-wise compression `Br` (corresponding to `Aᵀ`) and the columnwise compression `Bc` (corresponding to `A`).
710-
Before symmetric decompression, we must reconstruct `Br_and_Bc` from `Br` and `Bc`, knowing that the symmetric colors (those making up `Br_and_Bc`) are present in either a row of `Br`, a column of `Bc`, or both.
711-
Therefore, the column indices in `Br_and_Bc` don't necessarily match with the row indices in `Br` or the column indices in `Bc` since some colors may be missing in the partial compressions.
712-
The columns of the top part of `Br_and_Bc` (rows `1:n`) are the rows of `Br`, interlaced with zero columns whenever the current color hasn't been used to color any row.
713-
The columns of the bottom part of `Br_and_Bc` (rows `n+1:n+m`) are the columns of `Bc`, interlaced with zero columns whenever the current color hasn't been used to color any column.
714-
We use the vectors `symmetric_to_row` and `symmetric_to_column` to map from symmetric colors to row and column colors.
715-
=#
716-
(; A, symmetric_to_column, symmetric_to_row) = result
717-
m, n = size(A)
718-
R = Base.promote_eltype(Br, Bc)
719-
if eltype(result.Br_and_Bc) == R
720-
Br_and_Bc = result.Br_and_Bc
704+
"""
705+
JoinCompressed{R<:Real}
706+
707+
For a bicoloring of an original matrix `A` of size `(m, n)`, we build an augmented matrix `A_and_Aᵀ = [0 Aᵀ; A 0]`.
708+
Symmetric column coloring is then performed on `A_and_Aᵀ`, and the column-wise compression of `A_and_Aᵀ` produces a matrix `Br_and_Bc`.
709+
In the case of bicoloring, `Br_and_Bc` is computed as two partial compressions: the row-wise compression `Br` (corresponding to `Aᵀ`) and the column-wise compression `Bc` (corresponding to `A`).
710+
711+
For the symmetric decompression, we lazily reconstruct `Br_and_Bc` from `Br` and `Bc`, knowing that the symmetric colors (those making up `Br_and_Bc`) may appear in either a row of `Br`, a column of `Bc`, or both.
712+
The columns of the top part of `Br_and_Bc` (rows between `1` and `n`) are taken from the rows of `Br`, interleaved with zero columns whenever the current color has not been used to color any row.
713+
The columns of the bottom part of `Br_and_Bc` (rows between `n+1` and `n+m`) are taken from the columns of `Bc`, interleaved with zero columns whenever the current color has not been used to color any column.
714+
715+
We use the vectors `symmetric_to_row` and `symmetric_to_column` to map colors obtained during star or acyclic coloring to row colors in `Br` and column colors in `Bc`.
716+
717+
# Fields
718+
719+
- `m::Int`: number of rows in `A` and `Bc`
720+
- `n::Int`: number of columns in `A` and `Br`
721+
- `Br::AbstractMatrix{R}`: row-wise compressed matrix
722+
- `Bc::AbstractMatrix{R}`: column-wise compressed matrix
723+
- `symmetric_to_row::Vector{Int}`: vector mapping symmetric colors to row indices in `Br`
724+
- `symmetric_to_column::Vector{Int}`: vector mapping symmetric colors to column indices in `Bc`
725+
"""
726+
struct JoinCompressed{R<:Real,M1<:AbstractMatrix{R},M2<:AbstractMatrix{R}} <: AbstractMatrix{R}
727+
m::Int
728+
n::Int
729+
Br::M1
730+
Bc::M2
731+
symmetric_to_row::Vector{Int}
732+
symmetric_to_column::Vector{Int}
733+
end
734+
735+
function Base.getindex(B::JoinCompressed, i::Integer, j::Integer)
736+
(; n, Br, Bc, symmetric_to_row, symmetric_to_column) = B
737+
if i n
738+
return Br[symmetric_to_row[j], i]
721739
else
722-
Br_and_Bc = similar(result.Br_and_Bc, R)
740+
return Bc[i - n, symmetric_to_column[j]]
723741
end
724-
fill!(Br_and_Bc, zero(R))
725-
for c in axes(Br_and_Bc, 2)
726-
if symmetric_to_row[c] > 0 # some rows were colored with the symmetric color c
727-
copyto!(view(Br_and_Bc, 1:n, c), view(Br, symmetric_to_row[c], :))
728-
end
729-
if symmetric_to_column[c] > 0 # some columns were colored with the symmetric color c
730-
copyto!(
731-
view(Br_and_Bc, (n + 1):(n + m), c), view(Bc, :, symmetric_to_column[c])
732-
)
733-
end
734-
end
735-
return Br_and_Bc
742+
end
743+
744+
function Base.getindex(B::JoinCompressed, k::Integer)
745+
dim = B.m + B.n
746+
i = mod(k - 1, dim) + 1
747+
j = div(k - 1, dim) + 1
748+
return getindex(B, i, j)
736749
end
737750

738751
function decompress!(
739752
A::AbstractMatrix, Br::AbstractMatrix, Bc::AbstractMatrix, result::BicoloringResult
740753
)
754+
(; row_color_ind, symmetric_to_row, symmetric_to_column) = result
741755
m, n = size(A)
742-
Br_and_Bc = _join_compressed!(result, Br, Bc)
743-
A_and_Aᵀ = decompress(Br_and_Bc, result.symmetric_result)
756+
Br_and_Bc = JoinCompressed(m, n, Br, Bc, symmetric_to_row, symmetric_to_column)
757+
A_and_Aᵀ = decompress(Br_and_Bc, symmetric_result)
744758
copyto!(A, A_and_Aᵀ[(n + 1):(n + m), 1:n]) # original matrix in bottom left corner
745759
return A
746760
end
747761

748762
function decompress!(
749763
A::SparseMatrixCSC, Br::AbstractMatrix, Bc::AbstractMatrix, result::BicoloringResult
750764
)
751-
(; large_colptr, large_rowval, symmetric_result) = result
765+
(; row_color_ind, col_color_ind, symmetric_result, large_colptr, large_rowval) = result
752766
m, n = size(A)
753-
Br_and_Bc = _join_compressed!(result, Br, Bc)
767+
Br_and_Bc = JoinCompressed(m, n, Br, Bc, row_color_ind, col_color_ind)
754768
# pretend A is larger
755769
A_and_noAᵀ = SparseMatrixCSC(m + n, m + n, large_colptr, large_rowval, A.nzval)
756770
# decompress lower triangle only

src/interface.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ function coloring(
248248
A_and_Aᵀ, ag, color, tree_set, decompression_eltype
249249
)
250250
end
251-
return BicoloringResult(A, ag, symmetric_result, decompression_eltype)
251+
return BicoloringResult(A, ag, symmetric_result)
252252
end
253253

254254
## ADTypes interface

src/result.jl

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,6 @@ struct BicoloringResult{
526526
decompression,
527527
V,
528528
SR<:AbstractColoringResult{:symmetric,:column,decompression},
529-
R,
530529
} <: AbstractColoringResult{:nonsymmetric,:bidirectional,decompression}
531530
"matrix that was colored"
532531
A::M
@@ -546,8 +545,6 @@ struct BicoloringResult{
546545
symmetric_to_column::Vector{Int}
547546
"maps symmetric colors to row colors"
548547
symmetric_to_row::Vector{Int}
549-
"combination of `Br` and `Bc` (almost a concatenation up to color remapping)"
550-
Br_and_Bc::Matrix{R}
551548
"CSC storage of `A_and_noAᵀ - `colptr`"
552549
large_colptr::Vector{Int}
553550
"CSC storage of `A_and_noAᵀ - `rowval`"
@@ -564,8 +561,7 @@ function BicoloringResult(
564561
A::AbstractMatrix,
565562
ag::AdjacencyGraph,
566563
symmetric_result::AbstractColoringResult{:symmetric,:column},
567-
decompression_eltype::Type{R},
568-
) where {R}
564+
)
569565
m, n = size(A)
570566
symmetric_color = column_colors(symmetric_result)
571567
num_sym_colors = maximum(symmetric_color)
@@ -574,7 +570,6 @@ function BicoloringResult(
574570
)
575571
column_group = group_by_color(column_color)
576572
row_group = group_by_color(row_color)
577-
Br_and_Bc = Matrix{R}(undef, n + m, num_sym_colors)
578573
large_colptr = copy(ag.S.colptr)
579574
large_colptr[(n + 2):end] .= large_colptr[n + 1] # last few columns are empty
580575
large_rowval = ag.S.rowval[1:(end ÷ 2)] # forget the second half of nonzeros

0 commit comments

Comments
 (0)