diff --git a/src/constant.jl b/src/constant.jl index 046a1b0f..dd10cf60 100644 --- a/src/constant.jl +++ b/src/constant.jl @@ -75,8 +75,8 @@ end function ConstantColoringAlgorithm{:column}( matrix_template::AbstractMatrix, color::Vector{Int} ) - S = convert(SparseMatrixCSC, matrix_template) - result = ColumnColoringResult(S, color) + bg = BipartiteGraph(matrix_template) + result = ColumnColoringResult(matrix_template, bg, color) M, R = typeof(matrix_template), typeof(result) return ConstantColoringAlgorithm{:column,M,R}(matrix_template, color, result) end @@ -84,8 +84,8 @@ end function ConstantColoringAlgorithm{:row}( matrix_template::AbstractMatrix, color::Vector{Int} ) - S = convert(SparseMatrixCSC, matrix_template) - result = RowColoringResult(S, color) + bg = BipartiteGraph(matrix_template) + result = RowColoringResult(matrix_template, bg, color) M, R = typeof(matrix_template), typeof(result) return ConstantColoringAlgorithm{:row,M,R}(matrix_template, color, result) end diff --git a/src/decompression.jl b/src/decompression.jl index 1d9e92a4..42c5c576 100644 --- a/src/decompression.jl +++ b/src/decompression.jl @@ -115,9 +115,8 @@ true - [`ColoringProblem`](@ref) - [`AbstractColoringResult`](@ref) """ -function decompress(B::AbstractMatrix{R}, result::AbstractColoringResult) where {R<:Real} - @compat (; S) = result - A = respectful_similar(S, R) +function decompress(B::AbstractMatrix, result::AbstractColoringResult) + A = respectful_similar(result.A, eltype(B)) return decompress!(A, B, result) end @@ -264,12 +263,11 @@ end ## ColumnColoringResult -function decompress!( - A::AbstractMatrix{R}, B::AbstractMatrix{R}, result::ColumnColoringResult -) where {R<:Real} - @compat (; S, color) = result +function decompress!(A::AbstractMatrix, B::AbstractMatrix, result::ColumnColoringResult) + @compat (; color) = result + S = result.bg.S2 check_same_pattern(A, S) - A .= zero(R) + fill!(A, zero(eltype(A))) rvS = rowvals(S) for j in axes(S, 2) cj = color[j] @@ -282,9 +280,10 @@ function decompress!( end function decompress_single_color!( - A::AbstractMatrix{R}, b::AbstractVector{R}, c::Integer, result::ColumnColoringResult -) where {R<:Real} - @compat (; S, group) = result + A::AbstractMatrix, b::AbstractVector, c::Integer, result::ColumnColoringResult +) + @compat (; group) = result + S = result.bg.S2 check_same_pattern(A, S) rvS = rowvals(S) for j in group[c] @@ -296,10 +295,9 @@ function decompress_single_color!( return A end -function decompress!( - A::SparseMatrixCSC{R}, B::AbstractMatrix{R}, result::ColumnColoringResult -) where {R<:Real} - @compat (; S, compressed_indices) = result +function decompress!(A::SparseMatrixCSC, B::AbstractMatrix, result::ColumnColoringResult) + @compat (; compressed_indices) = result + S = result.bg.S2 check_same_pattern(A, S) nzA = nonzeros(A) for k in eachindex(nzA, compressed_indices) @@ -309,9 +307,10 @@ function decompress!( end function decompress_single_color!( - A::SparseMatrixCSC{R}, b::AbstractVector{R}, c::Integer, result::ColumnColoringResult -) where {R<:Real} - @compat (; S, group) = result + A::SparseMatrixCSC, b::AbstractVector, c::Integer, result::ColumnColoringResult +) + @compat (; group) = result + S = result.bg.S2 check_same_pattern(A, S) rvS = rowvals(S) nzA = nonzeros(A) @@ -326,12 +325,11 @@ end ## RowColoringResult -function decompress!( - A::AbstractMatrix{R}, B::AbstractMatrix{R}, result::RowColoringResult -) where {R<:Real} - @compat (; S, color) = result +function decompress!(A::AbstractMatrix, B::AbstractMatrix, result::RowColoringResult) + @compat (; color) = result + S = result.bg.S2 check_same_pattern(A, S) - A .= zero(R) + fill!(A, zero(eltype(A))) rvS = rowvals(S) for j in axes(S, 2) for k in nzrange(S, j) @@ -344,9 +342,10 @@ function decompress!( end function decompress_single_color!( - A::AbstractMatrix{R}, b::AbstractVector{R}, c::Integer, result::RowColoringResult -) where {R<:Real} - @compat (; S, Sᵀ, group) = result + A::AbstractMatrix, b::AbstractVector, c::Integer, result::RowColoringResult +) + @compat (; group) = result + S, Sᵀ = result.bg.S2, result.bg.S1 check_same_pattern(A, S) rvSᵀ = rowvals(Sᵀ) for i in group[c] @@ -358,10 +357,9 @@ function decompress_single_color!( return A end -function decompress!( - A::SparseMatrixCSC{R}, B::AbstractMatrix{R}, result::RowColoringResult -) where {R<:Real} - @compat (; S, compressed_indices) = result +function decompress!(A::SparseMatrixCSC, B::AbstractMatrix, result::RowColoringResult) + @compat (; compressed_indices) = result + S = result.bg.S2 check_same_pattern(A, S) nzA = nonzeros(A) for k in eachindex(nzA, compressed_indices) @@ -373,15 +371,13 @@ end ## StarSetColoringResult function decompress!( - A::AbstractMatrix{R}, - B::AbstractMatrix{R}, - result::StarSetColoringResult, - uplo::Symbol=:F, -) where {R<:Real} - @compat (; S, color, star_set) = result + A::AbstractMatrix, B::AbstractMatrix, result::StarSetColoringResult, uplo::Symbol=:F +) + @compat (; color, star_set) = result @compat (; star, hub, spokes) = star_set + S = result.ag.S uplo == :F && check_same_pattern(A, S) - A .= zero(R) + fill!(A, zero(eltype(A))) for i in axes(A, 1) if !iszero(S[i, i]) A[i, i] = B[i, color[i]] @@ -403,14 +399,15 @@ function decompress!( end function decompress_single_color!( - A::AbstractMatrix{R}, - b::AbstractVector{R}, + A::AbstractMatrix, + b::AbstractVector, c::Integer, result::StarSetColoringResult, uplo::Symbol=:F, -) where {R<:Real} - @compat (; S, color, group, star_set) = result +) + @compat (; color, group, star_set) = result @compat (; hub, spokes) = star_set + S = result.ag.S uplo == :F && check_same_pattern(A, S) for i in axes(A, 1) if !iszero(S[i, i]) && color[i] == c @@ -434,12 +431,10 @@ function decompress_single_color!( end function decompress!( - A::SparseMatrixCSC{R}, - B::AbstractMatrix{R}, - result::StarSetColoringResult, - uplo::Symbol=:F, -) where {R<:Real} - @compat (; S, compressed_indices) = result + A::SparseMatrixCSC, B::AbstractMatrix, result::StarSetColoringResult, uplo::Symbol=:F +) + @compat (; compressed_indices) = result + S = result.ag.S nzA = nonzeros(A) if uplo == :F check_same_pattern(A, S) @@ -468,14 +463,13 @@ end # TODO: add method for A::SparseMatrixCSC function decompress!( - A::AbstractMatrix{R}, - B::AbstractMatrix{R}, - result::TreeSetColoringResult, - uplo::Symbol=:F, -) where {R<:Real} - @compat (; S, color, vertices_by_tree, reverse_bfs_orders, buffer) = result + A::AbstractMatrix, B::AbstractMatrix, result::TreeSetColoringResult, uplo::Symbol=:F +) + @compat (; color, vertices_by_tree, reverse_bfs_orders, buffer) = result + S = result.ag.S uplo == :F && check_same_pattern(A, S) - A .= zero(R) + R = eltype(A) + fill!(A, zero(R)) if eltype(buffer) == R buffer_right_type = buffer @@ -513,19 +507,19 @@ end ## MatrixInverseColoringResult function decompress!( - A::AbstractMatrix{R}, - B::AbstractMatrix{R}, + A::AbstractMatrix, + B::AbstractMatrix, result::LinearSystemColoringResult, uplo::Symbol=:F, -) where {R<:Real} - @compat (; - S, color, strict_upper_nonzero_inds, T_factorization, strict_upper_nonzeros_A - ) = result +) + @compat (; color, strict_upper_nonzero_inds, T_factorization, strict_upper_nonzeros_A) = + result + S = result.ag.S uplo == :F && check_same_pattern(A, S) # TODO: for some reason I cannot use ldiv! with a sparse QR strict_upper_nonzeros_A = T_factorization \ vec(B) - A .= zero(R) + fill!(A, zero(eltype(A))) for i in axes(A, 1) if !iszero(S[i, i]) A[i, i] = B[i, color[i]] diff --git a/src/graph.jl b/src/graph.jl index 9d13b827..3810c3a4 100644 --- a/src/graph.jl +++ b/src/graph.jl @@ -24,6 +24,9 @@ end SparsityPatternCSC(A::SparseMatrixCSC) = SparsityPatternCSC(A.m, A.n, A.colptr, A.rowval) Base.size(S::SparsityPatternCSC) = (S.m, S.n) +Base.size(S::SparsityPatternCSC, d) = d::Integer <= 2 ? size(S)[d] : 1 +Base.axes(S::SparsityPatternCSC, d::Integer) = Base.OneTo(size(S, d)) + SparseArrays.nnz(S::SparsityPatternCSC) = length(S.rowval) SparseArrays.rowvals(S::SparsityPatternCSC) = S.rowval SparseArrays.nzrange(S::SparsityPatternCSC, j::Integer) = S.colptr[j]:(S.colptr[j + 1] - 1) @@ -81,6 +84,15 @@ function Base.transpose(S::SparsityPatternCSC{T}) where {T} return SparsityPatternCSC{T}(n, m, B_colptr, B_rowval) end +# copied from SparseArrays.jl +function Base.getindex(S::SparsityPatternCSC, i0::Integer, i1::Integer) + r1 = Int(S.colptr[i1]) + r2 = Int(S.colptr[i1 + 1] - 1) + (r1 > r2) && return false + r1 = searchsortedfirst(rowvals(S), i0, r1, r2, Base.Order.Forward) + return ((r1 > r2) || (rowvals(S)[r1] != i0)) ? false : true +end + ## Adjacency graph """ @@ -109,6 +121,7 @@ struct AdjacencyGraph{T} S::SparsityPatternCSC{T} end +AdjacencyGraph(A::AbstractMatrix) = AdjacencyGraph(SparseMatrixCSC(A)) AdjacencyGraph(A::SparseMatrixCSC) = AdjacencyGraph(SparsityPatternCSC(A)) pattern(g::AdjacencyGraph) = g.S @@ -183,6 +196,10 @@ struct BipartiteGraph{T<:Integer} S2::SparsityPatternCSC{T} end +function BipartiteGraph(A::AbstractMatrix; symmetric_pattern::Bool=false) + return BipartiteGraph(SparseMatrixCSC(A); symmetric_pattern) +end + function BipartiteGraph(A::SparseMatrixCSC; symmetric_pattern::Bool=false) S2 = SparsityPatternCSC(A) # columns to rows if symmetric_pattern diff --git a/src/interface.jl b/src/interface.jl index 5a559ffc..e943d2d1 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -180,12 +180,11 @@ function coloring( decompression_eltype::Type=Float64, symmetric_pattern::Bool=false, ) - S = convert(SparseMatrixCSC, A) bg = BipartiteGraph( - S; symmetric_pattern=symmetric_pattern || A isa Union{Symmetric,Hermitian} + A; symmetric_pattern=symmetric_pattern || A isa Union{Symmetric,Hermitian} ) color = partial_distance2_coloring(bg, Val(2), algo.order) - return ColumnColoringResult(S, color) + return ColumnColoringResult(A, bg, color) end function coloring( @@ -195,12 +194,11 @@ function coloring( decompression_eltype::Type=Float64, symmetric_pattern::Bool=false, ) - S = convert(SparseMatrixCSC, A) bg = BipartiteGraph( - S; symmetric_pattern=symmetric_pattern || A isa Union{Symmetric,Hermitian} + A; symmetric_pattern=symmetric_pattern || A isa Union{Symmetric,Hermitian} ) color = partial_distance2_coloring(bg, Val(1), algo.order) - return RowColoringResult(S, color) + return RowColoringResult(A, bg, color) end function coloring( @@ -209,10 +207,9 @@ function coloring( algo::GreedyColoringAlgorithm{:direct}; decompression_eltype::Type=Float64, ) - S = convert(SparseMatrixCSC, A) - ag = AdjacencyGraph(S) + ag = AdjacencyGraph(A) color, star_set = star_coloring(ag, algo.order) - return StarSetColoringResult(S, color, star_set) + return StarSetColoringResult(A, ag, color, star_set) end function coloring( @@ -221,31 +218,27 @@ function coloring( algo::GreedyColoringAlgorithm{:substitution}; decompression_eltype::Type=Float64, ) - S = convert(SparseMatrixCSC, A) - ag = AdjacencyGraph(S) + ag = AdjacencyGraph(A) color, tree_set = acyclic_coloring(ag, algo.order) - return TreeSetColoringResult(S, color, tree_set, decompression_eltype) + return TreeSetColoringResult(A, ag, color, tree_set, decompression_eltype) end ## ADTypes interface function ADTypes.column_coloring(A::AbstractMatrix, algo::GreedyColoringAlgorithm) - S = convert(SparseMatrixCSC, A) - bg = BipartiteGraph(S; symmetric_pattern=A isa Union{Symmetric,Hermitian}) + bg = BipartiteGraph(A; symmetric_pattern=A isa Union{Symmetric,Hermitian}) color = partial_distance2_coloring(bg, Val(2), algo.order) return color end function ADTypes.row_coloring(A::AbstractMatrix, algo::GreedyColoringAlgorithm) - S = convert(SparseMatrixCSC, A) - bg = BipartiteGraph(S; symmetric_pattern=A isa Union{Symmetric,Hermitian}) + bg = BipartiteGraph(A; symmetric_pattern=A isa Union{Symmetric,Hermitian}) color = partial_distance2_coloring(bg, Val(1), algo.order) return color end function ADTypes.symmetric_coloring(A::AbstractMatrix, algo::GreedyColoringAlgorithm) - S = convert(SparseMatrixCSC, A) - ag = AdjacencyGraph(S) + ag = AdjacencyGraph(A) color, star_set = star_coloring(ag, algo.order) return color end diff --git a/src/matrices.jl b/src/matrices.jl index 2ccfed12..795983c8 100644 --- a/src/matrices.jl +++ b/src/matrices.jl @@ -62,22 +62,23 @@ function respectful_similar(A::Union{Symmetric,Hermitian}, ::Type{T}) where {T} end """ - same_pattern(A::AbstractMatrix, B::AbstractMatrix) + same_pattern(A, B) Perform a partial equality check on the sparsity patterns of `A` and `B`: - if the return is `true`, they might have the same sparsity pattern but we're not sure - if the return is `false`, they definitely don't have the same sparsity pattern """ -function same_pattern(A::AbstractMatrix, B::AbstractMatrix) - return size(A) == size(B) -end +same_pattern(A, B) = size(A) == size(B) -function same_pattern(A::SparseMatrixCSC, B::SparseMatrixCSC) +function same_pattern( + A::Union{SparseMatrixCSC,SparsityPatternCSC}, + B::Union{SparseMatrixCSC,SparsityPatternCSC}, +) return size(A) == size(B) && nnz(A) == nnz(B) end -function check_same_pattern(A::AbstractMatrix, S::AbstractMatrix) +function check_same_pattern(A, S) if !same_pattern(A, S) throw(DimensionMismatch("`A` and `S` must have the same sparsity pattern.")) end diff --git a/src/result.jl b/src/result.jl index 62ff4864..1c35bcdb 100644 --- a/src/result.jl +++ b/src/result.jl @@ -24,7 +24,7 @@ Combination between the type parameters of [`ColoringProblem`](@ref) and [`Greed !!! warning Unlike the methods above, the concrete subtypes of `AbstractColoringResult` are not part of the public API and may change without notice. """ -abstract type AbstractColoringResult{structure,partition,decompression,M<:SparseMatrixCSC} end +abstract type AbstractColoringResult{structure,partition,decompression} end """ column_colors(result::AbstractColoringResult) @@ -99,9 +99,12 @@ $TYPEDFIELDS - [`AbstractColoringResult`](@ref) """ -struct ColumnColoringResult{M} <: AbstractColoringResult{:nonsymmetric,:column,:direct,M} +struct ColumnColoringResult{M<:AbstractMatrix,G<:BipartiteGraph} <: + AbstractColoringResult{:nonsymmetric,:column,:direct} "matrix that was colored" - S::M + A::M + "bipartite graph that was used for coloring" + bg::G "one integer color for each column or row (depending on `partition`)" color::Vector{Int} "color groups for columns or rows (depending on `partition`)" @@ -110,7 +113,8 @@ struct ColumnColoringResult{M} <: AbstractColoringResult{:nonsymmetric,:column,: compressed_indices::Vector{Int} end -function ColumnColoringResult(S::SparseMatrixCSC, color::Vector{Int}) +function ColumnColoringResult(A::AbstractMatrix, bg::BipartiteGraph, color::Vector{Int}) + S = bg.S2 group = group_by_color(color) n = size(S, 1) rv = rowvals(S) @@ -123,7 +127,7 @@ function ColumnColoringResult(S::SparseMatrixCSC, color::Vector{Int}) compressed_indices[k] = (c - 1) * n + i end end - return ColumnColoringResult(S, color, group, compressed_indices) + return ColumnColoringResult(A, bg, color, group, compressed_indices) end """ @@ -141,16 +145,17 @@ $TYPEDFIELDS - [`AbstractColoringResult`](@ref) """ -struct RowColoringResult{M} <: AbstractColoringResult{:nonsymmetric,:row,:direct,M} - S::M - Sᵀ::M +struct RowColoringResult{M<:AbstractMatrix,G<:BipartiteGraph} <: + AbstractColoringResult{:nonsymmetric,:row,:direct} + A::M + bg::G color::Vector{Int} group::Vector{Vector{Int}} compressed_indices::Vector{Int} end -function RowColoringResult(S::SparseMatrixCSC, color::Vector{Int}) - Sᵀ = convert(SparseMatrixCSC, transpose(S)) +function RowColoringResult(A::AbstractMatrix, bg::BipartiteGraph, color::Vector{Int}) + S = bg.S2 group = group_by_color(color) C = length(group) # ncolors rv = rowvals(S) @@ -163,7 +168,7 @@ function RowColoringResult(S::SparseMatrixCSC, color::Vector{Int}) compressed_indices[k] = (j - 1) * C + c end end - return RowColoringResult(S, Sᵀ, color, group, compressed_indices) + return RowColoringResult(A, bg, color, group, compressed_indices) end """ @@ -181,15 +186,20 @@ $TYPEDFIELDS - [`AbstractColoringResult`](@ref) """ -struct StarSetColoringResult{M} <: AbstractColoringResult{:symmetric,:column,:direct,M} - S::M +struct StarSetColoringResult{M<:AbstractMatrix,G<:AdjacencyGraph} <: + AbstractColoringResult{:symmetric,:column,:direct} + A::M + ag::G color::Vector{Int} group::Vector{Vector{Int}} star_set::StarSet compressed_indices::Vector{Int} end -function StarSetColoringResult(S::SparseMatrixCSC, color::Vector{Int}, star_set::StarSet) +function StarSetColoringResult( + A::AbstractMatrix, ag::AdjacencyGraph, color::Vector{Int}, star_set::StarSet +) + S = ag.S group = group_by_color(color) n = size(S, 1) rv = rowvals(S) @@ -202,7 +212,7 @@ function StarSetColoringResult(S::SparseMatrixCSC, color::Vector{Int}, star_set: compressed_indices[k] = (c - 1) * n + l end end - return StarSetColoringResult(S, color, group, star_set, compressed_indices) + return StarSetColoringResult(A, ag, color, group, star_set, compressed_indices) end """ @@ -220,9 +230,10 @@ $TYPEDFIELDS - [`AbstractColoringResult`](@ref) """ -struct TreeSetColoringResult{M,R} <: - AbstractColoringResult{:symmetric,:column,:substitution,M} - S::M +struct TreeSetColoringResult{M<:AbstractMatrix,G<:AdjacencyGraph,R} <: + AbstractColoringResult{:symmetric,:column,:substitution} + A::M + ag::G color::Vector{Int} group::Vector{Vector{Int}} vertices_by_tree::Vector{Vector{Int}} @@ -231,8 +242,13 @@ struct TreeSetColoringResult{M,R} <: end function TreeSetColoringResult( - S::SparseMatrixCSC, color::Vector{Int}, tree_set::TreeSet, decompression_eltype::Type{R} + A::AbstractMatrix, + ag::AdjacencyGraph, + color::Vector{Int}, + tree_set::TreeSet, + decompression_eltype::Type{R}, ) where {R} + S = ag.S nvertices = length(color) group = group_by_color(color) @@ -347,7 +363,7 @@ function TreeSetColoringResult( buffer = Vector{R}(undef, nvertices) return TreeSetColoringResult( - S, color, group, vertices_by_tree, reverse_bfs_orders, buffer + A, ag, color, group, vertices_by_tree, reverse_bfs_orders, buffer ) end @@ -368,9 +384,10 @@ $TYPEDFIELDS - [`AbstractColoringResult`](@ref) """ -struct LinearSystemColoringResult{M,R,F} <: - AbstractColoringResult{:symmetric,:column,:substitution,M} - S::M +struct LinearSystemColoringResult{M<:AbstractMatrix,G<:AdjacencyGraph,R,F} <: + AbstractColoringResult{:symmetric,:column,:substitution} + A::M + ag::G color::Vector{Int} group::Vector{Vector{Int}} strict_upper_nonzero_inds::Vector{Tuple{Int,Int}} @@ -379,10 +396,11 @@ struct LinearSystemColoringResult{M,R,F} <: end function LinearSystemColoringResult( - S::SparseMatrixCSC, color::Vector{Int}, decompression_eltype::Type{R} + A::AbstractMatrix, ag::AdjacencyGraph, color::Vector{Int}, decompression_eltype::Type{R} ) where {R} group = group_by_color(color) C = length(group) # ncolors + S = ag.S rv = rowvals(S) # build T such that T * strict_upper_nonzeros(A) = B @@ -411,6 +429,12 @@ function LinearSystemColoringResult( strict_upper_nonzeros_A = Vector{float(R)}(undef, size(T, 2)) return LinearSystemColoringResult( - S, color, group, strict_upper_nonzero_inds, strict_upper_nonzeros_A, T_factorization + A, + ag, + color, + group, + strict_upper_nonzero_inds, + strict_upper_nonzeros_A, + T_factorization, ) end diff --git a/test/graph.jl b/test/graph.jl index 31d56f03..1eddd1f0 100644 --- a/test/graph.jl +++ b/test/graph.jl @@ -15,13 +15,30 @@ using Test @testset "SparsityPatternCSC" begin @testset "Transpose" begin - for _ in 1:1000 + @test all(1:1000) do _ A = sprand(rand(100:1000), rand(100:1000), 0.1) S = SparsityPatternCSC(A) Sᵀ = transpose(S) Sᵀ_true = SparsityPatternCSC(sparse(transpose(A))) - @test Sᵀ.colptr == Sᵀ_true.colptr - @test Sᵀ.rowval == Sᵀ_true.rowval + Sᵀ.colptr == Sᵀ_true.colptr && Sᵀ.rowval == Sᵀ_true.rowval + end + end + @testset "size" begin + A = spzeros(10, 20) + S = SparsityPatternCSC(A) + @test size(A) == size(S) + @test_throws BoundsError size(A, 0) + @test size(A, 1) == size(S, 1) + @test size(A, 2) == size(S, 2) + @test size(A, 3) == size(S, 3) + @test axes(A, 1) == axes(S, 1) + @test axes(A, 2) == axes(S, 2) + end + @testset "getindex" begin + A = sprand(Bool, 100, 100, 0.1) + S = SparsityPatternCSC(A) + @test all(zip(axes(S, 1), axes(S, 2))) do (i, j) + A[i, j] == S[i, j] end end end diff --git a/test/utils.jl b/test/utils.jl index 89a4749c..2ebad2a4 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -1,6 +1,7 @@ using LinearAlgebra using SparseMatrixColorings -using SparseMatrixColorings: LinearSystemColoringResult, matrix_versions, respectful_similar +using SparseMatrixColorings: + AdjacencyGraph, LinearSystemColoringResult, matrix_versions, respectful_similar using Test function test_coloring_decompression( @@ -99,7 +100,8 @@ function test_coloring_decompression( @testset "Linear system decompression" begin if structure == :symmetric && count(!iszero, A) > 0 # sparse factorization cannot handle empty matrices - linresult = LinearSystemColoringResult(sparse(A), color, Float64) + ag = AdjacencyGraph(A) + linresult = LinearSystemColoringResult(A, ag, color, Float64) @test decompress(float.(B), linresult) ≈ A0 @test decompress!(respectful_similar(float.(A)), float.(B), linresult) ≈ A0 end