Skip to content

Commit 4ed7621

Browse files
committed
Remove the dictionaries in TreeSet
1 parent ee8bb7a commit 4ed7621

2 files changed

Lines changed: 107 additions & 42 deletions

File tree

src/coloring.jl

Lines changed: 102 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ function acyclic_coloring(
293293

294294
buffer = forbidden_colors
295295
reverse_bfs_orders = first_visit_to_tree
296-
tree_set = TreeSet(g, forest, buffer, reverse_bfs_orders)
296+
tree_set = TreeSet(g, forest, buffer, reverse_bfs_orders, ne)
297297
if postprocessing
298298
# Reuse the vector forbidden_colors to compute offsets during post-processing
299299
offsets = forbidden_colors
@@ -384,6 +384,7 @@ function TreeSet(
384384
forest::Forest{T},
385385
buffer::AbstractVector{T},
386386
reverse_bfs_orders::Vector{Tuple{T,T}},
387+
ne::Integer,
387388
) where {T}
388389
S = pattern(g)
389390
edge_to_index = edge_indices(g)
@@ -398,70 +399,118 @@ function TreeSet(
398399
# Contains the number of edges per tree
399400
num_edges_per_tree = zeros(T, nt)
400401

401-
# vector of dictionaries where each dictionary stores the neighbors of each vertex in a tree
402-
trees = [Dict{T,Vector{T}}() for i in 1:nt]
403-
404402
# current number of roots found
405403
nr = 0
406404

405+
# determine the number of edges for each tree and map each root to a tree index
406+
for index_edge in 1:ne
407+
root = find_root!(forest, index_edge)
408+
409+
# create a mapping between roots and tree indices
410+
if iszero(root_to_tree[root])
411+
nr += 1
412+
root_to_tree[root] = nr
413+
end
414+
415+
# index of the tree that contains this edge
416+
index_tree = root_to_tree[root]
417+
418+
# update the number of edges in the tree that contains this edge
419+
num_edges_per_tree[index_tree] += 1
420+
end
421+
422+
found_in_tree = Vector{Bool}(undef, nt)
423+
colptr_tree = zeros(T, ne + nt + 1)
424+
vertices1 = Vector{T}(undef, ne + nt)
425+
vertices2 = Vector{T}(undef, 2 * ne)
426+
427+
pos_vertices1 = Vector{T}(undef, nt)
428+
pos_vertices2 = Vector{T}(undef, nt)
429+
if nt > 0
430+
pos_vertices1[1] = zero(T)
431+
pos_vertices2[1] = zero(T)
432+
end
433+
for k in 2:nt
434+
pos_vertices1[k] = pos_vertices1[k - 1] + num_edges_per_tree[k - 1] + 1
435+
pos_vertices2[k] = pos_vertices2[k - 1] + 2 * num_edges_per_tree[k - 1]
436+
end
437+
438+
verbose = false
439+
407440
rvS = rowvals(S)
408441
for j in axes(S, 2)
442+
# Use this vector to determine if j appears in the trees
443+
found_in_tree .= false
409444
for pos in nzrange(S, j)
410445
i = rvS[pos]
411-
if i > j
446+
if i != j
412447
index_ij = edge_to_index[pos]
413-
root = find_root!(forest, index_ij)
414-
415-
# Update roots
416-
if iszero(root_to_tree[root])
417-
nr += 1
418-
root_to_tree[root] = nr
419-
end
420-
421-
# index of the tree T that contains this edge
448+
# we don't need to use find_root! because the paths are compressed
449+
root = forest.parents[index_ij]
422450
index_tree = root_to_tree[root]
423-
num_edges_per_tree[index_tree] += 1
424-
425-
# Update the neighbors of i in the tree T
426-
if !haskey(trees[index_tree], i)
427-
trees[index_tree][i] = [j]
428-
else
429-
push!(trees[index_tree][i], j)
430-
end
431-
432-
# Update the neighbors of j in the tree T
433-
if !haskey(trees[index_tree], j)
434-
trees[index_tree][j] = [i]
435-
else
436-
push!(trees[index_tree][j], i)
451+
t = index_tree
452+
verbose && println("t: $t")
453+
if !found_in_tree[index_tree]
454+
# j appears for the first time in the current tree
455+
found_in_tree[index_tree] = true
456+
pos_vertices1[index_tree] += 1
457+
# add j in the list of vertices of the current tree
458+
p = pos_vertices1[index_tree]
459+
verbose && println("pos_vertices1[$t]: $p")
460+
verbose && println("vertices1[$p]: $j")
461+
vertices1[p] = j
437462
end
463+
# increase the number of neighbors for j in the current tree
464+
p = pos_vertices1[index_tree]
465+
colptr_tree[p] += 1
466+
verbose && println("colptr_tree[$p]: $(colptr_tree[p])")
467+
# increase the position of the visited neighbors in the current tree
468+
pos_vertices2[index_tree] += 1
469+
q = pos_vertices2[index_tree]
470+
vertices2[q] = i
471+
verbose && println("pos_vertices2[$t]: $q")
472+
verbose && println("vertices2[$q]: $i")
438473
end
439474
end
440475
end
441476

477+
# Update tree_colptr
478+
for k in (ne + nt):-1:1
479+
colptr_tree[k + 1] = colptr_tree[k]
480+
end
481+
colptr_tree[1] = 1
482+
for k in 2:(ne + nt + 1)
483+
colptr_tree[k] += colptr_tree[k - 1]
484+
end
485+
442486
# degrees is a vector of integers that stores the degree of each vertex in a tree
443487
degrees = buffer
488+
mapping = Vector{T}(undef, nv)
489+
fill!(mapping, -1)
444490

445-
# nvmax is the number of vertices of the biggest tree in the forest
446-
nvmax = 0
447-
for k in 1:nt
448-
nb_vertices_tree = length(trees[k])
449-
nvmax = max(nvmax, nb_vertices_tree)
450-
end
491+
# nvmax is the number of vertices in the largest tree of the forest
492+
# In a tree, the number of vertices is equal to the number of edges plus one
493+
nvmax = maximum(num_edges_per_tree) + 1
451494

452495
# Create a queue with a fixed size nvmax
453496
queue = Vector{T}(undef, nvmax)
454497

455498
# Specify if each tree in the forest is a star,
456499
# meaning that one vertex is directly connected to all other vertices in the tree
457-
is_star = Vector{Bool}(undef, nt)
500+
is_star = found_in_tree
458501

459502
# Number of edges treated
460503
num_edges_treated = zero(T)
461504

505+
first = 1
462506
# reverse_bfs_orders contains the reverse breadth first (BFS) traversal order for each tree in the forest
463507
for k in 1:nt
464-
tree = trees[k]
508+
verbose && println("Arbre: $k")
509+
verbose && println("First index: $first")
510+
last = first + num_edges_per_tree[k]
511+
verbose && println("Last index: $last")
512+
verbose && println("ne: $(num_edges_per_tree[k])")
513+
verbose && println("nv: $(num_edges_per_tree[k] + 1)")
465514

466515
# Boolean indicating whether the current tree is a star (a single central vertex connected to all others)
467516
bool_star = true
@@ -474,9 +523,15 @@ function TreeSet(
474523
queue_end = 0
475524

476525
# compute the degree of each vertex in the tree
477-
for (vertex, neighbors) in tree
478-
degree = length(neighbors)
526+
for pos1 in first:last
527+
vertex = vertices1[pos1]
528+
degree = colptr_tree[pos1 + 1] - colptr_tree[pos1]
479529
degrees[vertex] = degree
530+
verbose && println("vertices1[$pos1] = $vertex")
531+
verbose && println("mapping[$vertex] = $pos1")
532+
533+
# store a reverse mapping
534+
mapping[vertex] = pos1
480535

481536
# the vertex is a leaf
482537
if degree == 1
@@ -493,7 +548,13 @@ function TreeSet(
493548
# Mark the vertex as removed
494549
degrees[leaf] = 0
495550

496-
for neighbor in tree[leaf]
551+
mleaf = mapping[leaf]
552+
verbose && println("mleaf = $mleaf")
553+
for pos2 in colptr_tree[mleaf]:(colptr_tree[mleaf + 1] - 1)
554+
verbose && println("pos2 = $pos2")
555+
neighbor = vertices2[pos2]
556+
verbose && println("vertices2[$pos2] = $neighbor")
557+
497558
# Check if neighbor is the parent of the leaf or if it was a child before the tree was pruned
498559
if degrees[neighbor] != 0
499560
# (leaf, neighbor) represents the next edge to visit during decompression
@@ -525,6 +586,8 @@ function TreeSet(
525586
end
526587
end
527588

589+
first = last + 1
590+
528591
# Specify if the tree is a star or not
529592
is_star[k] = bool_star
530593
end

src/forest.jl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,21 @@ function Forest{T}(n::Integer) where {T<:Integer}
2525
return Forest{T}(num_trees, parents, ranks)
2626
end
2727

28-
function _find_root!(parents::Vector{T}, index_edge::T) where {T<:Integer}
28+
function _find_root!(parents::Vector{<:Integer}, index_edge::Integer)
2929
p = parents[index_edge]
3030
if parents[p] != p
3131
parents[index_edge] = p = _find_root!(parents, p)
3232
end
3333
return p
3434
end
3535

36-
function find_root!(forest::Forest{T}, index_edge::T) where {T<:Integer}
36+
function find_root!(forest::Forest, index_edge::Integer)
3737
return _find_root!(forest.parents, index_edge)
3838
end
3939

40-
function root_union!(forest::Forest{T}, index_edge1::T, index_edge2::T) where {T<:Integer}
40+
function root_union!(
41+
forest::Forest{<:Integer}, index_edge1::Integer, index_edge2::Integer
42+
) where {T<:Integer}
4143
parents = forest.parents
4244
rks = forest.ranks
4345
rank1 = rks[index_edge1]

0 commit comments

Comments
 (0)