Skip to content

Commit 5a8b14c

Browse files
committed
Detect stars in the forest for acyclic coloring
1 parent 2fba12e commit 5a8b14c

3 files changed

Lines changed: 69 additions & 18 deletions

File tree

src/coloring.jl

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,7 @@ $TYPEDFIELDS
435435
"""
436436
struct TreeSet
437437
reverse_bfs_orders::Vector{Vector{Tuple{Int,Int}}}
438+
is_star::Vector{Bool}
438439
end
439440

440441
function TreeSet(forest::DisjointSets{Tuple{Int,Int}}, nvertices::Int)
@@ -499,9 +500,19 @@ function TreeSet(forest::DisjointSets{Tuple{Int,Int}}, nvertices::Int)
499500
# Create a queue with a fixed size nvmax
500501
queue = Vector{Int}(undef, nvmax)
501502

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

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

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

@@ -542,9 +565,12 @@ function TreeSet(forest::DisjointSets{Tuple{Int,Int}}, nvertices::Int)
542565
end
543566
end
544567
end
568+
569+
# Specify if the tree is a star or not
570+
is_star[k] = bool_star
545571
end
546572

547-
return TreeSet(reverse_bfs_orders)
573+
return TreeSet(reverse_bfs_orders, is_star)
548574
end
549575

550576
## Postprocessing, mirrors decompression code
@@ -605,17 +631,23 @@ function postprocess!(
605631
end
606632
else
607633
# only the colors of non-leaf vertices are used
608-
(; reverse_bfs_orders) = star_or_tree_set
634+
(; reverse_bfs_orders, is_star) = star_or_tree_set
609635
nb_trivial_trees = 0
610636

611637
# Iterate through all non-trivial trees
612638
for k in eachindex(reverse_bfs_orders)
613639
reverse_bfs_order = reverse_bfs_orders[k]
614-
# Check if we have more than one edge in the tree
640+
# Check if we have more than one edge in the tree (non-trivial tree)
615641
if length(reverse_bfs_order) > 1
616-
# TODO: Optimize by avoiding iteration over all edges
617-
# Only one edge is needed if we know if it is a normal tree or a star
618-
for (i, j) in reverse_bfs_order
642+
# Determine if the tree is a star
643+
if is_star[k]
644+
# It is a non-trivial star and only the color of the hub is needed
645+
(_, hub) = reverse_bfs_order[end]
646+
color_used[color[hub]] = true
647+
else
648+
# It is not a star and both colors are needed during the decompression
649+
(i, j) = reverse_bfs_order[1]
650+
color_used[color[i]] = true
619651
color_used[color[j]] = true
620652
end
621653
else

src/decompression.jl

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ end
533533
function decompress!(
534534
A::AbstractMatrix, B::AbstractMatrix, result::TreeSetColoringResult, uplo::Symbol=:F
535535
)
536-
(; ag, color, reverse_bfs_orders, buffer) = result
536+
(; ag, color, reverse_bfs_orders, is_star, buffer) = result
537537
(; S) = ag
538538
uplo == :F && check_same_pattern(A, S)
539539
R = eltype(A)
@@ -556,17 +556,27 @@ function decompress!(
556556

557557
# Recover the off-diagonal coefficients of A
558558
for k in eachindex(reverse_bfs_orders)
559-
# Reset the buffer to zero for all vertices in a tree (except the root)
560-
for (vertex, _) in reverse_bfs_orders[k]
561-
buffer_right_type[vertex] = zero(R)
559+
# We need the buffer only when the tree is not a star (trivial or non-trivial)
560+
if !is_star[k]
561+
# Reset the buffer to zero for all vertices in a tree (except the root)
562+
for (vertex, _) in reverse_bfs_orders[k]
563+
buffer_right_type[vertex] = zero(R)
564+
end
565+
566+
# Reset the buffer to zero for the root vertex
567+
(_, root) = reverse_bfs_orders[k][end]
568+
buffer_right_type[root] = zero(R)
562569
end
563-
# Reset the buffer to zero for the root vertex
564-
(_, root) = reverse_bfs_orders[k][end]
565-
buffer_right_type[root] = zero(R)
566570

567571
for (i, j) in reverse_bfs_orders[k]
568-
val = B[i, color[j]] - buffer_right_type[i]
569-
buffer_right_type[j] = buffer_right_type[j] + val
572+
if !is_star[k]
573+
# the tree is not a star
574+
val = B[i, color[j]] - buffer_right_type[i]
575+
buffer_right_type[j] = buffer_right_type[j] + val
576+
else
577+
# the tree is a trivial or non-trivial star
578+
val = B[i, color[j]]
579+
end
570580
if in_triangle(i, j, uplo)
571581
A[i, j] = val
572582
end
@@ -588,6 +598,7 @@ function decompress!(
588598
ag,
589599
color,
590600
reverse_bfs_orders,
601+
is_star,
591602
diagonal_indices,
592603
diagonal_nzind,
593604
lower_triangle_offsets,
@@ -642,8 +653,14 @@ function decompress!(
642653

643654
for (i, j) in reverse_bfs_orders[k]
644655
counter += 1
645-
val = B[i, color[j]] - buffer_right_type[i]
646-
buffer_right_type[j] = buffer_right_type[j] + val
656+
if !is_star[k]
657+
# the tree is not a star
658+
val = B[i, color[j]] - buffer_right_type[i]
659+
buffer_right_type[j] = buffer_right_type[j] + val
660+
else
661+
# the tree is a trivial or non-trivial star
662+
val = B[i, color[j]]
663+
end
647664

648665
#! format: off
649666
# 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
@@ -279,6 +279,7 @@ struct TreeSetColoringResult{M<:AbstractMatrix,G<:AdjacencyGraph,V,R} <:
279279
color::Vector{Int}
280280
group::V
281281
reverse_bfs_orders::Vector{Vector{Tuple{Int,Int}}}
282+
is_star::Vector{Bool}
282283
diagonal_indices::Vector{Int}
283284
diagonal_nzind::Vector{Int}
284285
lower_triangle_offsets::Vector{Int}
@@ -293,7 +294,7 @@ function TreeSetColoringResult(
293294
tree_set::TreeSet,
294295
decompression_eltype::Type{R},
295296
) where {R}
296-
(; reverse_bfs_orders) = tree_set
297+
(; reverse_bfs_orders, is_star) = tree_set
297298
(; S) = ag
298299
nvertices = length(color)
299300
group = group_by_color(color)
@@ -369,6 +370,7 @@ function TreeSetColoringResult(
369370
color,
370371
group,
371372
reverse_bfs_orders,
373+
is_star,
372374
diagonal_indices,
373375
diagonal_nzind,
374376
lower_triangle_offsets,

0 commit comments

Comments
 (0)