using Accord.MachineLearning;
public class KMeansClustering
public static int[] ClusterWithCapacity(double[][] data, int k, int capacity)
if (data == null || data.Length == 0)
throw new ArgumentException("Input data cannot be null or empty.");
throw new ArgumentException("Number of clusters must be greater than zero.");
throw new ArgumentException("Cluster capacity must be greater than zero.");
if (capacity * k < data.Length)
Console.WriteLine("Warning: Total cluster capacity is less than the number of data points. Some points may not be assigned optimally.");
KMeans kmeans = new KMeans(k);
KMeansClusterCollection clusters = kmeans.Learn(data, k, new Accord.Math.Random.RandomGenerator(1));
int[] assignments = new int[data.Length];
int[] clusterSizes = new int[k];
for (int i = 0; i < data.Length; i++)
double minDistance = double.MaxValue;
for (int j = 0; j < k; j++)
if (clusterSizes[j] < capacity)
double distance = Distance(data[i], clusters[j].Mean);
if (distance < minDistance)
if (nearestCluster == -1)
int leastFullCluster = 0;
for (int j = 1; j < k; j++)
if (clusterSizes[j] < clusterSizes[leastFullCluster])
nearestCluster = leastFullCluster;
assignments[i] = nearestCluster;
clusterSizes[nearestCluster]++;
private static double Distance(double[] a, double[] b)
for (int i = 0; i < a.Length; i++)
sum += Math.Pow(a[i] - b[i], 2);
double[][] data = new double[][]
new double[] { 1.0, 2.0 },
new double[] { 1.5, 1.8 },
new double[] { 5.0, 8.0 },
new double[] { 8.0, 8.0 },
new double[] { 1.0, 0.6 }
int[] assignments = KMeansClustering.ClusterWithCapacity(data, k, capacity);
Console.WriteLine("Cluster assignments:");
for (int i = 0; i < assignments.Length; i++)
Console.WriteLine($"Data point {i} assigned to cluster {assignments[i]}");
Console.WriteLine($"Error: {ex.Message}");