From 975404ef63862ff8f5af43e59a930b01889314af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Mon, 19 Jan 2026 15:11:23 +0100 Subject: [PATCH 1/6] Fix coloring with empty matrix as input --- src/interface.jl | 8 +++++++- src/result.jl | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/interface.jl b/src/interface.jl index 936b974c..0d183c9c 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -305,7 +305,13 @@ function _coloring( vertices_in_order = vertices(ag, order) return acyclic_coloring(ag, vertices_in_order, algo.postprocessing) end - color, tree_set = argmin(maximum ∘ first, color_and_tree_set_by_order) + # if `color` is empty, `maximum` will fail but `color_and_tree_set_by_order` + # is also one so we can just add a special case for this + if length(color_and_tree_set_by_order) == 1 + color, tree_set = only(color_and_tree_set_by_order) + else + color, tree_set = argmin(maximum ∘ first, color_and_tree_set_by_order) + end if speed_setting isa WithResult return TreeSetColoringResult(A, ag, color, tree_set, R) else diff --git a/src/result.jl b/src/result.jl index c74ceaa1..bdb58538 100644 --- a/src/result.jl +++ b/src/result.jl @@ -82,6 +82,9 @@ Create a color-indexed vector `group` such that `i ∈ group[c]` iff `color[i] = Assumes the colors are contiguously numbered from `0` to some `cmax`. """ function group_by_color(::Type{T}, color::AbstractVector) where {T<:Integer} + if isempty(color) + return SubArray{Int,1,Vector{Int},Tuple{UnitRange{Int}},true}[] + end cmin, cmax = extrema(color) @assert cmin >= 0 # Compute group sizes and offsets for a joint storage From 266784eada32ec56d744b376104e6a65ab620ead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Wed, 21 Jan 2026 10:20:29 +0100 Subject: [PATCH 2/6] Update src/result.jl Co-authored-by: Guillaume Dalle <22795598+gdalle@users.noreply.github.com> --- src/result.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/result.jl b/src/result.jl index bdb58538..0d47cf13 100644 --- a/src/result.jl +++ b/src/result.jl @@ -83,7 +83,7 @@ Assumes the colors are contiguously numbered from `0` to some `cmax`. """ function group_by_color(::Type{T}, color::AbstractVector) where {T<:Integer} if isempty(color) - return SubArray{Int,1,Vector{Int},Tuple{UnitRange{Int}},true}[] + return typeof(view(T[], 1:0))[] end cmin, cmax = extrema(color) @assert cmin >= 0 From 8bbe38842d1c17bef7da05131ab3f038ee737c76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 29 Jan 2026 13:42:16 +0100 Subject: [PATCH 3/6] Add check --- test/check.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/check.jl b/test/check.jl index b2701095..d8e2dc68 100644 --- a/test/check.jl +++ b/test/check.jl @@ -1,4 +1,5 @@ using LinearAlgebra +using SparseArrays using SparseMatrixColorings: structurally_orthogonal_columns, symmetrically_orthogonal_columns, @@ -308,3 +309,12 @@ end log = (:warn, "4 colors provided for 3 rows.") @test_logs log !substitutable_bidirectional(A, B, [1, 0, 0, 1], [0, 1, 1]; verbose=true) end + +# See https://github.com/gdalle/SparseMatrixColorings.jl/pull/300 +@testset "Empty matrix" begin + problem = ColoringProblem(; structure = :symmetric, partition = :column) + algo = GreedyColoringAlgorithm(; decompression = :substitution) + S = spzeros(Int, 0, 0) + result = coloring(S, problem, algo) + @test isempty(result.color) +end From 005e07f2aab71019db974e64be2bdad07e0bf98d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 29 Jan 2026 14:00:31 +0100 Subject: [PATCH 4/6] Fix format --- test/check.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/check.jl b/test/check.jl index d8e2dc68..7a4f5187 100644 --- a/test/check.jl +++ b/test/check.jl @@ -312,8 +312,8 @@ end # See https://github.com/gdalle/SparseMatrixColorings.jl/pull/300 @testset "Empty matrix" begin - problem = ColoringProblem(; structure = :symmetric, partition = :column) - algo = GreedyColoringAlgorithm(; decompression = :substitution) + problem = ColoringProblem(; structure=:symmetric, partition=:column) + algo = GreedyColoringAlgorithm(; decompression=:substitution) S = spzeros(Int, 0, 0) result = coloring(S, problem, algo) @test isempty(result.color) From c2cc91ac5433559b8a2becff42830e63c8956850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 29 Jan 2026 18:33:27 +0100 Subject: [PATCH 5/6] Change check --- test/check.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/check.jl b/test/check.jl index 7a4f5187..67e36635 100644 --- a/test/check.jl +++ b/test/check.jl @@ -316,5 +316,5 @@ end algo = GreedyColoringAlgorithm(; decompression=:substitution) S = spzeros(Int, 0, 0) result = coloring(S, problem, algo) - @test isempty(result.color) + @test isempty(result.group) end From 9caca0f459edc802a08a4050c17947554b8cd599 Mon Sep 17 00:00:00 2001 From: Guillaume Dalle <22795598+gdalle@users.noreply.github.com> Date: Thu, 29 Jan 2026 18:35:31 +0100 Subject: [PATCH 6/6] Apply suggestion from @gdalle --- test/check.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/check.jl b/test/check.jl index 67e36635..246261d0 100644 --- a/test/check.jl +++ b/test/check.jl @@ -316,5 +316,6 @@ end algo = GreedyColoringAlgorithm(; decompression=:substitution) S = spzeros(Int, 0, 0) result = coloring(S, problem, algo) + @test isempty(result.color) @test isempty(result.group) end