@@ -608,7 +608,8 @@ function postprocess!(
608608 color:: AbstractVector{<:Integer} ,
609609 star_or_tree_set:: Union{StarSet,TreeSet} ,
610610 g:: AdjacencyGraph ,
611- offsets:: AbstractVector{<:Integer} ,
611+ offsets:: AbstractVector{<:Integer} ;
612+ neutralized_first:: Symbol = :rows ,
612613)
613614 S = pattern (g)
614615 edge_to_index = edge_indices (g)
@@ -641,6 +642,7 @@ function postprocess!(
641642 end
642643
643644 # Process the trivial stars (if any)
645+ nb_nunknown_hubs = nb_trivial_stars
644646 if nb_trivial_stars > 0
645647 rvS = rowvals (S)
646648 for j in axes (S, 2 )
@@ -653,12 +655,47 @@ function postprocess!(
653655 if h < 0
654656 h = abs (h)
655657 spoke = h == j ? i : j
656- if color_used[color[spoke]]
657- # Switch the hub and the spoke to possibly avoid adding one more used color
658- hub[s] = spoke
658+ if color_used[color[h]]
659+ # The current hub of this trivial star is already a hub in a non-trivial star
660+ hub[s] = h
661+ nb_unknown_hubs -= 1
659662 else
660- # Keep the current hub
661- color_used[color[h]] = true
663+ if color_used[color[spoke]]
664+ # The current spoke of this trivial star is also a hub in a non-trivial star
665+ # Switch the hub and the spoke to avoid adding one more used color
666+ hub[s] = spoke
667+ nb_unknown_hubs -= 1
668+ end
669+ end
670+ end
671+ end
672+ end
673+ end
674+ end
675+ # Only trivial stars where both vertices can be promoted as hub are remaining.
676+ # In the context of bicoloring, if we want to minimize the number of row colors OR the number of column colors,
677+ # we can have the optimal post-processing by taking as hub the vertices in the other partition.
678+ # It is optimal because we will never increase the number of colors in the partition specified by `neutralized_first`
679+ # in this phase and everything else in the post-processing is deterministed.
680+ if nb_unknown_hubs > 0
681+ rvS = rowvals (S)
682+ for j in axes (S, 2 )
683+ for k in nzrange (S, j)
684+ i = rvS[k]
685+ if i > j
686+ index_ij = edge_to_index[k]
687+ s = star[index_ij]
688+ h = hub[s]
689+ # The hub of this trivial star is still unknown
690+ if h < 0
691+ if neutralized_first == :rows
692+ # j represents a column in the context of bicoloring
693+ hub[s] = j
694+ color_used[j] = true
695+ else # neutralized_first == :cols
696+ # i represents a row in the context of bicoloring
697+ hub[s] = i
698+ color_used[i] = true
662699 end
663700 end
664701 end
0 commit comments