Skip to content

Commit e2c3525

Browse files
committed
Detect stars in the forest for acyclic coloring
1 parent d854aa4 commit e2c3525

3 files changed

Lines changed: 69 additions & 16 deletions

File tree

src/coloring.jl

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,7 @@ $TYPEDFIELDS
434434
struct TreeSet
435435
vertices_by_tree::Vector{Vector{Int}}
436436
reverse_bfs_orders::Vector{Vector{Tuple{Int,Int}}}
437+
is_star::Vector{Bool}
437438
end
438439

439440
function TreeSet(forest::DisjointSets{Tuple{Int,Int}}, nvertices::Int)
@@ -497,9 +498,19 @@ function TreeSet(forest::DisjointSets{Tuple{Int,Int}}, nvertices::Int)
497498
# Create a queue with a fixed size nvmax
498499
queue = Vector{Int}(undef, nvmax)
499500

501+
# Specify if each tree in the forest is a star,
502+
# meaning that one vertex is directly connected to all other vertices in the tree
503+
is_star = Vector{Bool}(undef, ntrees)
504+
500505
for k in 1:ntrees
501506
tree = trees[k]
502507

508+
# Boolean indicating whether the current tree is a star (a single central vertex connected to all others)
509+
bool_star = true
510+
511+
# Candidate hub vertex if the current tree is a star
512+
virtual_hub = 0
513+
503514
# Initialize the queue to store the leaves
504515
queue_start = 1
505516
queue_end = 0
@@ -529,6 +540,18 @@ function TreeSet(forest::DisjointSets{Tuple{Int,Int}}, nvertices::Int)
529540
# (leaf, neighbor) represents the next edge to visit during decompression
530541
push!(reverse_bfs_orders[k], (leaf, neighbor))
531542

543+
if bool_star
544+
# Initialize the potential hub of the star with the first parent of a leaf
545+
if virtual_hub == 0
546+
virtual_hub = neighbor
547+
else
548+
# Verify if the tree still qualifies as a star
549+
if virtual_hub != neighbor
550+
bool_star = false
551+
end
552+
end
553+
end
554+
532555
# reduce the degree of the neighbor
533556
degrees[neighbor] -= 1
534557

@@ -540,9 +563,12 @@ function TreeSet(forest::DisjointSets{Tuple{Int,Int}}, nvertices::Int)
540563
end
541564
end
542565
end
566+
567+
# Specify if the tree is a star or not
568+
is_star[k] = bool_star
543569
end
544570

545-
return TreeSet(vertices_by_tree, reverse_bfs_orders)
571+
return TreeSet(vertices_by_tree, reverse_bfs_orders, is_star)
546572
end
547573

548574
## Postprocessing, mirrors decompression code
@@ -599,17 +625,23 @@ function postprocess!(
599625
end
600626
else
601627
# only the colors of non-leaf vertices are used
602-
(; reverse_bfs_orders) = star_or_tree_set
628+
(; reverse_bfs_orders, is_star) = star_or_tree_set
603629
nb_trivial_trees = 0
604630

605631
# Iterate through all non-trivial trees
606632
for k in eachindex(reverse_bfs_orders)
607633
reverse_bfs_order = reverse_bfs_orders[k]
608-
# Check if we have more than one edge in the tree
634+
# Check if we have more than one edge in the tree (non-trivial tree)
609635
if length(reverse_bfs_order) > 1
610-
# TODO: Optimize by avoiding iteration over all edges
611-
# Only one edge is needed if we know if it is a normal tree or a star
612-
for (i, j) in reverse_bfs_order
636+
# Determine if the tree is a star
637+
if is_star[k]
638+
# It is a non-trivial star and only the color of the hub is needed
639+
(_, hub) = reverse_bfs_order[end]
640+
color_used[color[hub]] = true
641+
else
642+
# It is not a star and both colors are needed during the decompression
643+
(i, j) = reverse_bfs_order[1]
644+
color_used[color[i]] = true
613645
color_used[color[j]] = true
614646
end
615647
else

src/decompression.jl

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ end
505505
function decompress!(
506506
A::AbstractMatrix, B::AbstractMatrix, result::TreeSetColoringResult, uplo::Symbol=:F
507507
)
508-
(; color, vertices_by_tree, reverse_bfs_orders, buffer) = result
508+
(; color, vertices_by_tree, reverse_bfs_orders, is_star, buffer) = result
509509
S = result.ag.S
510510
uplo == :F && check_same_pattern(A, S)
511511
R = eltype(A)
@@ -526,13 +526,22 @@ function decompress!(
526526

527527
# Recover the off-diagonal coefficients of A
528528
for k in eachindex(vertices_by_tree, reverse_bfs_orders)
529-
for vertex in vertices_by_tree[k]
530-
buffer_right_type[vertex] = zero(R)
529+
# We need the buffer only when the tree is not a star (trivial or non-trivial)
530+
if !is_star[k]
531+
for vertex in vertices_by_tree[k]
532+
buffer_right_type[vertex] = zero(R)
533+
end
531534
end
532535

533536
for (i, j) in reverse_bfs_orders[k]
534-
val = B[i, color[j]] - buffer_right_type[i]
535-
buffer_right_type[j] = buffer_right_type[j] + val
537+
if !is_star[k]
538+
# the tree is not a star
539+
val = B[i, color[j]] - buffer_right_type[i]
540+
buffer_right_type[j] = buffer_right_type[j] + val
541+
else
542+
# the tree is a trivial or non-trivial star
543+
val = B[i, color[j]]
544+
end
536545
if in_triangle(i, j, uplo)
537546
A[i, j] = val
538547
end
@@ -554,6 +563,7 @@ function decompress!(
554563
color,
555564
vertices_by_tree,
556565
reverse_bfs_orders,
566+
is_star,
557567
diagonal_indices,
558568
diagonal_nzind,
559569
lower_triangle_offsets,
@@ -596,14 +606,23 @@ function decompress!(
596606

597607
# Recover the off-diagonal coefficients of A
598608
for k in eachindex(vertices_by_tree, reverse_bfs_orders)
599-
for vertex in vertices_by_tree[k]
600-
buffer_right_type[vertex] = zero(R)
609+
# We need the buffer only when the tree is not a star (trivial or non-trivial)
610+
if !is_star[k]
611+
for vertex in vertices_by_tree[k]
612+
buffer_right_type[vertex] = zero(R)
613+
end
601614
end
602615

603616
for (i, j) in reverse_bfs_orders[k]
604617
counter += 1
605-
val = B[i, color[j]] - buffer_right_type[i]
606-
buffer_right_type[j] = buffer_right_type[j] + val
618+
if !is_star[k]
619+
# the tree is not a star
620+
val = B[i, color[j]] - buffer_right_type[i]
621+
buffer_right_type[j] = buffer_right_type[j] + val
622+
else
623+
# the tree is a trivial or non-trivial star
624+
val = B[i, color[j]]
625+
end
607626

608627
#! format: off
609628
# A[i,j] is in the lower triangular part of A

src/result.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ struct TreeSetColoringResult{M<:AbstractMatrix,G<:AdjacencyGraph,V,R} <:
280280
group::V
281281
vertices_by_tree::Vector{Vector{Int}}
282282
reverse_bfs_orders::Vector{Vector{Tuple{Int,Int}}}
283+
is_star::Vector{Bool}
283284
diagonal_indices::Vector{Int}
284285
diagonal_nzind::Vector{Int}
285286
lower_triangle_offsets::Vector{Int}
@@ -294,7 +295,7 @@ function TreeSetColoringResult(
294295
tree_set::TreeSet,
295296
decompression_eltype::Type{R},
296297
) where {R}
297-
(; vertices_by_tree, reverse_bfs_orders) = tree_set
298+
(; vertices_by_tree, reverse_bfs_orders, is_star) = tree_set
298299
S = ag.S
299300
nvertices = length(color)
300301
group = group_by_color(color)
@@ -369,6 +370,7 @@ function TreeSetColoringResult(
369370
group,
370371
vertices_by_tree,
371372
reverse_bfs_orders,
373+
is_star,
372374
diagonal_indices,
373375
diagonal_nzind,
374376
lower_triangle_offsets,

0 commit comments

Comments
 (0)