OR-Tools求解车辆路径规划(VRP)返回错误0距离结果问题求助
车辆路径规划(VRP)结果总距离显示为0的问题排查与解决
问题现象
使用首行首列设为0的距离矩阵运行OR-Tools VRP代码后,出现车辆遍历所有地点总距离为0的错误结果,调整车辆最大行驶距离和全局跨度成本系数后异常仍存在。
问题代码
def create_data_model(): """Stores the data for the problem.""" data = {} data["distance_matrix"] = [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 14.0, 201.0, 154.0, 154.0], [0.0, 46.0, 0.0, 165.0, 118.0, 118.0], [0.0, 70.0, 54.0, 0.0, 110.0, 110.0], [0.0, 24.0, 26.0, 187.0, 0.0, 140.0], [0.0, 28.0, 0.0, 199.0, 152.0, 0.0]] data["num_vehicles"] = 3 data["depot"] = 0 return data def print_solution(data, manager, routing, solution): """Prints solution on console.""" print(f"Objective: {solution.ObjectiveValue()}") max_route_distance = 0 for vehicle_id in range(data["num_vehicles"]): index = routing.Start(vehicle_id) plan_output = f"Route for vehicle {vehicle_id}:\n" route_distance = 0 while not routing.IsEnd(index): plan_output += f" {manager.IndexToNode(index)} -> " previous_index = index index = solution.Value(routing.NextVar(index)) route_distance += routing.GetArcCostForVehicle( previous_index, index, vehicle_id ) plan_output += f"{manager.IndexToNode(index)}\n" plan_output += f"Distance of the route: {route_distance}m\n" print(plan_output) max_route_distance = max(route_distance, max_route_distance) print(f"Maximum of the route distances: {max_route_distance}m") def main(): """Entry point of the program.""" # Instantiate the data problem. data = create_data_model() # Create the routing index manager. manager = pywrapcp.RoutingIndexManager( len(data["distance_matrix"]), data["num_vehicles"], data["depot"] ) # Create Routing Model. routing = pywrapcp.RoutingModel(manager) # Create and register a transit callback. def distance_callback(from_index, to_index): """Returns the distance between the two nodes.""" # Convert from routing variable Index to distance matrix NodeIndex. from_node = manager.IndexToNode(from_index) to_node = manager.IndexToNode(to_index) return data["distance_matrix"][from_node][to_node] transit_callback_index = routing.RegisterTransitCallback(distance_callback) # Define cost of each arc. routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # Add Distance constraint. dimension_name = "Distance" routing.AddDimension( transit_callback_index, 0, # no slack 5000, # vehicle maximum travel distance True, # start cumul to zero dimension_name, ) distance_dimension = routing.GetDimensionOrDie(dimension_name) distance_dimension.SetGlobalSpanCostCoefficient(100) # Setting first solution heuristic. search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC ) # Solve the problem. solution = routing.SolveWithParameters(search_parameters) # Print solution on console. if solution: print_solution(data, manager, routing, solution) else: print("No solution found !")
错误输出
Objective: 0 Route for vehicle 0: 0 -> 0 Distance of the route: 0m Route for vehicle 1: 0 -> 0 Distance of the route: 0m Route for vehicle 2: 0 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 Distance of the route: 0m Maximum of the route distances: 0m
错误原因
OR-Tools的Routing模块默认使用整数类型处理成本/距离值,当传入浮点数时,会被自动截断为整数。你的距离矩阵中所有值都是带.0的浮点数,被截断后全部变成0,导致所有路径的成本计算为0,最终出现异常结果。
首行首列设为0的操作本身没有问题,问题核心在于浮点数与OR-Tools整数成本机制不兼容。
解决方法
将距离矩阵中的浮点数改为整数,或者在距离回调函数中将浮点数转换为整数,确保传入OR-Tools的成本值为整数类型。
修正后的代码示例
修改create_data_model函数中的distance_matrix,去掉.0使用整数:
def create_data_model(): """Stores the data for the problem.""" data = {} data["distance_matrix"] = [[0, 0, 0, 0, 0, 0], [0, 0, 14, 201, 154, 154], [0, 46, 0, 165, 118, 118], [0, 70, 54, 0, 110, 110], [0, 24, 26, 187, 0, 140], [0, 28, 0, 199, 152, 0]] data["num_vehicles"] = 3 data["depot"] = 0 return data
或者如果需要保留浮点数计算,在回调函数中转换为整数(比如乘以100保留两位小数后转整,根据需求调整):
def distance_callback(from_index, to_index): """Returns the distance between the two nodes.""" from_node = manager.IndexToNode(from_index) to_node = manager.IndexToNode(to_index) # 转换为整数,这里直接取整,可根据精度需求调整 return int(data["distance_matrix"][from_node][to_node])
修正后效果
运行修正后的代码,系统会正确计算路径距离,输出的路由距离不再为0,Objective值也会对应实际的路径成本总和。
内容的提问来源于stack exchange,提问作者Charles T
相关产品推荐
相关产品推荐

