Skip to content

Commit fcf052b

Browse files
committed
[bicoloring] Use Br and Bc directly for the decompression
1 parent e5ce73c commit fcf052b

File tree

4 files changed

+59
-42
lines changed

4 files changed

+59
-42
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: 51 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -717,56 +717,73 @@ end
717717

718718
## BicoloringResult
719719

720-
function _join_compressed!(result::BicoloringResult, Br::AbstractMatrix, Bc::AbstractMatrix)
721-
#=
722-
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)]`.
723-
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)]`.
724-
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`.
725-
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`).
726-
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.
727-
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.
728-
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.
729-
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.
730-
We use the vectors `symmetric_to_row` and `symmetric_to_column` to map from symmetric colors to row and column colors.
731-
=#
732-
(; A, symmetric_to_column, symmetric_to_row) = result
733-
m, n = size(A)
734-
R = Base.promote_eltype(Br, Bc)
735-
if eltype(result.Br_and_Bc) == R
736-
Br_and_Bc = result.Br_and_Bc
720+
"""
721+
JoinCompressed{R<:Real}
722+
723+
For a bicoloring of an original matrix `A` of size `(m, n)`, we build an augmented matrix `A_and_Aᵀ = [0 Aᵀ; A 0]`.
724+
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`.
725+
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`).
726+
727+
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.
728+
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.
729+
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.
730+
731+
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`.
732+
733+
# Fields
734+
735+
- `m::Int`: number of rows in `A` and `Bc`
736+
- `n::Int`: number of columns in `A` and `Br`
737+
- `Br::AbstractMatrix{R}`: row-wise compressed matrix
738+
- `Bc::AbstractMatrix{R}`: column-wise compressed matrix
739+
- `symmetric_to_row::Vector{Int}`: vector mapping symmetric colors to row indices in `Br`
740+
- `symmetric_to_column::Vector{Int}`: vector mapping symmetric colors to column indices in `Bc`
741+
"""
742+
struct JoinCompressed{R<:Real,M1<:AbstractMatrix{R},M2<:AbstractMatrix{R}} <:
743+
AbstractMatrix{R}
744+
m::Int
745+
n::Int
746+
Br::M1
747+
Bc::M2
748+
symmetric_to_row::Vector{Int}
749+
symmetric_to_column::Vector{Int}
750+
end
751+
752+
function Base.getindex(B::JoinCompressed, i::Integer, j::Integer)
753+
(; n, Br, Bc, symmetric_to_row, symmetric_to_column) = B
754+
if i n
755+
return Br[symmetric_to_row[j], i]
737756
else
738-
Br_and_Bc = similar(result.Br_and_Bc, R)
739-
end
740-
fill!(Br_and_Bc, zero(R))
741-
for c in axes(Br_and_Bc, 2)
742-
if symmetric_to_row[c] > 0 # some rows were colored with the symmetric color c
743-
copyto!(view(Br_and_Bc, 1:n, c), view(Br, symmetric_to_row[c], :))
744-
end
745-
if symmetric_to_column[c] > 0 # some columns were colored with the symmetric color c
746-
copyto!(
747-
view(Br_and_Bc, (n + 1):(n + m), c), view(Bc, :, symmetric_to_column[c])
748-
)
749-
end
757+
return Bc[i - n, symmetric_to_column[j]]
750758
end
751-
return Br_and_Bc
759+
end
760+
761+
function Base.getindex(B::JoinCompressed, k::Integer)
762+
dim = B.m + B.n
763+
i = mod(k - 1, dim) + 1
764+
j = div(k - 1, dim) + 1
765+
return getindex(B, i, j)
752766
end
753767

754768
function decompress!(
755769
A::AbstractMatrix, Br::AbstractMatrix, Bc::AbstractMatrix, result::BicoloringResult
756770
)
771+
(; symmetric_to_row, symmetric_to_column, symmetric_result) = result
757772
m, n = size(A)
758-
Br_and_Bc = _join_compressed!(result, Br, Bc)
759-
A_and_Aᵀ = decompress(Br_and_Bc, result.symmetric_result)
773+
Br_and_Bc = JoinCompressed(m, n, Br, Bc, symmetric_to_row, symmetric_to_column)
774+
A_and_Aᵀ = decompress(Br_and_Bc, symmetric_result)
760775
copyto!(A, A_and_Aᵀ[(n + 1):(n + m), 1:n]) # original matrix in bottom left corner
761776
return A
762777
end
763778

764779
function decompress!(
765780
A::SparseMatrixCSC, Br::AbstractMatrix, Bc::AbstractMatrix, result::BicoloringResult
766781
)
767-
(; large_colptr, large_rowval, symmetric_result) = result
782+
(;
783+
symmetric_to_row, symmetric_to_column, symmetric_result, large_colptr, large_rowval
784+
) = result
768785
m, n = size(A)
769-
Br_and_Bc = _join_compressed!(result, Br, Bc)
786+
Br_and_Bc = JoinCompressed(m, n, Br, Bc, symmetric_to_row, symmetric_to_column)
770787
# pretend A is larger
771788
A_and_noAᵀ = SparseMatrixCSC(m + n, m + n, large_colptr, large_rowval, A.nzval)
772789
# 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
@@ -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
@@ -588,7 +583,6 @@ function BicoloringResult(
588583
symmetric_result,
589584
symmetric_to_column,
590585
symmetric_to_row,
591-
Br_and_Bc,
592586
large_colptr,
593587
large_rowval,
594588
)

0 commit comments

Comments
 (0)