Skip to content

Commit d774220

Browse files
amontoisongdalle
andauthored
Optimize acyclic_coloring (#52)
* Optimize acyclic_coloring * Remove nvertices and nedges --------- Co-authored-by: Guillaume Dalle <22795598+gdalle@users.noreply.github.com>
1 parent 5008832 commit d774220

1 file changed

Lines changed: 32 additions & 40 deletions

File tree

src/coloring.jl

Lines changed: 32 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,11 @@ The vertices are colored in a greedy fashion, following the `order` supplied.
7676
"""
7777
function star_coloring(g::Graph, order::AbstractOrder)
7878
# Initialize data structures
79-
nvertices = length(g)
80-
color = zeros(Int, nvertices)
81-
forbidden_colors = zeros(Int, nvertices)
82-
first_neighbor = fill((0, 0), nvertices) # at first no neighbors have been encountered
83-
treated = zeros(Int, nvertices)
79+
nv = length(g)
80+
color = zeros(Int, nv)
81+
forbidden_colors = zeros(Int, nv)
82+
first_neighbor = fill((0, 0), nv) # at first no neighbors have been encountered
83+
treated = zeros(Int, nv)
8484
star = Dict{Tuple{Int,Int},Int}()
8585
hub = Int[]
8686
vertices_in_order = vertices(g, order)
@@ -129,7 +129,7 @@ Encode a set of 2-colored stars resulting from the [`star_coloring`](@ref) algor
129129
$TYPEDFIELDS
130130
"""
131131
struct StarSet
132-
"a mapping from edges (pair of vertices) their to star index"
132+
"a mapping from edges (pair of vertices) to their star index"
133133
star::Dict{Tuple{Int,Int},Int}
134134
"a mapping from star indices to their hub (the hub is `0` if the star only contains one edge)"
135135
hub::Vector{Int}
@@ -280,14 +280,14 @@ The vertices are colored in a greedy fashion, following the `order` supplied.
280280
"""
281281
function acyclic_coloring(g::Graph, order::AbstractOrder)
282282
# Initialize data structures
283-
nvertices = length(g)
284-
color = zeros(Int, nvertices)
285-
forbidden_colors = zeros(Int, nvertices)
286-
first_neighbor = fill((0, 0), nvertices) # at first no neighbors have been encountered
287-
first_visit_to_tree = fill((0, 0), nnz(g)) # Could we use less than nnz(g) values?
288-
disjoint_sets = DisjointSets{Tuple{Int,Int}}()
283+
nv = length(g)
284+
ne = nnz(g) ÷ 2 # symmetric sparse matrix with empty diagonal
285+
color = zeros(Int, nv)
286+
forbidden_colors = zeros(Int, nv)
287+
first_neighbor = fill((0, 0), nv) # at first no neighbors have been encountered
288+
first_visit_to_tree = fill((0, 0), ne)
289+
forest = DisjointSets{Tuple{Int,Int}}()
289290
vertices_in_order = vertices(g, order)
290-
parent = Int[] # Could be a vector of Bool
291291

292292
for v in vertices_in_order
293293
for w in neighbors(g, v)
@@ -300,7 +300,7 @@ function acyclic_coloring(g::Graph, order::AbstractOrder)
300300
iszero(color[x]) && continue
301301
if forbidden_colors[color[x]] != v
302302
_prevent_cycle!(
303-
v, w, x, color, first_visit_to_tree, forbidden_colors, disjoint_sets
303+
v, w, x, color, first_visit_to_tree, forbidden_colors, forest
304304
)
305305
end
306306
end
@@ -313,19 +313,19 @@ function acyclic_coloring(g::Graph, order::AbstractOrder)
313313
end
314314
for w in neighbors(g, v) # grow two-colored stars around the vertex v
315315
iszero(color[w]) && continue
316-
_grow_star!(v, w, color, first_neighbor, disjoint_sets, parent)
316+
_grow_star!(v, w, color, first_neighbor, forest)
317317
end
318318
for w in neighbors(g, v)
319319
iszero(color[w]) && continue
320320
for x in neighbors(g, w)
321321
(x == v || iszero(color[x])) && continue
322322
if color[x] == color[v]
323-
_merge_trees!(v, w, x, disjoint_sets) # merge trees T₁ ∋ vw and T₂ ∋ wx if T₁ != T₂
323+
_merge_trees!(v, w, x, forest) # merge trees T₁ ∋ vw and T₂ ∋ wx if T₁ != T₂
324324
end
325325
end
326326
end
327327
end
328-
return color, TreeSet(disjoint_sets, parent)
328+
return color, TreeSet(forest)
329329
end
330330

331331
function _prevent_cycle!(
@@ -337,11 +337,11 @@ function _prevent_cycle!(
337337
# modified
338338
first_visit_to_tree::AbstractVector{<:Tuple},
339339
forbidden_colors::AbstractVector{<:Integer},
340-
disjoint_sets::DisjointSets{<:Tuple{Int,Int}},
340+
forest::DisjointSets{<:Tuple{Int,Int}},
341341
)
342342
wx = _sort(w, x)
343-
root = find_root!(disjoint_sets, wx) # edge wx belongs to the 2-colored tree T represented by edge "root"
344-
id = disjoint_sets.intmap[root] # ID of the representative edge "root" of a two-colored tree.
343+
root = find_root!(forest, wx) # edge wx belongs to the 2-colored tree represented by edge "root"
344+
id = forest.intmap[root] # ID of the representative edge "root" of a two-colored tree.
345345
(p, q) = first_visit_to_tree[id]
346346
if p != v # T is being visited from vertex v for the first time
347347
vw = _sort(v, w)
@@ -359,21 +359,19 @@ function _grow_star!(
359359
color::AbstractVector{<:Integer},
360360
# modified
361361
first_neighbor::AbstractVector{<:Tuple},
362-
disjoint_sets::DisjointSets{Tuple{Int,Int}},
363-
parent::Vector{Int},
362+
forest::DisjointSets{Tuple{Int,Int}},
364363
)
365364
vw = _sort(v, w)
366-
push!(disjoint_sets, vw) # Create a new tree T_{vw} consisting only of edge vw
367-
push!(parent, v) # the vertex v is the parent of the vertex w in tree T_{vw} -- parent[disjoint_sets.intmap[vw]] == v
365+
push!(forest, vw) # Create a new tree T_{vw} consisting only of edge vw
368366
(p, q) = first_neighbor[color[w]]
369367
if p != v # a neighbor of v with color[w] encountered for the first time
370368
first_neighbor[color[w]] = (v, w)
371369
else # merge T_{vw} with a two-colored star being grown around v
372370
vw = _sort(v, w)
373371
pq = _sort(p, q)
374-
root1 = find_root!(disjoint_sets, vw)
375-
root2 = find_root!(disjoint_sets, pq)
376-
root_union!(disjoint_sets, root1, root2)
372+
root1 = find_root!(forest, vw)
373+
root2 = find_root!(forest, pq)
374+
root_union!(forest, root1, root2)
377375
end
378376
return nothing
379377
end
@@ -384,34 +382,28 @@ function _merge_trees!(
384382
w::Integer,
385383
x::Integer,
386384
# modified
387-
disjoint_sets::DisjointSets{Tuple{Int,Int}},
385+
forest::DisjointSets{Tuple{Int,Int}},
388386
)
389387
vw = _sort(v, w)
390388
wx = _sort(w, x)
391-
root1 = find_root!(disjoint_sets, vw)
392-
root2 = find_root!(disjoint_sets, wx)
389+
root1 = find_root!(forest, vw)
390+
root2 = find_root!(forest, wx)
393391
if root1 != root2
394-
root_union!(disjoint_sets, root1, root2)
392+
root_union!(forest, root1, root2)
395393
end
396394
return nothing
397395
end
398396

399397
"""
400398
TreeSet
401399
402-
Encode a set of 2-colored trees resulting from the acyclic coloring algorithm.
400+
Encode a set of 2-colored trees resulting from the [`acyclic_coloring`](@ref) algorithm.
403401
404402
# Fields
405403
406404
$TYPEDFIELDS
407-
408-
# References
409-
410-
> [_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
411405
"""
412406
struct TreeSet
413-
"set of 2-colored trees"
414-
disjoint_sets::DisjointSets{Tuple{Int,Int}}
415-
"???" # TODO: fill this
416-
parent::Vector{Int}
407+
"a forest of two-colored trees"
408+
forest::DisjointSets{Tuple{Int,Int}}
417409
end

0 commit comments

Comments
 (0)