Este es un problema de optimización. Tenemos una biblioteca Java de código abierto que resuelve este problema (agrupamiento donde la cantidad por grupo debe estar entre los rangos establecidos). Sin embargo, necesitaría que su número total de puntos sea un máximo de unos pocos miles, no más de 5000 o quizás 10000.
La biblioteca está aquí:
https://github.com/PGWelch/territorium/tree/master/territorium.core
La biblioteca en sí está configurada para problemas geográficos / tipo SIG, por lo que verá referencias a X e Ys, latitudes y longitudes, clientes, distancia y tiempo, etc. Sin embargo, puede ignorar los elementos 'geográficos' y usarlo como un puro clusterer
Proporciona un conjunto de grupos de entrada inicialmente vacíos, cada uno con una cantidad objetivo mínima y máxima. El clusterer asignará puntos a sus grupos de entrada, utilizando un algoritmo de optimización basado en heurística (swaps, movimientos, etc.). En la optimización, prioriza en primer lugar mantener cada grupo dentro de su rango de cantidad mínima y máxima y luego minimiza en segundo lugar las distancias entre todos los puntos en el grupo y el punto central del grupo, por lo que un grupo es espacialmente cohesivo.
Usted le da al solucionador una función métrica (es decir, función de distancia) entre puntos usando esta interfaz:
https://github.com/PGWelch/territorium/blob/master/territorium.core/src/main/java/com/opendoorlogistics/territorium/problem/TravelMatrix.java
La métrica en realidad está estructurada para devolver tanto la distancia como el 'tiempo', porque está diseñada para problemas geográficos basados en viajes, pero para problemas de agrupamiento arbitrario simplemente establece que 'tiempo' sea cero y la distancia sea la métrica real que estás usando entre puntos.
Configuraría su problema en esta clase:
https://github.com/PGWelch/territorium/blob/master/territorium.core/src/main/java/com/opendoorlogistics/territorium/problem/Problem.java
Sus puntos serían los 'Clientes' y su cantidad sería 1. En la clase de cliente, asegúrese de establecer costPerUnitTime = 0 y costPerUnitDistance = 1 suponiendo que devuelve su distancia métrica en el campo 'distancia' devuelta por TravelMatrix.
https://github.com/PGWelch/territorium/blob/master/territorium.core/src/main/java/com/opendoorlogistics/territorium/problem/Customer.java
Vea aquí un ejemplo de ejecución del solucionador:
https://github.com/PGWelch/territorium/blob/master/territorium.core/src/test/java/com/opendoorlogistics/territorium/TestSolver.java