Although I asked this question on stackoverflow to possibly reach a broader audience, I wonder your inputs about this problem. Without giving much research into this, I thought p-center problem ($x_{ij}=1$ if point is clustered around point $j$; 0, otherwise) can be useful to construct a simple model to partition the points into equally-sized clusters. With a proper constraint, I could also let $x_{ij}\in\mathbb{R}_{\geq 0}$, I guess. I am just afraid that the problem size might be too large for the exact solution, hence I tried to find the cure in heuristic/algorithmic solutions world. How would you approach this problem?
I am trying to cluster a dataset with 3,663 points. I have (x,y) coordinates and point-to-point weights available. Since I would like to use the weights instead of Euclidean distances, I implemented the AgglomerativeClustering with Python's sklearn thanks to Vivek Kumar's answer here. I created 20 clusters and had the following number of points in each cluster:
Num_points_in_cluster = [673,54,111,88,312,464,332,366,141,128,33,86,426,39,45,1,63,105,2,194]
As seen, some clusters have only 1 or 2 point(s). I would instead like to have number of points in clusters almost uniformly distributed. Is there a way to play around this within AgglomarativeClustering or is there any other method (preferably in sklearn world) that meets the criterion? I think, an alternative solution could be solving a p-center-like problem, but the time performance of off-the-shelf linear solvers can be a bottleneck as I also would like a quick solution.
For code-checking purposes, here is my code, where TT_np_matrix is my weight matrix in numpy matrix type, e.g., TT_np_matrix = array([[2,3,4],[5,2,3],[4,5,8]])
:
agg = AgglomerativeClustering(n_clusters=20, affinity='precomputed',
linkage='average')
agg_results = agg.fit_predict(TT_np_matrix) # The solution is an array
Edit:
Below is my (though I say "my," it most likely exists somewhere readily) formulation to solve the problem with binary/linear programming.
\begin{align} \min&\quad \sum_{i,j\in I}c_{ij}x_{ij}&\\ \text{s.t.}&\quad \sum_{j\in I} y_{j} =k & \\ &\quad \sum_{i\in I}x_{ij}\geq \lfloor |I|/k\rfloor y_j &\forall j\in I\\ &\quad \sum_{j\in I}x_{ij}=1 &\forall i\in I\\ &\quad x_{ij}\leq y_j &\forall i,j\in I\\ &\quad x,y\in\{0,1\}, \end{align}
where $x_{ij}=1$ if point $i\in I$ is centered around point $j\in I$; $0$, otherwise, and $y_j=1$ if point $j\in I$ is selected as a center; $0$, otherwise. Here, $k$ defines the number of clusters, and $I$ denotes the set of points to be clustered/partitioned.
Although I write this, I do not want to implement it as I believe it will be computationally more expensive (regardless of exactness) than an off-the-shelf so-called machine learning clustering algorithm. I am instead seeking an open-source implementable function or its example coded in Python (too much constraint, sorry).