package com.doumee.core.utils.tsp; import com.doumee.core.constants.ResponseStatus; import com.doumee.core.exception.BusinessException; import com.google.ortools.Loader; import com.google.ortools.constraintsolver.*; import lombok.extern.slf4j.Slf4j; import com.google.protobuf.Internal.IntListAdapter.IntConverter; import com.google.ortools.constraintsolver.mainJNI; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @Slf4j public class TspSolver { public static void main(String[] args) throws Exception { DataModel data = new DataModel(); data.initDataList();//构造数据 startSearch(data); /*// 初始化数据模型 Loader.loadNativeLibraries(); DataModel data = new DataModel(); data.initDataList();//构造数据 long start =System.currentTimeMillis(); System.out.println("=============start=========="+start); //创建求解器manager对象,初始化求解器数据 RoutingIndexManager manager = new RoutingIndexManager(data.distanceMatrix.length, data.vehicleNumber, data.depot); // 初始化求解器 RoutingModel routing = new RoutingModel(manager); // // 注册回调函数 final int transitCallbackIndex = routing.registerTransitCallback((long fromIndex, long toIndex) -> { int fromNode = manager.indexToNode(fromIndex); int toNode = manager.indexToNode(toIndex); return data.distanceMatrix[fromNode][toNode]; }); // 定义回调函数至每条路线 routing.setArcCostEvaluatorOfAllVehicles(transitCallbackIndex); // 增加距离维度约束 routing.addDimension(transitCallbackIndex, 0, 30000, true, "Distance"); RoutingDimension distanceDimension = routing.getMutableDimension("Distance"); distanceDimension.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"); Solver solver = routing.solver(); //设置搜索方法 RoutingSearchParameters searchParameters = main.defaultRoutingSearchParameters() .toBuilder() .setFirstSolutionStrategy(FirstSolutionStrategy.Value.PATH_CHEAPEST_ARC) .build(); // 执行算法 Assignment solution = routing.solveWithParameters(searchParameters); // 打印路线 printSolution(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"); */} public static void startSearch(DataModel data) { // 初始化数据模型 Loader.loadNativeLibraries(); long start =System.currentTimeMillis(); System.out.println("=============start=========="+start); //创建求解器manager对象,初始化求解器数据 RoutingIndexManager manager = new RoutingIndexManager(data.distanceMatrix.length, data.vehicleNumber, data.depot); // 初始化求解器 RoutingModel routing = new RoutingModel(manager); // 注册回调函数 final int transitCallbackIndex = routing.registerTransitCallback((long fromIndex, long toIndex) -> { int fromNode = manager.indexToNode(fromIndex); int toNode = manager.indexToNode(toIndex); return data.distanceMatrix[fromNode][toNode]; }); // 定义回调函数至每条路线 routing.setArcCostEvaluatorOfAllVehicles(transitCallbackIndex); // 增加距离维度约束 routing.addDimension(transitCallbackIndex, 0, 300000000, true, "Distance"); RoutingDimension distanceDimension = routing.getMutableDimension("Distance"); distanceDimension.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(); //设置搜索方法 RoutingSearchParameters searchParameters = main.defaultRoutingSearchParameters() .toBuilder() .setFirstSolutionStrategy(FirstSolutionStrategy.Value.PATH_CHEAPEST_ARC) .build(); // 执行算法 Assignment solution = routing.solveWithParameters(searchParameters); if(solution ==null){ throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"未找到最优路线!"); } // 打印路线 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"); } static void resultSolution( DataModel data, RoutingModel routing, RoutingIndexManager manager, Assignment solution) { long maxRouteDistance = 0; List mapList = new ArrayList<>(); for (int i = 0; i < data.vehicleNumber; ++i) { TspSolverSolutions t = new TspSolverSolutions(); t.setLineIndex(i); long index = routing.start(i); log.info("Route for Vehicle " + i + ":"); long routeDistance = 0; int routeDemand = 0; String route = ""; List routeList = new ArrayList<>(); while (!routing.isEnd(index)) { int tNode = manager.indexToNode(index); routeList.add( tNode); route += tNode+ " -> "; routeDemand += data.demands[tNode]; long previousIndex = index; index = solution.value(routing.nextVar(index)); routeDistance += routing.getArcCostForVehicle(previousIndex, index, i); } int tNode = manager.indexToNode(index); routeList.add( tNode); log.info(route + tNode); t.setRouteIndex(routeList); t.setDistance(routeDistance); log.info("Distance of the route: " + routeDistance + "m"+" Capacity of the route:"+routeDemand+"/"+data.vehicleCapacities[i]); maxRouteDistance = Math.max(routeDistance, maxRouteDistance); mapList.add(t); } data.setSolutions(mapList); log.info("Maximum of the route distances: " + maxRouteDistance + "m"); } static void printSolution( DataModel data, RoutingModel routing, RoutingIndexManager manager, Assignment solution) { long maxRouteDistance = 0; for (int i = 0; i < data.vehicleNumber; ++i) { long index = routing.start(i); log.info("Route for Vehicle " + i + ":"); long routeDistance = 0; int routeDemand = 0; String route = ""; List routeList = new ArrayList<>(); while (!routing.isEnd(index)) { int tNode = manager.indexToNode(index); routeList.add( tNode); route += tNode+ " -> "; routeDemand += data.demands[tNode]; long previousIndex = index; index = solution.value(routing.nextVar(index)); routeDistance += routing.getArcCostForVehicle(previousIndex, index, i); } log.info(route + manager.indexToNode(index)); log.info("Distance of the route: " + routeDistance + "m"+" Capacity of the route:"+routeDemand+"/"+data.vehicleCapacities[i]); maxRouteDistance = Math.max(routeDistance, maxRouteDistance); } log.info("Maximum of the route distances: " + maxRouteDistance + "m"); } public static void startOptimize(){ } public static class DataModel { //距离矩阵 public int lenght; //最大车辆限制 public int vehicleNumber; public List solutions; //起点 public static final int depot = 0; //每一个点的商品的数量 public long[] demands; //车辆最大容载 public long[] vehicleCapacities ; public long[][] distanceMatrix ; public List getSolutions() { return solutions; } public void setSolutions(List solutions) { this.solutions = solutions; } public void initDataInfo(int vehicleNumber1, long[] demands1, long[] vehicleCapacities1, long[][] distanceMatrix1){ this.demands = demands1; this.vehicleNumber = vehicleNumber1; this.vehicleCapacities=vehicleCapacities1; this.distanceMatrix=distanceMatrix1; } public void initDataList(){ lenght = 100; vehicleNumber = 7; demands = new long[lenght]; vehicleCapacities =new long[vehicleNumber]; distanceMatrix = new long[lenght][lenght]; int total0 =0; for (int i = 0; i