| | |
| | | import com.doumee.core.exception.BusinessException; |
| | | import com.google.ortools.Loader; |
| | | import com.google.ortools.constraintsolver.*; |
| | | import com.google.protobuf.Duration; |
| | | import com.google.protobuf.DurationOrBuilder; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import com.google.ortools.constraintsolver.mainJNI; |
| | | |
| | |
| | | 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); |
| | | |
| | |
| | | // 打印路线 |
| | | 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); |
| | | |
| | |
| | | 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); |
| | |
| | | |
| | | // 定义回调函数至每条路线 |
| | | routing.setArcCostEvaluatorOfAllVehicles(transitCallbackIndex); |
| | | // 增加距离维度约束 |
| | | routing.addDimension(transitCallbackIndex, 0, 300000000, |
| | | /* 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) -> { |
| | | int fromNode = manager.indexToNode(fromIndex); |
| | | return data.customerDemands[fromNode]; |
| | | }); |
| | | for (int d = 0; d < data.vehicleMaxNodes.length; d++) { |
| | | // 增加距离维度约束 |
| | | routing.addDimension(transitCallbackIndex1, 0, data.vehicleMaxNodes[d], |
| | | true, |
| | | "customer_"+d); |
| | | RoutingDimension distanceDimension1 = routing.getMutableDimension("customer_"+d); |
| | | distanceDimension1.setGlobalSpanCostCoefficient(100); |
| | | } |
| | | // 添加容量限制 |
| | | final int demandCallbackIndex = routing.registerUnaryTransitCallback((long fromIndex) -> { |
| | | int fromNode = manager.indexToNode(fromIndex); |
| | | return data.demands[fromNode]; |
| | | }); |
| | | routing.addDimensionWithVehicleCapacity(demandCallbackIndex, 0, data.vehicleCapacities, true, "Capacity"); |
| | | // routing.addDimensionWithVehicleTransits() |
| | | Solver solver = routing.solver(); |
| | | |
| | | //设置搜索方法 |
| | | Solver solver = routing.solver(); |
| | | //设置搜索方法( |
| | | RoutingSearchParameters searchParameters = |
| | | main.defaultRoutingSearchParameters() |
| | | .toBuilder() |
| | | .setTimeLimit(Duration.newBuilder().setSeconds(60*60*6).build())//最久1小时 |
| | | .setFirstSolutionStrategy(FirstSolutionStrategy.Value.PATH_CHEAPEST_ARC) |
| | | .build(); |
| | | |
| | |
| | | // 打印路线 |
| | | 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; |
| | |
| | | |
| | | //每一个点的商品的数量 |
| | | public long[] demands; |
| | | public long[] customerDemands; |
| | | //车辆最大容载 |
| | | public long[] vehicleCapacities ; |
| | | public long[] vehicleMaxNodes ; |
| | | public long[][] distanceMatrix ; |
| | | |
| | | public List<TspSolverSolutions> getSolutions() { |
| | |
| | | this.solutions = solutions; |
| | | } |
| | | |
| | | public void initDataInfo(int vehicleNumber1, long[] demands1, long[] vehicleCapacities1, long[][] distanceMatrix1){ |
| | | 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 = 100; |
| | | vehicleNumber = 7; |
| | | 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]; |
| | | int total0 =0; |
| | | for (int i = 0; i <vehicleNumber ; i++) { |
| | | long tem = (long) (Math.random() * 1000 + 20000); |
| | | vehicleCapacities[i] = tem; |
| | | 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++) { |
| | |
| | | } |
| | | } |
| | | |
| | | 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}, |