package com.doumee.core.tsp;
|
|
import java.math.BigDecimal;
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.List;
|
|
import com.doumee.core.utils.Constants;
|
import com.doumee.dao.admin.request.SketchCateModel;
|
import com.doumee.dao.business.model.JkSketchCustomer;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.math3.ml.clustering.*;
|
import org.apache.commons.math3.ml.distance.EuclideanDistance;
|
/**
|
*
|
* @author xjx
|
*
|
*/
|
@Slf4j
|
public class ClusterCustomKMeans{
|
//欧式距离
|
|
public List<SketchCateModel> clusterPoints(List<JkSketchCustomer> customers, int k, int d){
|
List<SketchCateModel> list = new ArrayList<>();
|
if(customers.size() <= k){
|
int index =0;
|
for (JkSketchCustomer c : customers) {
|
SketchCateModel sketchCateModel = new SketchCateModel();
|
sketchCateModel.setId(index);
|
List<JkSketchCustomer> cList = new ArrayList<>();
|
cList.add(c);
|
sketchCateModel.setTotalNum(c.getTotalNum());
|
sketchCateModel.setCustomerList(cList);
|
sketchCateModel.setStartPoint(c);
|
sketchCateModel.setTotalCustomer(1);
|
list.add(sketchCateModel);
|
log.error("Cluster " + index + "members:"+1+"/200 "+" 客户:"+ c.getName());
|
index ++;
|
}
|
return list;
|
}
|
List<DoublePointNew> points = new ArrayList<>();
|
for (int i = 0; i < customers.size(); i++) {
|
DoublePointNew p = new DoublePointNew(new double[]{customers.get(i).getLatitude().doubleValue(), customers.get(i).getLongitude().doubleValue()});
|
p.setCustomer(customers.get(i));
|
points.add(p); // 示例点1
|
}
|
KMeansPlusPlusClusterer<DoublePointNew> clusterer = new KMeansPlusPlusClusterer<>(k, d, new EuclideanDistance());
|
List<CentroidCluster<DoublePointNew>> clusters = clusterer.cluster(points);
|
|
int index = 0;
|
int maxMembersPerCluster = 200; // 设置每个簇的最大成员数
|
List<CentroidCluster<DoublePointNew>> allList = new ArrayList<>();
|
for (CentroidCluster<DoublePointNew> cluster : clusters) {
|
if(cluster.getPoints() ==null || cluster.getPoints().size() ==0){
|
log.error("Cluster " + clusters.indexOf(cluster) + "members:"+cluster.getPoints().size()+"/200 无数据");
|
continue;
|
}
|
log.error("Cluster " + clusters.indexOf(cluster) + "members:"+cluster.getPoints().size()+"/200 "+"中心点:"+ Arrays.toString(cluster.getCenter().getPoint())+"中心点:"+ cluster.getPoints().get(0).getCustomer().getName());
|
if (cluster.getPoints().size() > maxMembersPerCluster) {
|
// 这里可以重新运行聚类算法或者手动调整簇的分配策略
|
log.error("Cluster " + clusters.indexOf(cluster) + " exceeds maximum members:" + cluster.getPoints().size() + "/200, re-clustering needed.");
|
// 可以考虑再次调用KMeansPlusPlusClusterer或其它逻辑来处理超限情况。
|
}
|
allList.add(cluster);
|
}
|
for (CentroidCluster<DoublePointNew> cluster : allList) {
|
// System.out.println("Cluster " + clusters.indexOf(cluster) + "members:"+cluster.getPoints().size()+"/200 ");
|
if (cluster.getPoints().size() > maxMembersPerCluster) {
|
// 这里可以重新运行聚类算法或者手动调整簇的分配策略
|
// System.out.println("Cluster " + clusters.indexOf(cluster) + " exceeds maximum members:"+cluster.getPoints().size()+"/200, re-clustering needed.");
|
// 可以考虑再次调用KMeansPlusPlusClusterer或其它逻辑来处理超限情况。
|
}
|
SketchCateModel sketchCateModel = new SketchCateModel();
|
sketchCateModel.setId(index);
|
List<JkSketchCustomer> cList = new ArrayList<>();
|
for(DoublePointNew doublePointNew:cluster.getPoints()){
|
cList.add(doublePointNew.getCustomer());
|
sketchCateModel.setTotalNum(Constants.formatBigdecimal(sketchCateModel.getTotalNum()).add(Constants.formatBigdecimal(doublePointNew.getCustomer().getTotalNum())));
|
}
|
sketchCateModel.setCustomerList(cList);
|
sketchCateModel.setStartPoint(cList.get(0));
|
sketchCateModel.setTotalCustomer(cList.size());
|
list.add(sketchCateModel);
|
}
|
return list;
|
}
|
|
public class DoublePointNew extends DoublePoint{
|
private JkSketchCustomer customer;
|
|
public DoublePointNew(double[] point) {
|
super(point);
|
}
|
|
public JkSketchCustomer getCustomer() {
|
return customer;
|
}
|
|
public void setCustomer(JkSketchCustomer customer) {
|
this.customer = customer;
|
}
|
|
}
|
public static void main(String[] args) {
|
List<JkSketchCustomer> points = new ArrayList<>();
|
for (int i = 0; i <10; i++) {
|
JkSketchCustomer a = new JkSketchCustomer();
|
a.setLatitude(new BigDecimal(30.19d ));
|
a.setLongitude(new BigDecimal(117.40 ));
|
a.setName("客户"+i);
|
points.add(a);
|
}
|
for (int i = 0; i <10; i++) {
|
JkSketchCustomer a = new JkSketchCustomer();
|
a.setLatitude(new BigDecimal(31.19d ));
|
a.setLongitude(new BigDecimal(118.40 ));
|
a.setName("客户"+i);
|
points.add(a);
|
}
|
for (int i = 10; i <3000; i++) {
|
JkSketchCustomer a = new JkSketchCustomer();
|
a.setLatitude(new BigDecimal(31.19d-(0.1d)*Math.random()));
|
a.setLongitude(new BigDecimal(118.40-(0.2d)*Math.random()));
|
a.setName("客户"+i);
|
points.add(a);
|
}
|
|
double threshold = 1000; // 设置距离阈值,超过这个距离就不属于同一聚类。
|
(new ClusterCustomKMeans()).clusterPoints(points, 100,1);
|
}
|
|
}
|