1717#include < vector>
1818
1919#include " AbstractGraphics.h"
20+ #include " absl/container/inlined_vector.h"
2021#include " db_sta/dbNetwork.hh"
2122#include " db_sta/dbSta.hh"
2223#include " lemon/core.h"
@@ -1737,8 +1738,13 @@ void MBFF::KMeans(const std::vector<Flop>& flops,
17371738 }
17381739
17391740 // find new center locations
1741+ absl::InlinedVector<int , 4 > empty_clusters;
17401742 for (int i = 0 ; i < knn; i++) {
17411743 const int cur_sz = clusters[i].size ();
1744+ if (cur_sz == 0 ) {
1745+ empty_clusters.push_back (i);
1746+ continue ;
1747+ }
17421748 float cX = 0 ;
17431749 float cY = 0 ;
17441750
@@ -1752,6 +1758,48 @@ void MBFF::KMeans(const std::vector<Flop>& flops,
17521758 centers[i].pt = Point{new_x, new_y};
17531759 }
17541760
1761+ 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.
1766+ absl::InlinedVector<int , 8 > used_flops;
1767+ for (int empty_idx : empty_clusters) {
1768+ float max_dist = -1 ;
1769+ Point best_pt = centers[empty_idx].pt ; // Fallback to previous center
1770+ int best_idx = -1 ;
1771+
1772+ for (int j = 0 ; j < knn; j++) {
1773+ if (clusters[j].empty ()) {
1774+ continue ;
1775+ }
1776+ for (const Flop& flop : clusters[j]) {
1777+ if (std::find (used_flops.begin (), used_flops.end (), flop.idx )
1778+ != used_flops.end ()) {
1779+ continue ;
1780+ }
1781+ // Find the flop that has the worst-fit (largest displacement)
1782+ // to its currently assigned center.
1783+ const float dist = GetDist (flop.pt , centers[j].pt );
1784+ if (dist > max_dist) {
1785+ max_dist = dist;
1786+ best_pt = flop.pt ;
1787+ best_idx = flop.idx ;
1788+ }
1789+ }
1790+ }
1791+
1792+ 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.
1797+ centers[empty_idx].pt = best_pt;
1798+ used_flops.push_back (best_idx);
1799+ }
1800+ }
1801+ }
1802+
17551803 // get total displacement
17561804 float tot_disp = 0 ;
17571805 for (int i = 0 ; i < knn; i++) {
0 commit comments