Skip to content

Commit d9ec840

Browse files
authored
Exclude ordering from coloring primitives (#249)
* Exclude ordering from coloring primitives * Bump
1 parent 0c2771a commit d9ec840

File tree

4 files changed

+57
-44
lines changed

4 files changed

+57
-44
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "SparseMatrixColorings"
22
uuid = "0a514795-09f3-496d-8182-132a7b665d35"
33
authors = ["Guillaume Dalle", "Alexis Montoison"]
4-
version = "0.4.18"
4+
version = "0.4.19"
55

66
[deps]
77
ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b"

src/coloring.jl

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
"""
2-
partial_distance2_coloring(bg::BipartiteGraph, ::Val{side}, order::AbstractOrder)
2+
partial_distance2_coloring(bg::BipartiteGraph, ::Val{side}, vertices_in_order::AbstractVector)
33
44
Compute a distance-2 coloring of the given `side` (`1` or `2`) in the bipartite graph `bg` and return a vector of integer colors.
55
66
A _distance-2 coloring_ is such that two vertices have different colors if they are at distance at most 2.
77
8-
The vertices are colored in a greedy fashion, following the `order` supplied.
8+
The vertices are colored in a greedy fashion, following the order supplied.
99
1010
# See also
1111
@@ -17,11 +17,10 @@ The vertices are colored in a greedy fashion, following the `order` supplied.
1717
> [_What Color Is Your Jacobian? Graph Coloring for Computing Derivatives_](https://epubs.siam.org/doi/10.1137/S0036144504444711), Gebremedhin et al. (2005), Algorithm 3.2
1818
"""
1919
function partial_distance2_coloring(
20-
bg::BipartiteGraph{T}, ::Val{side}, order::AbstractOrder
20+
bg::BipartiteGraph{T}, ::Val{side}, vertices_in_order::AbstractVector{<:Integer}
2121
) where {T,side}
2222
color = Vector{T}(undef, nb_vertices(bg, Val(side)))
2323
forbidden_colors = Vector{T}(undef, nb_vertices(bg, Val(side)))
24-
vertices_in_order = vertices(bg, Val(side), order)
2524
partial_distance2_coloring!(color, forbidden_colors, bg, Val(side), vertices_in_order)
2625
return color
2726
end
@@ -54,7 +53,7 @@ function partial_distance2_coloring!(
5453
end
5554

5655
"""
57-
star_coloring(g::AdjacencyGraph, order::AbstractOrder, postprocessing::Bool)
56+
star_coloring(g::AdjacencyGraph, vertices_in_order::AbstractVector, postprocessing::Bool)
5857
5958
Compute a star coloring of all vertices in the adjacency graph `g` and return a tuple `(color, star_set)`, where
6059
@@ -63,7 +62,7 @@ Compute a star coloring of all vertices in the adjacency graph `g` and return a
6362
6463
A _star coloring_ is a distance-1 coloring such that every path on 4 vertices uses at least 3 colors.
6564
66-
The vertices are colored in a greedy fashion, following the `order` supplied.
65+
The vertices are colored in a greedy fashion, following the order supplied.
6766
6867
If `postprocessing=true`, some colors might be replaced with `0` (the "neutral" color) as long as they are not needed during decompression.
6968
@@ -77,7 +76,7 @@ If `postprocessing=true`, some colors might be replaced with `0` (the "neutral"
7776
> [_New Acyclic and Star Coloring Algorithms with Application to Computing Hessians_](https://epubs.siam.org/doi/abs/10.1137/050639879), Gebremedhin et al. (2007), Algorithm 4.1
7877
"""
7978
function star_coloring(
80-
g::AdjacencyGraph{T}, order::AbstractOrder, postprocessing::Bool
79+
g::AdjacencyGraph{T}, vertices_in_order::AbstractVector{<:Integer}, postprocessing::Bool
8180
) where {T<:Integer}
8281
# Initialize data structures
8382
nv = nb_vertices(g)
@@ -88,7 +87,6 @@ function star_coloring(
8887
treated = zeros(T, nv)
8988
star = Vector{T}(undef, ne)
9089
hub = T[] # one hub for each star, including the trivial ones
91-
vertices_in_order = vertices(g, order)
9290

9391
for v in vertices_in_order
9492
for (w, index_vw) in neighbors_with_edge_indices(g, v)
@@ -206,7 +204,7 @@ struct StarSet{T}
206204
end
207205

208206
"""
209-
acyclic_coloring(g::AdjacencyGraph, order::AbstractOrder, postprocessing::Bool)
207+
acyclic_coloring(g::AdjacencyGraph, vertices_in_order::AbstractVector, postprocessing::Bool)
210208
211209
Compute an acyclic coloring of all vertices in the adjacency graph `g` and return a tuple `(color, tree_set)`, where
212210
@@ -215,7 +213,7 @@ Compute an acyclic coloring of all vertices in the adjacency graph `g` and retur
215213
216214
An _acyclic coloring_ is a distance-1 coloring with the further restriction that every cycle uses at least 3 colors.
217215
218-
The vertices are colored in a greedy fashion, following the `order` supplied.
216+
The vertices are colored in a greedy fashion, following the order supplied.
219217
220218
If `postprocessing=true`, some colors might be replaced with `0` (the "neutral" color) as long as they are not needed during decompression.
221219
@@ -229,7 +227,7 @@ If `postprocessing=true`, some colors might be replaced with `0` (the "neutral"
229227
> [_New Acyclic and Star Coloring Algorithms with Application to Computing Hessians_](https://epubs.siam.org/doi/abs/10.1137/050639879), Gebremedhin et al. (2007), Algorithm 3.1
230228
"""
231229
function acyclic_coloring(
232-
g::AdjacencyGraph{T}, order::AbstractOrder, postprocessing::Bool
230+
g::AdjacencyGraph{T}, vertices_in_order::AbstractVector{<:Integer}, postprocessing::Bool
233231
) where {T<:Integer}
234232
# Initialize data structures
235233
nv = nb_vertices(g)
@@ -239,7 +237,6 @@ function acyclic_coloring(
239237
first_neighbor = fill((zero(T), zero(T), zero(T)), nv) # at first no neighbors have been encountered
240238
first_visit_to_tree = fill((zero(T), zero(T)), ne)
241239
forest = Forest{T}(ne)
242-
vertices_in_order = vertices(g, order)
243240

244241
for v in vertices_in_order
245242
for w in neighbors(g, v)
@@ -527,8 +524,8 @@ function TreeSet(
527524
# Positions of the first and last vertices in the current tree
528525
# Note: tree_edge_indices contains the positions of the first and last edges,
529526
# so we add to add an offset k-1 between edge indices and vertex indices
530-
first_vertex = tree_edge_indices[k] + (k-1)
531-
last_vertex = tree_edge_indices[k + 1] + (k-1)
527+
first_vertex = tree_edge_indices[k] + (k - 1)
528+
last_vertex = tree_edge_indices[k + 1] + (k - 1)
532529

533530
# compute the degree of each vertex in the tree
534531
for index_vertex in first_vertex:last_vertex

src/interface.jl

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -227,10 +227,10 @@ function _coloring(
227227
decompression_eltype::Type,
228228
symmetric_pattern::Bool,
229229
)
230-
bg = BipartiteGraph(
231-
A; symmetric_pattern=symmetric_pattern || A isa Union{Symmetric,Hermitian}
232-
)
233-
color = partial_distance2_coloring(bg, Val(2), algo.order)
230+
symmetric_pattern = symmetric_pattern || A isa Union{Symmetric,Hermitian}
231+
bg = BipartiteGraph(A; symmetric_pattern)
232+
vertices_in_order = vertices(bg, Val(2), algo.order)
233+
color = partial_distance2_coloring(bg, Val(2), vertices_in_order)
234234
if speed_setting isa WithResult
235235
return ColumnColoringResult(A, bg, color)
236236
else
@@ -246,10 +246,10 @@ function _coloring(
246246
decompression_eltype::Type,
247247
symmetric_pattern::Bool,
248248
)
249-
bg = BipartiteGraph(
250-
A; symmetric_pattern=symmetric_pattern || A isa Union{Symmetric,Hermitian}
251-
)
252-
color = partial_distance2_coloring(bg, Val(1), algo.order)
249+
symmetric_pattern = symmetric_pattern || A isa Union{Symmetric,Hermitian}
250+
bg = BipartiteGraph(A; symmetric_pattern)
251+
vertices_in_order = vertices(bg, Val(1), algo.order)
252+
color = partial_distance2_coloring(bg, Val(1), vertices_in_order)
253253
if speed_setting isa WithResult
254254
return RowColoringResult(A, bg, color)
255255
else
@@ -266,7 +266,8 @@ function _coloring(
266266
symmetric_pattern::Bool,
267267
)
268268
ag = AdjacencyGraph(A; has_diagonal=true)
269-
color, star_set = star_coloring(ag, algo.order, algo.postprocessing)
269+
vertices_in_order = vertices(ag, algo.order)
270+
color, star_set = star_coloring(ag, vertices_in_order, algo.postprocessing)
270271
if speed_setting isa WithResult
271272
return StarSetColoringResult(A, ag, color, star_set)
272273
else
@@ -283,7 +284,8 @@ function _coloring(
283284
symmetric_pattern::Bool,
284285
) where {R}
285286
ag = AdjacencyGraph(A; has_diagonal=true)
286-
color, tree_set = acyclic_coloring(ag, algo.order, algo.postprocessing)
287+
vertices_in_order = vertices(ag, algo.order)
288+
color, tree_set = acyclic_coloring(ag, vertices_in_order, algo.postprocessing)
287289
if speed_setting isa WithResult
288290
return TreeSetColoringResult(A, ag, color, tree_set, R)
289291
else
@@ -301,7 +303,8 @@ function _coloring(
301303
) where {R}
302304
A_and_Aᵀ, edge_to_index = bidirectional_pattern(A; symmetric_pattern)
303305
ag = AdjacencyGraph(A_and_Aᵀ, edge_to_index; has_diagonal=false)
304-
color, star_set = star_coloring(ag, algo.order, algo.postprocessing)
306+
vertices_in_order = vertices(ag, algo.order)
307+
color, star_set = star_coloring(ag, vertices_in_order, algo.postprocessing)
305308
if speed_setting isa WithResult
306309
symmetric_result = StarSetColoringResult(A_and_Aᵀ, ag, color, star_set)
307310
return BicoloringResult(A, ag, symmetric_result, R)
@@ -323,7 +326,8 @@ function _coloring(
323326
) where {R}
324327
A_and_Aᵀ, edge_to_index = bidirectional_pattern(A; symmetric_pattern)
325328
ag = AdjacencyGraph(A_and_Aᵀ, edge_to_index; has_diagonal=false)
326-
color, tree_set = acyclic_coloring(ag, algo.order, algo.postprocessing)
329+
vertices_in_order = vertices(ag, algo.order)
330+
color, tree_set = acyclic_coloring(ag, vertices_in_order, algo.postprocessing)
327331
if speed_setting isa WithResult
328332
symmetric_result = TreeSetColoringResult(A_and_Aᵀ, ag, color, tree_set, R)
329333
return BicoloringResult(A, ag, symmetric_result, R)

test/suitesparse.jl

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ using Test
2020

2121
nbunique(x) = length(unique(x))
2222

23-
_N() = NaturalOrder()
24-
_LF() = LargestFirst()
25-
_SL() = SmallestLast(; reproduce_colpack=true)
26-
_ID() = IncidenceDegree(; reproduce_colpack=true)
27-
_DLF() = DynamicLargestFirst(; reproduce_colpack=true)
23+
_N(args...) = vertices(args..., NaturalOrder())
24+
_LF(args...) = vertices(args..., LargestFirst())
25+
_SL(args...) = vertices(args..., SmallestLast(; reproduce_colpack=true))
26+
_ID(args...) = vertices(args..., IncidenceDegree(; reproduce_colpack=true))
27+
_DLF(args...) = vertices(args..., DynamicLargestFirst(; reproduce_colpack=true))
2828

2929
## Distance-2 coloring
3030

@@ -49,13 +49,17 @@ colpack_table_6_7 = CSV.read(
4949
@test maximum_degree(bg, Val(2)) == row[:Δ2]
5050
end
5151
@testset "Natural" begin
52-
@test nbunique(partial_distance2_coloring(bg, Val(1), _N())) == row[:N1]
53-
@test nbunique(partial_distance2_coloring(bg, Val(2), _N())) == row[:N2]
52+
@test nbunique(partial_distance2_coloring(bg, Val(1), _N(bg, Val(1)))) ==
53+
row[:N1]
54+
@test nbunique(partial_distance2_coloring(bg, Val(2), _N(bg, Val(2)))) ==
55+
row[:N2]
5456
end
5557
yield()
5658
@testset "LargestFirst" begin
57-
@test nbunique(partial_distance2_coloring(bg, Val(1), _LF())) == row[:LF1]
58-
@test nbunique(partial_distance2_coloring(bg, Val(2), _LF())) == row[:LF2]
59+
@test nbunique(partial_distance2_coloring(bg, Val(1), _LF(bg, Val(1)))) ==
60+
row[:LF1]
61+
@test nbunique(partial_distance2_coloring(bg, Val(2), _LF(bg, Val(2)))) ==
62+
row[:LF2]
5963
end
6064
yield()
6165
if row[:name] == "af23560"
@@ -67,18 +71,24 @@ colpack_table_6_7 = CSV.read(
6771
continue
6872
end
6973
@testset "SmallestLast" begin
70-
@test nbunique(partial_distance2_coloring(bg, Val(1), _SL())) == row[:SL1]
71-
@test nbunique(partial_distance2_coloring(bg, Val(2), _SL())) == row[:SL2]
74+
@test nbunique(partial_distance2_coloring(bg, Val(1), _SL(bg, Val(1)))) ==
75+
row[:SL1]
76+
@test nbunique(partial_distance2_coloring(bg, Val(2), _SL(bg, Val(2)))) ==
77+
row[:SL2]
7278
end
7379
yield()
7480
@testset "IncidenceDegree" begin
75-
@test nbunique(partial_distance2_coloring(bg, Val(1), _ID())) == row[:ID1]
76-
@test nbunique(partial_distance2_coloring(bg, Val(2), _ID())) == row[:ID2]
81+
@test nbunique(partial_distance2_coloring(bg, Val(1), _ID(bg, Val(1)))) ==
82+
row[:ID1]
83+
@test nbunique(partial_distance2_coloring(bg, Val(2), _ID(bg, Val(2)))) ==
84+
row[:ID2]
7785
end
7886
yield()
7987
@testset "DynamicLargestFirst" begin
80-
@test nbunique(partial_distance2_coloring(bg, Val(1), _DLF())) == row[:DLF1]
81-
@test nbunique(partial_distance2_coloring(bg, Val(2), _DLF())) == row[:DLF2]
88+
@test nbunique(partial_distance2_coloring(bg, Val(1), _DLF(bg, Val(1)))) ==
89+
row[:DLF1]
90+
@test nbunique(partial_distance2_coloring(bg, Val(2), _DLF(bg, Val(2)))) ==
91+
row[:DLF2]
8292
end
8393
yield()
8494
end
@@ -105,7 +115,8 @@ what_table_31_32 = CSV.read(
105115
@test maximum_degree(bg, Val(1)) == row[:ρmax]
106116
@test minimum_degree(bg, Val(2)) == row[:κmin]
107117
@test maximum_degree(bg, Val(2)) == row[:κmax]
108-
color_Nb = partial_distance2_coloring(bg, Val(2), NaturalOrder())
118+
vertices_in_order = vertices(bg, Val(2), NaturalOrder())
119+
color_Nb = partial_distance2_coloring(bg, Val(2), vertices_in_order)
109120
if length(unique(color_Nb)) == row[:K]
110121
@test length(unique(color_Nb)) == row[:K]
111122
else
@@ -133,7 +144,8 @@ what_table_41_42 = CSV.read(
133144
@test maximum_degree(ag) == row[]
134145
@test minimum_degree(ag) == row[]
135146
postprocessing = false
136-
color_N, _ = star_coloring(ag, NaturalOrder(), postprocessing)
147+
vertices_in_order = vertices(ag, NaturalOrder())
148+
color_N, _ = star_coloring(ag, vertices_in_order, postprocessing)
137149
@test_skip row[:KS1] <= length(unique(color_N)) <= row[:KS2] # TODO: find better
138150
yield()
139151
end

0 commit comments

Comments
 (0)