| server/system_service/src/main/java/com/doumee/core/utils/Constants.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| server/visits/dmvisit_service/pom.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/ClusterCustomKMeans.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/Clustering.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/TspSolver.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| server/visits/dmvisit_service/src/main/java/com/doumee/dao/admin/request/SketchCateModel.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| server/visits/dmvisit_service/src/main/java/com/doumee/service/business/JkSketchService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkSketchServiceImpl.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
server/system_service/src/main/java/com/doumee/core/utils/Constants.java
@@ -57,6 +57,7 @@ public static final String SIGN_IN_QRCODE ="SIGN_IN_QRCODE" ; public static final String SIGN_IN_ATTENTION ="SIGN_IN_ATTENTION" ; public static final String SIGN_IN_QRCODE_PREFIX ="SIGN_IN_QRCODE_PREFIX" ; public static final String JK_PLAN_MAX_CLUSTER ="JK_PLAN_MAX_CLUSTER" ; /** * æä½ç±»åï¼ç¨äºåæ¥å£éªè¯åç» server/visits/dmvisit_service/pom.xml
@@ -40,6 +40,11 @@ <scope>compile</scope> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-math3</artifactId> <version>3.6.1</version> </dependency> <dependency> <groupId>com.doumee</groupId> <artifactId>emaysms</artifactId> <version>1.0.0-SNAPSHOT</version> server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/ClusterCustomKMeans.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,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); } } server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/Clustering.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,85 @@ package com.doumee.core.tsp; /** * èç±»åç» */ import com.doumee.core.utils.Constants; import com.doumee.dao.admin.request.SketchCateModel; import com.doumee.dao.business.model.JkSketchCustomer; import com.doumee.service.business.impl.JkSketchServiceImpl; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; public class Clustering { public static List<SketchCateModel> clusterPoints(List<JkSketchCustomer> points, double threshold) { List<SketchCateModel> clusters = new ArrayList<>(); boolean[] visited = new boolean[points.size()]; int index =0; for (int i = 0; i < points.size(); i++) { if (!visited[i]) { List<JkSketchCustomer> cluster = new ArrayList<>(); dfs(points, visited, cluster, i, threshold); SketchCateModel sketchCateModel = new SketchCateModel(); sketchCateModel.setCustomerList(cluster); sketchCateModel.setId(index); sketchCateModel.setStartPoint(cluster.get(0)); for (JkSketchCustomer c : cluster){ sketchCateModel.setTotalNum(Constants.formatBigdecimal(sketchCateModel.getTotalNum()).add(Constants.formatBigdecimal(c.getTotalNum()))); } sketchCateModel.setTotalCustomer(cluster.size()); clusters.add(sketchCateModel); } } // æå°æ¯ä¸ªèç±»çç¹ for (int i = 0; i < clusters.size(); i++) { System.out.println("Cluster " + (i + 1) + ": " + clusters.get(i).getStartPoint().getName()+ ": " + clusters.get(i).getCustomerList().size()); } return clusters; } public static double distanceTo(JkSketchCustomer self, JkSketchCustomer other) { List<DistanceMapParam> distanceMapParamList =JkSketchServiceImpl.getListFromJsonStr(self.getDistanceJson()); DistanceMapParam param = JkSketchServiceImpl.getParamByCustomerIds( other.getId(),distanceMapParamList); if(param!=null && param.getDistance()!=0){//妿ä¹åå·²ç»è·åè¿ return (param.getDistance()); } return DistanceCalculator.calculateDistance(Constants.formatBigdecimal(self.getLatitude()).doubleValue() ,Constants.formatBigdecimal(self.getLongitude()).doubleValue() ,Constants.formatBigdecimal(other.getLatitude()).doubleValue() ,Constants.formatBigdecimal(other.getLongitude()).doubleValue()); } private static void dfs(List<JkSketchCustomer> points, boolean[] visited, List<JkSketchCustomer> cluster, int startIndex, double threshold) { visited[startIndex] = true; cluster.add(points.get(startIndex)); JkSketchCustomer startPoint = points.get(startIndex); for (int i = 0; i < points.size(); i++) { if (!visited[i]) { double distance = distanceTo(startPoint,points.get(i)); if (distance <= threshold) { dfs(points, visited, cluster, i, threshold); // é彿·»å å°èç±»ä¸ } } } } /** * 117°40â²ï½118°44â²ãå纬30°19â²ï½31°34â² * @param args */ public static void main(String[] args) { List<JkSketchCustomer> points = new ArrayList<>(); for (int i = 0; i <3000; i++) { JkSketchCustomer a = new JkSketchCustomer(); a.setLatitude(new BigDecimal(30.19d+(30.54d-30.19d)*Math.random())); a.setLongitude(new BigDecimal(117.40+(117.74d-117.40d)*Math.random())); a.setName("客æ·"+i); points.add(a); } double threshold = 1000; // 设置è·ç¦»éå¼ï¼è¶ è¿è¿ä¸ªè·ç¦»å°±ä¸å±äºåä¸èç±»ã clusterPoints(points, threshold); } } server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/TspSolver.java
@@ -25,7 +25,7 @@ data.initDataList();//æé æ°æ® long start =System.currentTimeMillis(); System.out.println("=============start=========="+start); log.error("=============start=========="+start); //å建æ±è§£å¨manager对象ï¼åå§åæ±è§£å¨æ°æ® RoutingIndexManager manager = new RoutingIndexManager(data.distanceMatrix.length, data.vehicleNumber, data.depot); @@ -71,15 +71,15 @@ // æå°è·¯çº¿ printSolution(data, routing, manager, solution); long end =System.currentTimeMillis(); System.out.println("=============end=========="+end); log.error("=============end=========="+end); System.out.println("=============èæ¶=========="+(end -start)+"ï¼msï¼"+(end -start)/1000 +"s"+(end -start)/60/1000 +"m"); log.error("=============èæ¶=========="+(end -start)+"ï¼msï¼"+(end -start)/1000 +"s"+(end -start)/60/1000 +"m"); */} public static void startSearch(DataModel data) { // åå§åæ°æ®æ¨¡å Loader.loadNativeLibraries(); long start =System.currentTimeMillis(); System.out.println("=============start=========="+start); log.error("å¼å§è§å=============start=========="+start); //å建æ±è§£å¨manager对象ï¼åå§åæ±è§£å¨æ°æ® RoutingIndexManager manager = new RoutingIndexManager(data.distanceMatrix.length, data.vehicleNumber, data.depot); @@ -87,7 +87,7 @@ RoutingModel routing = new RoutingModel(manager); // 注ååè°å½æ° /* final int transitCallbackIndex = final int transitCallbackIndex = routing.registerTransitCallback((long fromIndex, long toIndex) -> { int fromNode = manager.indexToNode(fromIndex); int toNode = manager.indexToNode(toIndex); @@ -96,7 +96,7 @@ // å®ä¹åè°å½æ°è³æ¯æ¡è·¯çº¿ routing.setArcCostEvaluatorOfAllVehicles(transitCallbackIndex); routing.addDimension(transitCallbackIndex, 0, 30000000, /* routing.addDimension(transitCallbackIndex, 0, 30000000, true, "Distance"); RoutingDimension distanceDimension = routing.getMutableDimension("Distance"); @@ -104,7 +104,8 @@ // 注ååè°å½æ° final int transitCallbackIndex1 = routing.registerTransitCallback((long fromIndex, long toIndex) -> { return 1; int fromNode = manager.indexToNode(fromIndex); return data.customerDemands[fromNode]; }); for (int d = 0; d < data.vehicleMaxNodes.length; d++) { // å¢å è·ç¦»ç»´åº¦çº¦æ @@ -121,20 +122,12 @@ }); routing.addDimensionWithVehicleCapacity(demandCallbackIndex, 0, data.vehicleCapacities, true, "Capacity"); /* // æ·»å 容ééå¶ final int demandCallbackIndex1 = routing.registerUnaryTransitCallback((long fromIndex) -> { return 1; }); routing.addDimensionWithVehicleCapacity(demandCallbackIndex1, 0, data.vehicleMaxNodes, true, "Capacity"); */ Solver solver = routing.solver(); //设置æç´¢æ¹æ³( RoutingSearchParameters searchParameters = main.defaultRoutingSearchParameters() .toBuilder() // .setTimeLimit(Duration.newBuilder().setSeconds(60*60).build())//æä¹ 1å°æ¶ .setTimeLimit(Duration.newBuilder().setSeconds(60*60*6).build())//æä¹ 1å°æ¶ .setFirstSolutionStrategy(FirstSolutionStrategy.Value.PATH_CHEAPEST_ARC) .build(); @@ -146,8 +139,7 @@ // æå°è·¯çº¿ resultSolution(data, routing, manager, solution); long end =System.currentTimeMillis(); System.out.println("=============end=========="+end); System.out.println("=============èæ¶=========="+(end -start)+"ï¼msï¼"+(end -start)/1000 +"s"+(end -start)/60/1000 +"m"); log.error("è§åç»æ=============èæ¶=========="+(end -start)+"ï¼msï¼"+(end -start)/1000 +"s"+(end -start)/60/1000 +"m"); } static void resultSolution( DataModel data, RoutingModel routing, RoutingIndexManager manager, Assignment solution) { long maxRouteDistance = 0; @@ -223,6 +215,7 @@ //æ¯ä¸ä¸ªç¹çååçæ°é public long[] demands; public long[] customerDemands; //è½¦è¾æå¤§å®¹è½½ public long[] vehicleCapacities ; public long[] vehicleMaxNodes ; @@ -236,17 +229,19 @@ this.solutions = solutions; } public void initDataInfo(int vehicleNumber1, long[] demands1, long[] vehicleCapacities1, long[][] distanceMatrix1,long[] vehicleMaxNodes){ public void initDataInfo(int vehicleNumber1, long[] demands1,long[] demands2, long[] vehicleCapacities1, long[][] distanceMatrix1,long[] vehicleMaxNodes){ this.demands = demands1; this.customerDemands = demands2; this.vehicleNumber = vehicleNumber1; this.vehicleCapacities=vehicleCapacities1; this.distanceMatrix=distanceMatrix1; this.vehicleMaxNodes =vehicleMaxNodes; } public void initDataList(){ lenght = 20; lenght = 10; vehicleNumber = 5; demands = new long[lenght]; customerDemands = new long[lenght]; vehicleCapacities =new long[vehicleNumber]; vehicleMaxNodes =new long[vehicleNumber]; distanceMatrix = new long[lenght][lenght]; @@ -254,15 +249,16 @@ for (int i = 0; i <vehicleNumber ; i++) { long tem = (long) (Math.random() * 1000 + 20000); vehicleCapacities[i] = tem; vehicleMaxNodes[i] =5; vehicleMaxNodes[i] =50; total0+=tem; System.out.print(tem+" ,"); } System.out.println( "\ntotal Capacity:"+total0+"====================="); log.error( "\ntotal Capacity:"+total0+"====================="); long total = 0; for (int i = 0; i <lenght ; i++) { long tem = (int)(Math.random()*100+100); demands[i] =tem; customerDemands[i] =1; total+=tem; System.out.print(tem+" ,"); for (int j = 0; j <lenght ; j++) { @@ -276,7 +272,7 @@ } } System.out.println( "\ntotal Demands:"+total+"====================="); log.error( "\ntotal Demands:"+total+"====================="); } /* public final long[][] distanceMatrix = { {0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354, 468, 776, 662}, server/visits/dmvisit_service/src/main/java/com/doumee/dao/admin/request/SketchCateModel.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,36 @@ package com.doumee.dao.admin.request; import com.baomidou.mybatisplus.annotation.TableField; import com.doumee.core.annotation.excel.ExcelColumn; import com.doumee.core.tsp.DistanceMapParam; import com.doumee.dao.business.model.JkSketchCustomer; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.math.BigDecimal; import java.util.List; /** * å工信æ¯å¯¼å ¥è¡¨ * @author æ±è¹è¹ * @date 2024/01/16 10:03 */ @Data @ApiModel("线路è§åèç±»åç»éå") public class SketchCateModel { private int id; private JkSketchCustomer startPoint; //ä¸å¿ç¹çº¬åº¦ private BigDecimal latitude; //ä¸å¿ç¹ç»åº¦ private BigDecimal longitude; @ApiModelProperty(value = "éè´§é", example = "1") private BigDecimal totalNum; @ApiModelProperty(value = "æ»å®¢æ·æ°", example = "1") private int totalCustomer; //ç¹éå private List<JkSketchCustomer> customerList; } server/visits/dmvisit_service/src/main/java/com/doumee/service/business/JkSketchService.java
@@ -108,6 +108,7 @@ List<JkSketch> importBatch(MultipartFile file, String dateInfo, LoginUserInfo loginUser); void startUpdateLineAsyncOld(JkSketch model); void startUpdateLineAsync(JkSketch model); void distanceCustomer(Category model ); @@ -119,7 +120,7 @@ void startEditSketchLineAsync(JkSketch model); void startInitOriginDistanceBatch(JkSketch list); void startEditSketchLineAsyncOld(JkSketch model); /** * 车è¾çº¿è·¯ - çµä¿¡ä½¿ç¨ server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkSketchServiceImpl.java
@@ -12,6 +12,7 @@ import com.doumee.core.wms.model.response.WmsBaseDataResponse; import com.doumee.core.wms.model.response.WmsBaseResponse; import com.doumee.dao.admin.request.JkOrdersImport; import com.doumee.dao.admin.request.SketchCateModel; import com.doumee.dao.business.*; import com.doumee.dao.business.dto.TelecomLineInfoDTO; import com.doumee.dao.business.model.*; @@ -508,6 +509,69 @@ @Async public void startUpdateLineAsync(JkSketch model) { try { int maxnum =100; try { maxnum = Integer.parseInt(systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.JK_PLAN_MAX_CLUSTER).getCode()); }catch (Exception e){ } List<JkSketchCustomer> allCustomerList = model.getCustomerList(); //ä¸¤å ¬éå æ°æ®å®¢æ·åå¹¶ // List<SketchCateModel> customerList =Clustering.clusterPoints(allCustomerList,1000); List<SketchCateModel> customerList = new ClusterCustomKMeans().clusterPoints(allCustomerList,maxnum,500); List<JkLine> lineList = model.getLineList(); TspSolver.DataModel dataModel = new TspSolver.DataModel(); int vehicleNumber1 = lineList.size();//线路æ°é long[] vehicleCapacities1=new long[lineList.size()];//æ¯è¾è½¦çæå¤§è®¢åééå¶ long[] vehicleMaxNodes=new long[lineList.size()];//æ¯è¾è½¦çæå¤§è®¢åééå¶ long[] demands1 = new long[customerList.size()+1]; //å个ç¹ç订åé long[] demands2 = new long[customerList.size()+1]; //å个ç¹ç客æ¶é long[][] distanceMatrix1 = new long[customerList.size()+1][customerList.size()+1]; distanceMatrix1[0][0] = 0; demands1[0] =0;//åç¹ demands2[0] =0;//åç¹ for (int i = 0; i < customerList.size(); i++) { List<DistanceMapParam> disList = customerList.get(i).getStartPoint().getDistanceMapParamList(); distanceMatrix1[0][i+1] = disList.get(0).getDistance(); distanceMatrix1[i+1][0] = disList.get(disList.size() -1).getDistance(); demands1[i+1] = Constants.formatBigdecimal( customerList.get(i).getTotalNum()).longValue(); //å个ç¹ç订åé demands2[i+1] = customerList.get(i).getTotalCustomer(); //å个ç¹ç订åé for (int j = 0; j < customerList.size(); j++) { distanceMatrix1[i+1][j+1] =disList.get(j+1).getDistance() ; } } for (int i = 0; i < lineList.size(); i++) { vehicleCapacities1[i] = lineList.get(i).getMaxOrder();//æ¯è¾è½¦çæå¤§è®¢åééå¶ vehicleMaxNodes[i] =lineList.get(i).getMaxCustomer();//æå¤§å®¢æ·æ° } //æé ä¼åæ°æ®æ¨¡å dataModel.initDataInfo(vehicleNumber1,demands1,demands2,vehicleCapacities1,distanceMatrix1,vehicleMaxNodes); TspSolver.startSearch(dataModel); dealSearchSolution(model, customerList,dataModel); }catch (Exception e){ e.printStackTrace(); jkSketchMapper.update(null,new UpdateWrapper<JkSketch>().lambda() .eq(JkSketch::getId,model.getId() ) .eq(JkSketch::getJobId,model.getJobId() ) .set(JkSketch::getPlanLineInfo,"æè¿ä¸æ¬¡çº¿è·¯ä¼å失败ï¼") .set(JkSketch::getStatus,Constants.THREE) .set(JkSketch::getPlanLineEndDate,new Date())); } } private List<JkSketchCustomer> getCustomerCateList(List<JkSketchCustomer> allCustomerList) { List<JkSketchCustomer> list = new ArrayList<>(); return list; } /** * å¼å§å¼æ¥æ§è¡çº¿è·¯ä¼åä»»å¡ * @param model */ @Override @Async public void startUpdateLineAsyncOld(JkSketch model) { try { List<JkSketchCustomer> customerList = model.getCustomerList(); List<JkLine> lineList = model.getLineList(); TspSolver.DataModel dataModel = new TspSolver.DataModel(); @@ -515,6 +579,7 @@ long[] vehicleCapacities1=new long[lineList.size()];//æ¯è¾è½¦çæå¤§è®¢åééå¶ long[] vehicleMaxNodes=new long[lineList.size()];//æ¯è¾è½¦çæå¤§è®¢åééå¶ long[] demands1 = new long[customerList.size()+1]; //å个ç¹ç订åé long[] demands2 = new long[customerList.size()+1]; //å个ç¹ç客æ·é long[][] distanceMatrix1 = new long[customerList.size()+1][customerList.size()+1]; distanceMatrix1[0][0] = 0; demands1[0] =0;//åç¹ @@ -523,6 +588,7 @@ distanceMatrix1[0][i+1] = disList.get(0).getDistance(); distanceMatrix1[i+1][0] = disList.get(disList.size() -1).getDistance(); demands1[i+1] = Constants.formatBigdecimal( customerList.get(i).getTotalNum()).longValue(); //å个ç¹ç订åé demands2[i+1] =1; //å个ç¹ç订åé for (int j = 0; j < customerList.size(); j++) { distanceMatrix1[i+1][j+1] =disList.get(j+1).getDistance() ; } @@ -542,9 +608,9 @@ vehicleMaxNodes[i] =lineList.get(i).getMaxCustomer();//æå¤§å®¢æ·æ° } //æé ä¼åæ°æ®æ¨¡å dataModel.initDataInfo(vehicleNumber1,demands1,vehicleCapacities1,distanceMatrix1,vehicleMaxNodes); dataModel.initDataInfo(vehicleNumber1,demands1,demands2,vehicleCapacities1,distanceMatrix1,vehicleMaxNodes); TspSolver.startSearch(dataModel); dealSearchSolution(model,dataModel); dealSearchSolutionOld(model,dataModel); }catch (Exception e){ e.printStackTrace(); jkSketchMapper.update(null,new UpdateWrapper<JkSketch>().lambda() @@ -563,6 +629,126 @@ @Override @Async public void startEditSketchLineAsync(JkSketch model) { boolean success = true; int totalDistance = 0; List<JkSketchLine> lineList = model.getSketchLineList(); try { MPJLambdaWrapper<JkSketchCustomer> queryWrapper = new MPJLambdaWrapper<>(); queryWrapper.selectAll(JkSketchCustomer.class ) .selectAs(JkCustomer::getName,JkSketchCustomer::getName) .selectAs(JkCustomer::getCode,JkSketchCustomer::getCode) .selectAs(JkCustomer::getDistance,JkSketchCustomer::getDistanceJson) .selectAs(JkCustomer::getLongitude,JkSketchCustomer::getLongitude) .selectAs(JkCustomer::getLatitude,JkSketchCustomer::getLatitude) .selectAs(JkCustomer::getStartDistance,JkSketchCustomer::getStartDistance) .selectAs(JkCustomer::getEndDistance,JkSketchCustomer::getEndDistance) .leftJoin(JkCustomer.class,JkCustomer::getId,JkSketchCustomer::getCustomerId ) .eq(JkSketchCustomer::getType, Constants.equalsInteger(model.getOptStatus(),Constants.ONE)?1:0) .eq(JkSketchCustomer::getSketchId, model.getId()) .eq(JkSketchCustomer::getIsdeleted,Constants.ZERO) .orderByAsc(JkSketchCustomer::getSortnum); List<JkSketchCustomer> customerList = jkSketchCustomerMapper.selectJoinList(JkSketchCustomer.class,queryWrapper); if(customerList == null ||customerList.size() ==0){ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"该线路客æ·ä¿¡æ¯ä¸ºç©ºï¼ä¸æ»¡è¶³ä¼åæ¡ä»¶ï¼"); } int maxnum =100; try { maxnum = Integer.parseInt(systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.JK_PLAN_MAX_CLUSTER).getCode()); }catch (Exception e){ } int totalNum = 0; for(JkSketchLine line : lineList){ //å®å线路客æ·ä¼ååæ° List<JkSketchCustomer> customerListParam = line.getCustomerList() ; if(customerListParam ==null || customerListParam.size()==0){ throw new BusinessException(ResponseStatus.BAD_REQUEST); } initSketchCustomerListParam(line.getCustomerList(),customerList) ; totalNum += customerListParam.size(); } if(totalNum != Constants.formatIntegerNum(model.getOrderNum())){ throw new BusinessException(ResponseStatus.BAD_REQUEST); } for(JkSketchLine line : lineList){ //é个路线ä¼å List<JkSketchCustomer> allCustomerListParam = line.getCustomerList() ; // List<SketchCateModel> customerListParam = Clustering.clusterPoints(allCustomerListParam,1000); List<SketchCateModel> customerListParam = new ClusterCustomKMeans().clusterPoints(allCustomerListParam,maxnum,500); TspSolver.DataModel dataModel = new TspSolver.DataModel(); int vehicleNumber1 = 1;//线路æ°é long[] vehicleCapacities1=new long[]{line.getMaxOrder()};//æ¯è¾è½¦çæå¤§è®¢åééå¶ long[] vehicleMaxNodes=new long[]{line.getMaxCustomer()};//æ¯è¾è½¦çæå¤§è®¢åééå¶ long[] demands1 = new long[customerListParam.size()+1]; //å个ç¹ç订åé long[] demands2 = new long[customerListParam.size()+1]; //å个ç¹ç订åé long[][] distanceMatrix1 = new long[customerListParam.size()+1][customerListParam.size()+1]; distanceMatrix1[0][0] = 0; demands1[0] =0;//åç¹ for (int i = 0; i < customerListParam.size(); i++) { List<DistanceMapParam> disList = customerListParam.get(i).getStartPoint().getDistanceMapParamList(); distanceMatrix1[0][i+1] = disList.get(0).getDistance(); distanceMatrix1[i+1][0] = disList.get(disList.size() -1).getDistance(); demands1[i+1] = Constants.formatBigdecimal( customerListParam.get(i).getTotalNum()).longValue(); //å个ç¹ç订åé demands2[i+1] = customerListParam.get(i).getTotalCustomer() ; //å个ç¹ç订åé for (int j = 0; j < customerListParam.size(); j++) { distanceMatrix1[i+1][j+1] =disList.get(j+1).getDistance() ; } } //æé ä¼åæ°æ®æ¨¡å dataModel.initDataInfo(vehicleNumber1,demands1,demands2,vehicleCapacities1,distanceMatrix1,vehicleMaxNodes); TspSolver.startSearch(dataModel); if(dataModel.getSolutions()==null || dataModel.getSolutions().size()==0){ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"线路ã"+line.getLineName()+"ãè°æ´å¤±è´¥ ï¼æªè·å¾æä¼äº¤éè§åæ¹æ¡ï¼"); } TspSolverSolutions so = dataModel.getSolutions().get(0); List<Integer> routes = so.getRouteIndex(); totalDistance += so.getDistance(); if(routes.size() <=2) { throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"线路ã"+line.getLineName()+"ãè°æ´å¤±è´¥ ï¼æªè·å¾æä¼äº¤éè§åæ¹æ¡ï¼"); } int index = 0; line.setDistance(so.getDistance()); //ææè·¯å¾ for (Integer cIndex : routes){ if(cIndex ==0){ continue; //èµ·å§ç¹ä¸å¤ç } SketchCateModel cateModel = customerListParam.get(cIndex-1); for(int t=0;t<cateModel.getCustomerList().size();t++){ JkSketchCustomer customer = cateModel.getCustomerList().get(t); customer.setSortnum(index++); if(t < cateModel.getCustomerList().size()-1){ long tdistance = (long)Clustering.distanceTo(customer, cateModel.getCustomerList().get(t+1)); line.setDistance(Constants.formatLongNum(line.getDistance()) +tdistance); totalDistance += tdistance; } } } } }catch (Exception e){ e.printStackTrace(); success =false; }finally { if(success){ List<JkSketchCustomer> allList = new ArrayList<>(); for(JkSketchLine line : lineList){ allList.addAll(line.getCustomerList()); } jkSketchLineMapper.updateById(lineList); jkSketchCustomerMapper.updateById(allList); } jkSketchMapper.update(null,new UpdateWrapper<JkSketch>().lambda() // .eq(JkSketch::getId,model.getId() ) .eq(JkSketch::getJobId,model.getJobId() ) .set(success,JkSketch::getDistance,totalDistance) .set(JkSketch::getPlanLineInfo,success?"æè¿ä¸æ¬¡çº¿è·¯è°æ´æå":"æè¿ä¸æ¬¡çº¿è·¯è°æ´å¤±è´¥ï¼") .set(JkSketch::getStatus,success?Constants.TWO:Constants.THREE) .set(JkSketch::getPlanLineEndDate,new Date())); } } @Override @Async public void startEditSketchLineAsyncOld(JkSketch model) { boolean success = true; int totalDistance = 0; List<JkSketchLine> lineList = model.getSketchLineList(); @@ -607,6 +793,7 @@ long[] vehicleCapacities1=new long[]{line.getMaxOrder()};//æ¯è¾è½¦çæå¤§è®¢åééå¶ long[] vehicleMaxNodes=new long[]{line.getMaxCustomer()};//æ¯è¾è½¦çæå¤§è®¢åééå¶ long[] demands1 = new long[customerListParam.size()+1]; //å个ç¹ç订åé long[] demands2 = new long[customerListParam.size()+1]; //å个ç¹ç订åé long[][] distanceMatrix1 = new long[customerListParam.size()+1][customerListParam.size()+1]; distanceMatrix1[0][0] = 0; demands1[0] =0;//åç¹ @@ -615,12 +802,13 @@ distanceMatrix1[0][i+1] = disList.get(0).getDistance(); distanceMatrix1[i+1][0] = disList.get(disList.size() -1).getDistance(); demands1[i+1] = Constants.formatBigdecimal( customerListParam.get(i).getTotalNum()).longValue(); //å个ç¹ç订åé demands2[i+1] = 1; //å个ç¹ç订åé for (int j = 0; j < customerListParam.size(); j++) { distanceMatrix1[i+1][j+1] =disList.get(j+1).getDistance() ; } } //æé ä¼åæ°æ®æ¨¡å dataModel.initDataInfo(vehicleNumber1,demands1,vehicleCapacities1,distanceMatrix1,vehicleMaxNodes); dataModel.initDataInfo(vehicleNumber1,demands1,demands2,vehicleCapacities1,distanceMatrix1,vehicleMaxNodes); TspSolver.startSearch(dataModel); if(dataModel.getSolutions()==null || dataModel.getSolutions().size()==0){ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"线路ã"+line.getLineName()+"ãè°æ´å¤±è´¥ ï¼æªè·å¾æä¼äº¤éè§åæ¹æ¡ï¼"); @@ -828,7 +1016,114 @@ return new ArrayList<>(); } private void dealSearchSolution(JkSketch model, TspSolver.DataModel dataModel) { private void dealSearchSolution(JkSketch model, List<SketchCateModel> customerList,TspSolver.DataModel dataModel) { Date date = new Date(); List<TspSolverSolutions> solutions = dataModel.getSolutions(); List<JkSketchLine> sketchLineList = new ArrayList<>(); List<JkSketchCustomer> sketchCustomerList = new ArrayList<>(); long totalDistance = 0l; if(solutions!=null && solutions.size()>0){ for(TspSolverSolutions so : solutions){ List<Integer> routes = so.getRouteIndex(); totalDistance+= so.getDistance(); if(routes.size() <=2) { continue;//æ 客æ·çéææè·¯çº¿ } JkLine line =model.getLineList().get(so.getLineIndex()); JkSketchLine tModel = new JkSketchLine(); tModel.setSketchId(model.getId()); tModel.setCreator(model.getEditor()); tModel.setCreateDate(date); tModel.setLineId(line.getId()); tModel.setTotalNum(new BigDecimal(0)); tModel.setDateInfo(model.getDateInfo()); tModel.setType(Constants.ONE); tModel.setSortnum(sketchLineList.size()+1); tModel.setEditDate(tModel.getCreateDate()); tModel.setEditor(tModel.getCreator()); tModel.setIsdeleted(Constants.ZERO); tModel.setDistance(so.getDistance());// sketchLineList.add(tModel); tModel.setCustomerList( new ArrayList<>()); //ææè·¯å¾ for (Integer cIndex : routes){ if(cIndex ==0){ continue; //èµ·å§ç¹ä¸å¤ç } // JkSketchCustomer customer = model.getCustomerList().get(cIndex-1); // tModel.setTotalNum(tModel.getTotalNum().add(Constants.formatBigdecimal(customer.getTotalNum())));//éè´§é SketchCateModel cateModel = customerList.get(cIndex-1); tModel.setTotalNum(tModel.getTotalNum().add(Constants.formatBigdecimal(cateModel.getTotalNum())));//éè´§é for(int t=0;t<cateModel.getCustomerList().size();t++){ JkSketchCustomer customer = cateModel.getCustomerList().get(t); JkSketchCustomer cModel = new JkSketchCustomer(); cModel.setCreator(tModel.getCreator()); cModel.setOrderId(customer.getOrderId()); cModel.setCreateDate(tModel.getCreateDate()); cModel.setType(Constants.ONE); cModel.setTotalNum(customer.getTotalNum()); cModel.setDateInfo(model.getDateInfo()); cModel.setSortnum(tModel.getCustomerList().size()+1); cModel.setEditDate(tModel.getCreateDate()); cModel.setEditor(tModel.getCreator()); cModel.setIsdeleted(Constants.ZERO); cModel.setSketchId(model.getId()); cModel.setCustomerId(customer.getCustomerId()); if(t < cateModel.getCustomerList().size()-1){ long tdistance = (long)Clustering.distanceTo(customer, cateModel.getCustomerList().get(t+1)); tModel.setDistance(Constants.formatLongNum(tModel.getDistance()) +tdistance); totalDistance += tdistance; } tModel.getCustomerList().add(cModel); } tModel.setOrderNum( tModel.getCustomerList().size()); } } } if(sketchLineList!=null && sketchLineList.size()>0){ jkSketchLineMapper.update(null,new UpdateWrapper<JkSketchLine>().lambda() .set(JkSketchLine::getIsdeleted,Constants.ONE) .eq(JkSketchLine::getIsdeleted,Constants.ZERO) .eq(JkSketchLine::getType,Constants.ONE) .eq(JkSketchLine::getDateInfo,model.getDateInfo())); jkSketchCustomerMapper.update(null,new UpdateWrapper<JkSketchCustomer>().lambda() .set(JkSketchCustomer::getIsdeleted,Constants.ONE) .eq(JkSketchCustomer::getIsdeleted,Constants.ZERO) .eq(JkSketchCustomer::getType,Constants.ONE) .eq(JkSketchCustomer::getDateInfo,model.getDateInfo())); if(sketchLineList.size()>0){ jkSketchLineMapper.insert(sketchLineList); } for(JkSketchLine l : sketchLineList){ if(l.getCustomerList()!=null ){ for(JkSketchCustomer c :l.getCustomerList()){ c.setSketchLineId(l.getId()); } sketchCustomerList.addAll(l.getCustomerList()); } } if(sketchCustomerList.size()>0){ jkSketchCustomerMapper.insert(sketchCustomerList); } jkSketchMapper.update(null,new UpdateWrapper<JkSketch>().lambda() .eq(JkSketch::getId,model.getId() ) .eq(JkSketch::getJobId,model.getJobId() ) .set(JkSketch::getLineNum,sketchLineList.size() ) .set(JkSketch::getOptStatus,Constants.ONE)//å·²çæä¼å线路 .set(JkSketch::getDistance,totalDistance) .set(JkSketch::getPlanLineInfo,"æè¿ä¸æ¬¡çº¿è·¯ä¼åæåï¼ä¼ååæ»è·ç¦»ï¼"+(totalDistance/1000)+"å ¬éï¼") .set(JkSketch::getStatus,Constants.TWO) .set(JkSketch::getPlanLineEndDate,date)); }else{ jkSketchMapper.update(null,new UpdateWrapper<JkSketch>().lambda() .eq(JkSketch::getId,model.getId() ) .eq(JkSketch::getJobId,model.getJobId() ) .set(JkSketch::getPlanLineInfo,"æè¿ä¸æ¬¡çº¿è·¯ä¼å失败,æªæ¾å°æä¼è·¯çº¿ï¼") .set(JkSketch::getStatus,Constants.THREE) .set(JkSketch::getPlanLineEndDate,date)); } } private void dealSearchSolutionOld(JkSketch model, TspSolver.DataModel dataModel) { Date date = new Date(); List<TspSolverSolutions> solutions = dataModel.getSolutions(); List<JkSketchLine> sketchLineList = new ArrayList<>();