@@ -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
0 commit comments