Skip to content

Commit 8a90816

Browse files
committed
Detect stars in the forest for acyclic coloring
1 parent 50f3f23 commit 8a90816

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
@@ -433,6 +433,7 @@ $TYPEDFIELDS
433433
"""
434434
struct TreeSet
435435
reverse_bfs_orders::Vector{Vector{Tuple{Int,Int}}}
436+
is_star::Vector{Bool}
436437
end
437438

438439
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(reverse_bfs_orders)
571+
return TreeSet(reverse_bfs_orders, is_star)
546572
end
547573

548574
## Postprocessing, mirrors decompression code
@@ -602,17 +628,23 @@ function postprocess!(
602628
end
603629
else
604630
# only the colors of non-leaf vertices are used
605-
(; reverse_bfs_orders) = star_or_tree_set
631+
(; reverse_bfs_orders, is_star) = star_or_tree_set
606632
nb_trivial_trees = 0
607633

608634
# Iterate through all non-trivial trees
609635
for k in eachindex(reverse_bfs_orders)
610636
reverse_bfs_order = reverse_bfs_orders[k]
611-
# Check if we have more than one edge in the tree
637+
# Check if we have more than one edge in the tree (non-trivial tree)
612638
if length(reverse_bfs_order) > 1
613-
# TODO: Optimize by avoiding iteration over all edges
614-
# Only one edge is needed if we know if it is a normal tree or a star
615-
for (i, j) in reverse_bfs_order
639+
# Determine if the tree is a star
640+
if is_star[k]
641+
# It is a non-trivial star and only the color of the hub is needed
642+
(_, hub) = reverse_bfs_order[end]
643+
color_used[color[hub]] = true
644+
else
645+
# It is not a star and both colors are needed during the decompression
646+
(i, j) = reverse_bfs_order[1]
647+
color_used[color[i]] = true
616648
color_used[color[j]] = true
617649
end
618650
else

src/decompression.jl

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ end
517517
function decompress!(
518518
A::AbstractMatrix, B::AbstractMatrix, result::TreeSetColoringResult, uplo::Symbol=:F
519519
)
520-
(; ag, color, reverse_bfs_orders, buffer) = result
520+
(; ag, color, reverse_bfs_orders, is_star, buffer) = result
521521
(; S) = ag
522522
uplo == :F && check_same_pattern(A, S)
523523
R = eltype(A)
@@ -540,17 +540,27 @@ function decompress!(
540540

541541
# Recover the off-diagonal coefficients of A
542542
for k in eachindex(reverse_bfs_orders)
543-
# Reset the buffer to zero for all vertices in a tree (except the root)
544-
for (vertex, _) in reverse_bfs_orders[k]
545-
buffer_right_type[vertex] = zero(R)
543+
# We need the buffer only when the tree is not a star (trivial or non-trivial)
544+
if !is_star[k]
545+
# Reset the buffer to zero for all vertices in a tree (except the root)
546+
for (vertex, _) in reverse_bfs_orders[k]
547+
buffer_right_type[vertex] = zero(R)
548+
end
549+
550+
# Reset the buffer to zero for the root vertex
551+
(_, root) = reverse_bfs_orders[k][end]
552+
buffer_right_type[root] = zero(R)
546553
end
547-
# Reset the buffer to zero for the root vertex
548-
(_, root) = reverse_bfs_orders[k][end]
549-
buffer_right_type[root] = zero(R)
550554

551555
for (i, j) in reverse_bfs_orders[k]
552-
val = B[i, color[j]] - buffer_right_type[i]
553-
buffer_right_type[j] = buffer_right_type[j] + val
556+
if !is_star[k]
557+
# the tree is not a star
558+
val = B[i, color[j]] - buffer_right_type[i]
559+
buffer_right_type[j] = buffer_right_type[j] + val
560+
else
561+
# the tree is a trivial or non-trivial star
562+
val = B[i, color[j]]
563+
end
554564
if in_triangle(i, j, uplo)
555565
A[i, j] = val
556566
end
@@ -572,6 +582,7 @@ function decompress!(
572582
ag,
573583
color,
574584
reverse_bfs_orders,
585+
is_star,
575586
diagonal_indices,
576587
diagonal_nzind,
577588
lower_triangle_offsets,
@@ -626,8 +637,14 @@ function decompress!(
626637

627638
for (i, j) in reverse_bfs_orders[k]
628639
counter += 1
629-
val = B[i, color[j]] - buffer_right_type[i]
630-
buffer_right_type[j] = buffer_right_type[j] + val
640+
if !is_star[k]
641+
# the tree is not a star
642+
val = B[i, color[j]] - buffer_right_type[i]
643+
buffer_right_type[j] = buffer_right_type[j] + val
644+
else
645+
# the tree is a trivial or non-trivial star
646+
val = B[i, color[j]]
647+
end
631648

632649
#! format: off
633650
# 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)