From 3d6ff15899256f33cd100d95237f613c023d50df Mon Sep 17 00:00:00 2001
From: MrShi <1878285526@qq.com>
Date: 星期一, 08 十二月 2025 09:54:09 +0800
Subject: [PATCH] 优化
---
server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/ClusterCustomKMeans.java | 147 +++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 147 insertions(+), 0 deletions(-)
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/ClusterCustomKMeans.java b/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/ClusterCustomKMeans.java
new file mode 100644
index 0000000..8915a9b
--- /dev/null
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/ClusterCustomKMeans.java
@@ -0,0 +1,147 @@
+package com.doumee.core.tsp;
+
+import java.math.BigDecimal;
+import java.util.*;
+
+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())));
+ }
+ sortPointByCenterPoint(cluster,cList);
+ sketchCateModel.setCustomerList(cList);
+ sketchCateModel.setStartPoint(cList.get(0));
+ sketchCateModel.setTotalCustomer(cList.size());
+ list.add(sketchCateModel);
+ }
+ return list;
+ }
+
+ private void sortPointByCenterPoint(CentroidCluster<DoublePointNew> cluster, List<JkSketchCustomer> cList) {
+ double clat = Constants.formatBigdecimal(cList.get(0).getLatitude()).doubleValue();
+ double clong = Constants.formatBigdecimal(cList.get(0).getLongitude()).doubleValue();
+ if(cluster!=null || cluster.getCenter() != null || cluster.getCenter().getPoint() != null && cluster.getCenter().getPoint().length>=2){
+ clong = cluster.getCenter().getPoint()[1];
+ clat = cluster.getCenter().getPoint()[0];
+ }
+ for(JkSketchCustomer c : cList){
+ double latDiff = Constants.formatBigdecimal(c.getLatitude()).doubleValue() - clat;
+ double lonDiff = Constants.formatBigdecimal(c.getLongitude()).doubleValue() - clong;
+ c.setDistanceCenter(Math.sqrt(latDiff * latDiff + lonDiff * lonDiff)); // 娆ф皬璺濈
+ }
+ Collections.sort(cList, (p1, p2) -> Double.compare(p1.getDistanceCenter(), p2.getDistanceCenter()));
+ }
+
+ 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);
+ }
+
+}
\ No newline at end of file
--
Gitblit v1.9.3