@@ -1759,10 +1759,14 @@ void MBFF::KMeans(const std::vector<Flop>& flops,
17591759 }
17601760
17611761 if (!empty_clusters.empty ()) {
1762+ // To revive empty clusters and avoid division by zero, we re-seed their
1763+ // centers with active flops that are currently furthest from their
1764+ // assigned cluster centers. We use an inlined vector to track chosen
1765+ // flops and prevent promoting the same flop to multiple empty clusters.
17621766 absl::InlinedVector<int , 8 > used_flops;
17631767 for (int empty_idx : empty_clusters) {
17641768 float max_dist = -1 ;
1765- Point best_pt = centers[empty_idx].pt ;
1769+ Point best_pt = centers[empty_idx].pt ; // Fallback to previous center
17661770 int best_idx = -1 ;
17671771
17681772 for (int j = 0 ; j < knn; j++) {
@@ -1774,6 +1778,8 @@ void MBFF::KMeans(const std::vector<Flop>& flops,
17741778 != used_flops.end ()) {
17751779 continue ;
17761780 }
1781+ // Find the flop that has the worst-fit (largest displacement)
1782+ // to its currently assigned center.
17771783 const float dist = GetDist (flop.pt , centers[j].pt );
17781784 if (dist > max_dist) {
17791785 max_dist = dist;
@@ -1784,6 +1790,10 @@ void MBFF::KMeans(const std::vector<Flop>& flops,
17841790 }
17851791
17861792 if (best_idx != -1 ) {
1793+ // Re-seeding the center directly onto the flop's coordinate.
1794+ // This guarantees that in the next iteration, the distance from this
1795+ // flop to this center is 0.0, forcing it to be assigned to this
1796+ // cluster and keeping it active.
17871797 centers[empty_idx].pt = best_pt;
17881798 used_flops.push_back (best_idx);
17891799 }
0 commit comments