Skip to content

Commit 07d7e1d

Browse files
committed
[bicoloring] Use Br and Bc directly for the decompression
1 parent 1ce9fb8 commit 07d7e1d

3 files changed

Lines changed: 56 additions & 40 deletions

File tree

src/decompression.jl

Lines changed: 54 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -701,54 +701,76 @@ 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 dictionaries `col_color_ind` and `row_color_ind` to map from symmetric colors to row/column colors.
715-
=#
716-
(; A, col_color_ind, row_color_ind) = 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 dictionaries `col_color_ind` and `row_color_ind` 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+
- `c::Int` : number of colors used for the symmetric coloring
722+
- `Br::AbstractMatrix{R}` : row-wise compressed matrix
723+
- `Bc::AbstractMatrix{R}` : column-wise compressed matrix
724+
- `row_color_ind::Dict{Int,Int}` : dictionary mapping symmetric colors to row indices in `Br`
725+
- `col_color_ind::Dict{Int,Int}` : dictionary mapping symmetric colors to column indices in `Bc`
726+
"""
727+
struct JoinCompressed{R<:Real} <: AbstractMatrix{R}
728+
m::Int
729+
n::Int
730+
c::Int
731+
Br::Matrix{R}
732+
Bc::Matrix{R}
733+
row_color_ind::Dict{Int,Int}
734+
col_color_ind::Dict{Int,Int}
735+
end
736+
737+
Base.size(B::JoinCompressed) = (B.m + B.n, B.c)
738+
739+
function Base.getindex(B::JoinCompressed, i::Integer, j::Integer)
740+
(; n, Br, Bc, row_color_ind, col_color_ind) = B
741+
if i n
742+
return Br[row_color_ind[j], i]
721743
else
722-
Br_and_Bc = similar(result.Br_and_Bc, R)
723-
end
724-
fill!(Br_and_Bc, zero(R))
725-
for c in axes(Br_and_Bc, 2)
726-
if haskey(row_color_ind, c) # some rows were colored with symmetric color c
727-
copyto!(view(Br_and_Bc, 1:n, c), view(Br, row_color_ind[c], :))
728-
end
729-
if haskey(col_color_ind, c) # some columns were colored with symmetric c
730-
copyto!(view(Br_and_Bc, (n + 1):(n + m), c), view(Bc, :, col_color_ind[c]))
731-
end
744+
return Bc[i - n, col_color_ind[j]]
732745
end
733-
return Br_and_Bc
746+
end
747+
748+
function Base.getindex(B::JoinCompressed, k::Integer)
749+
dim = B.m + B.n
750+
i = mod(k - 1, dim) + 1
751+
j = div(k - 1, dim) + 1
752+
return getindex(B, i, j)
734753
end
735754

736755
function decompress!(
737756
A::AbstractMatrix, Br::AbstractMatrix, Bc::AbstractMatrix, result::BicoloringResult
738757
)
758+
(; row_color_ind, col_color_ind, symmetric_result) = result
739759
m, n = size(A)
740-
Br_and_Bc = _join_compressed!(result, Br, Bc)
741-
A_and_Aᵀ = decompress(Br_and_Bc, result.symmetric_result)
760+
c = ncolors(result)
761+
Br_and_Bc = JoinCompressed(m, n, c, Br, Bc, row_color_ind, col_color_ind)
762+
A_and_Aᵀ = decompress(Br_and_Bc, symmetric_result)
742763
copyto!(A, A_and_Aᵀ[(n + 1):(n + m), 1:n]) # original matrix in bottom left corner
743764
return A
744765
end
745766

746767
function decompress!(
747768
A::SparseMatrixCSC, Br::AbstractMatrix, Bc::AbstractMatrix, result::BicoloringResult
748769
)
749-
(; large_colptr, large_rowval, symmetric_result) = result
770+
(; row_color_ind, col_color_ind, symmetric_result, large_colptr, large_rowval) = result
750771
m, n = size(A)
751-
Br_and_Bc = _join_compressed!(result, Br, Bc)
772+
c = ncolors(result)
773+
Br_and_Bc = JoinCompressed(m, n, c, Br, Bc, row_color_ind, col_color_ind)
752774
# pretend A is larger
753775
A_and_noAᵀ = SparseMatrixCSC(m + n, m + n, large_colptr, large_rowval, A.nzval)
754776
# 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 & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,6 @@ struct BicoloringResult{
493493
decompression,
494494
V,
495495
SR<:AbstractColoringResult{:symmetric,:column,decompression},
496-
R,
497496
} <: AbstractColoringResult{:nonsymmetric,:bidirectional,decompression}
498497
"matrix that was colored"
499498
A::M
@@ -513,8 +512,6 @@ struct BicoloringResult{
513512
col_color_ind::Dict{Int,Int}
514513
"row color to index"
515514
row_color_ind::Dict{Int,Int}
516-
"combination of `Br` and `Bc` (almost a concatenation up to color remapping)"
517-
Br_and_Bc::Matrix{R}
518515
"CSC storage of `A_and_noAᵀ - `colptr`"
519516
large_colptr::Vector{Int}
520517
"CSC storage of `A_and_noAᵀ - `rowval`"
@@ -531,15 +528,13 @@ function BicoloringResult(
531528
A::AbstractMatrix,
532529
ag::AdjacencyGraph,
533530
symmetric_result::AbstractColoringResult{:symmetric,:column},
534-
decompression_eltype::Type{R},
535-
) where {R}
531+
)
536532
m, n = size(A)
537533
symmetric_color = column_colors(symmetric_result)
538534
column_color, col_color_ind = remap_colors(symmetric_color[1:n])
539535
row_color, row_color_ind = remap_colors(symmetric_color[(n + 1):(n + m)])
540536
column_group = group_by_color(column_color)
541537
row_group = group_by_color(row_color)
542-
Br_and_Bc = Matrix{R}(undef, n + m, maximum(column_colors(symmetric_result)))
543538
large_colptr = copy(ag.S.colptr)
544539
large_colptr[(n + 2):end] .= large_colptr[n + 1] # last few columns are empty
545540
large_rowval = ag.S.rowval[1:(end ÷ 2)] # forget the second half of nonzeros
@@ -553,7 +548,6 @@ function BicoloringResult(
553548
symmetric_result,
554549
col_color_ind,
555550
row_color_ind,
556-
Br_and_Bc,
557551
large_colptr,
558552
large_rowval,
559553
)

0 commit comments

Comments
 (0)