| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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); |
| | | } |
| | | |
| | | } |