server/system_service/src/main/java/com/doumee/core/utils/Constants.java
@@ -1,9 +1,7 @@ package com.doumee.core.utils; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -25,9 +23,7 @@ public static final String HEADER_USER_TOKEN = "dm_user_token"; public static final String REDIS_USER_KEY = "user_token_list_"; public static final String REDIS_TOKEN_KEY = "token_"; public static final String WMS_IN_REPERTOTY_CODE_LIST = "WMS_IN_REPERTOTY_CODE_LIST"; public static final String REDIS_HK_TOKEN_KEY = "hk_token_"; public static boolean IS_AUTOCALL_WORKING = false; public static final String HK_TOKEN_VALIDITY = "HK_TOKEN_VALIDITY"; public static final String[] ALL_SPELL_LIST_FIRST = new String[]{"A", "B", "C", "D", "E", "F", "G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"}; public static final int ZERO = 0 ; @@ -38,8 +34,6 @@ public static final String HK_PARAM ="HK_PARAM" ; public static final String HK_WEBSITE_DOMAIN_URL ="HK_WEBSITE_DOMAIN_URL" ; public static final String LED_CONTENT_SPEED ="LED_CONTENT_SPEED" ; public static final String SYSTEM_TITLE ="SYSTEM_TITLE" ; public static final String SYSTEM_SUBTITLE ="SYSTEM_SUBTITLE" ; public static final String HK_HOST ="HK_HOST" ; public static final String HK_APPKEY ="HK_APPKEY" ; public static final String LOGIN_OUT_URL ="LOGIN_OUT" ; @@ -64,19 +58,6 @@ 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" ; public static final String JK_PLAN_DISTANCE_CLUSTER ="JK_PLAN_DISTANCE_CLUSTER" ; public static final String HK_PUSH_THIRD_URL ="HK_PUSH_THIRD_URL" ; public static final String API_KEY ="API_KEY" ; public static final String JDY_APPID = "JDY_APPID"; public static final String JDY_ENTRY_ID ="JDY_ENTRY_ID"; public static final String JDY_API_KEY ="JDY_API_KEY" ; public static final String JDY_CONFIG ="JDY_CONFIG" ; public static final String JDY_COMPANY_ROOT_NO ="JDY_COMPANY_ROOT_NO" ; public static final String JDY_SECRET ="JDY_SECRET"; public static final String JDY_MEMBER_PUSH_STATUS_URL ="JDY_MEMBER_PUSH_STATUS_URL"; public static final String JDY_API_HOST = "JDY_API_HOST"; /** * 操作类型,用于做接口验证分组 @@ -102,6 +83,7 @@ public static final String WEATHER_CONFIG ="WEATHER_CONFIG" ; public static final String REQUEST_URL ="REQUEST_URL" ; public static final String LOCATION ="LOCATION" ; public static final String API_KEY ="API_KEY" ; public static final String CABINET_CONFIG ="CABINET_CONFIG" ; public static final String BLOW_TIME ="BLOW_TIME" ; public static final String PRESSURE ="PRESSURE" ; @@ -234,7 +216,6 @@ public static boolean DEALING_HK_NOTICE_LIST = false; public static boolean DEALING_FROM_HK_VISIT = false; public static boolean DEALING_HK_EMPOWER = false; public static boolean DEALING_DUANLUQI_CLOSE = false; public static boolean DEALING_HK_EMPOWER_DETAIL = false; public static boolean DEALING_HK_EMPOWER_RESULT = false; public static boolean DEALING_HK_PARKBOOK = false; @@ -305,15 +286,6 @@ public static final int depart = 3; public static final int custom = 4; public static final int self = -1; } //类型 0门禁 1车库 2LED 3广播点 4广播设备 5断路器空开 public interface DEVICE_TYPE{ public static final int door = 0; public static final int park = 1; public static final int led = 2; public static final int broadcaset = 3; public static final int broadcasetChannel = 4; public static final int duanluqi = 5; } /** @@ -560,7 +532,6 @@ public static final String COFFEE_BEAN_TASK ="COFFEE_BEAN_TASK"; public static final String IN_REPERTOTY_CODE ="IN_REPERTOTY_CODE"; public static final String HOME_IMAGE ="HOME_IMAGE"; public static final String DD_TALK ="DD_TALK"; @@ -568,6 +539,8 @@ public static final String APP_SECRET ="APP_SECRET"; public static final String ACCESS_TOKEN ="ACCESS_TOKEN"; public static final String AGENT_ID ="AGENT_ID"; public static final String WX_PLATFORM = "WX_PLATFORM"; @@ -598,11 +571,6 @@ public static final String BIGSCREEN_UUID ="BIGSCREEN_UUID"; public static final String IMPORTING_GAS ="IMPORTING_GAS"; public static final String ERP_TOKEN ="ERP_TOKEN"; public static final String HK_REGIONS ="HK_REGIONS"; public static final String HK_CAMERAS ="HK_CAMERAS"; public static final String HK_REGIONS_TREE ="HK_REGIONS_TREE"; public static final String HK_FIRE_DEVICE="HK_FIRE_DEVICE"; public static final String HK_SENSOR="HK_SENSOR"; public static final long EXPIRE_TIME = 7200; public static final String INTERNAL_TOKEN ="INTERNAL_TOKEN"; @@ -797,73 +765,14 @@ } } public static String getWmsAreasNameByCode(String listStr,String code) { try { JSONArray list = JSONObject.parseArray(listStr ); if(list!=null && list.size()>0){ for (int i = 0; i < list.size(); i++) { if(StringUtils.equals(list.getJSONObject(i).getString("code"),code)){ return list.getJSONObject(i).getString("name"); } } } }catch (Exception e){ } return null; } public static List<JSONObject> getWmsAreasList(){ List<JSONObject> list = new ArrayList<>(); JSONObject t = new JSONObject(); t.put("code","01"); t.put("name","蚌埠菴烟厂"); list.add(t); t = new JSONObject(); t.put("code","02"); t.put("name","芜湖卷烟厂"); list.add(t); t = new JSONObject(); t.put("code","03"); t.put("name","合肥卷烟厂"); list.add(t); t = new JSONObject(); t.put("code","04"); t.put("name","阜阳卷烟厂"); list.add(t); t = new JSONObject(); t.put("code","04206"); t.put("name","合肥卷烟厂鞍山库"); list.add(t); t = new JSONObject(); t.put("code","05"); t.put("name","滁州卷烟厂"); list.add(t); t = new JSONObject(); t.put("code","06"); t.put("name","蒙城香茄生产部"); list.add(t); t = new JSONObject(); t.put("code","07"); t.put("name","重庆中烟工业有限责任公司"); list.add(t); t = new JSONObject(); t.put("code","08"); t.put("name","陕西中烟工业有限责任公司"); list.add(t); t = new JSONObject(); t.put("code","09"); t.put("name","特殊纪念版"); list.add(t); return list; } public static void main(String[] args) { System.out.println(JSONObject.toJSONString(getWmsAreasList())); // getChinesePingyin("DDaa江萍的对对对"); // System.out.println(DateUtil.getShortTime(new Date())); // System.out.println( "2025-01-14 10:50:56".substring(0,10)); // System.out.println(Constants.checkCarNo("皖AA10991")); // System.out.println(Constants.getVehiclePlateNo("湘B140D17").getDescription()); // System.out.println(Constants.getVehiclePlateNo("宿AP0637").getDescription()); // 0789150665 C97B092F 0789150561 @@ -1024,7 +933,6 @@ LEAVED(10, "已离园 ","车辆从{data}离场 " ), OVER_NUMBER(11, "已过号","超时未到指定月台自动过号" ), CHANGE_GROUP(12, "更换月台组","从【{data}】更换到【{data1}】" ), BACK_TO_WAIT_SIGNIN(13, "重新签到","重新签到" ), ; // 成员变量 @@ -1614,14 +1522,6 @@ return JSONObject.toJSONString(map); } public interface MqttTopic{ String mts_attr = "/dev/+/+/attr/json";//属性topic String mts_status = "/dev/+/+/status/json";//状态topic String mts_event= "/dev/+/+/event/json";//事件topic String mts_echo= "/dev/+/+/echo/json";//消息回复topic String mts_cmd= "/dev/$CATE/$DEVID/cmd/json";//命令topic String mts_resp= "/dev/+/+/resp/json";//命令响应topic } public enum WarningConfig { @@ -1629,17 +1529,12 @@ GRID_TIME_OUT_INFO(10003, "【钥匙柜】开门超时未关闭",0), KEY_TIME_OUT_BACK(10004, "【钥匙柜】钥匙超时未归还",0), AF_QYRQ(131588, "【安防事件】区域入侵",1), AF_QUPD(131668, "【安防事件】区域跑动",1), AF_RYLG(422000001, "【安防事件】人员离岗",1), AF_RYLG_CUSTOM(-422000001, "【安防事件】人员离岗(定制后)",1), AF_QUPD(131592, "【安防事件】区域跑动",1), AF_RYLG(131603, "【安防事件】人员离岗",1), AF_KYSCX(131585, "【安防事件】跨越生产线",1), AF_XFTDZS(422000000, "【安防事件】消防通道阻塞",1), XF_SYGDBJ(254215, "【消防事件】水压过低报警",1), XF_SYGGBJ(254216, "【消防事件】水压过高报警",1), XF_HZBJ(254047, "【消防事件】火灾报警",1), XF_YWGDBJ(254331, "【消防事件】液位过低报警",1), XF_YWGGBJ(254332, "【消防事件】液位过高报警",1), AF_DZWL(327681, "【安防事件】电子围栏",1), XF_SYBJ(253956, "【消防事件】水压报警",1), XF_HZBJ(253999, "【消防事件】火灾报警",1), XF_YWBJ(254047, "【消防事件】液位报警",1), ; // 成员变量 private int key; server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/ClusterCustomKMeans.java
@@ -1,7 +1,9 @@ package com.doumee.core.tsp; import java.math.BigDecimal; import java.util.*; 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; @@ -76,7 +78,6 @@ 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()); @@ -84,21 +85,6 @@ } 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; server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/Clustering.java
@@ -40,12 +40,11 @@ return clusters; } public static double distanceTo(JkSketchCustomer self, JkSketchCustomer other) { // ====标记==忽略交通规划距离===== /*List<DistanceMapParam> distanceMapParamList =JkSketchServiceImpl.getListFromJsonStr(self.getDistanceJson()); 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() 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,15 +96,16 @@ // 定义回调函数至每条路线 routing.setArcCostEvaluatorOfAllVehicles(transitCallbackIndex); routing.addDimension(transitCallbackIndex, 0, 30000000, /* routing.addDimension(transitCallbackIndex, 0, 30000000, true, "Distance"); RoutingDimension distanceDimension = routing.getMutableDimension("Distance"); distanceDimension.setGlobalSpanCostCoefficient(100);*/ distanceDimension.setGlobalSpanCostCoefficient(100); */ // 注册回调函数 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/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<>();