doum
4 小时以前 d8b9d884967f502caac58d723e57931d0356fa11
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
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);
    }
 
}