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 clusterPoints(List customers, int k, int d){ List list = new ArrayList<>(); if(customers.size() <= k){ int index =0; for (JkSketchCustomer c : customers) { SketchCateModel sketchCateModel = new SketchCateModel(); sketchCateModel.setId(index); List 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 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 clusterer = new KMeansPlusPlusClusterer<>(k, d, new EuclideanDistance()); List> clusters = clusterer.cluster(points); int index = 0; int maxMembersPerCluster = 200; // 设置每个簇的最大成员数 List> allList = new ArrayList<>(); for (CentroidCluster 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 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 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 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); } }