具有距离约束的 OR-tools CVRP 不起作用
OR-tools CVRP with a distance constraint not working
我正在使用 OR 工具代码来优化具有距离和容量限制的公交路线。这是我得到的输出:
Route for vehicle 0:
Stop 0 Students(2) -> Stop 3 Students(37) -> Stop 5 Students(37)
Duration of the route: 48m
Number of students of the route: 37
Route for vehicle 1:
Stop 6 Students(4) -> Stop 4 Students(38) -> Stop 9 Students(41) -> Stop 19 Students(45) -> Stop 5 Students(45)
Duration of the route: 55m
Number of students of the route: 45
Route for vehicle 2:
Stop 7 Students(4) -> Stop 1 Students(39) -> Stop 8 Students(40) -> Stop 18 Students(43) -> Stop 5 Students(43)
Duration of the route: 56m
Number of students of the route: 43
Route for vehicle 3:
Stop 11 Students(1) -> Stop 10 Students(2) -> Stop 20 Students(12) -> Stop 23 Students(43) -> Stop 5 Students(43)
Duration of the route: 54m
Number of students of the route: 43
Route for vehicle 4:
Stop 12 Students(1) -> Stop 2 Students(36) -> Stop 22 Students(39) -> Stop 21 Students(45) -> Stop 5 Students(45)
Duration of the route: 58m
Number of students of the route: 45
Route for vehicle 5:
Stop 13 Students(1) -> Stop 14 Students(4) -> Stop 5 Students(4)
Duration of the route: 60m
Number of students of the route: 4
Route for vehicle 6:
Stop 16 Students(3) -> Stop 15 Students(6) -> Stop 17 Students(12) -> Stop 5 Students(12)
Duration of the route: 57m
Number of students of the route: 12
Route for vehicle 7:
Stop 24 Students(3) -> Stop 5 Students(3)
Duration of the route: 0m
Number of students of the route: 3
Route for vehicle 8:
Stop 25 Students(3) -> Stop 5 Students(3)
Duration of the route: 0m
Number of students of the route: 3
Total duration of all routes: 388m
Total number of students of all routes: 235
车辆 0-6 的持续时间似乎是正确的,但车辆 7 和 8 的持续时间为 0。我多次检查矩阵,看来我的 matrix/data 不是问题所在。我认为 def print_solution 下的 while not 部分可能有问题,但我不确定如何更改它。因为只有两站,所以我认为不是 运行 while not 部分将每条路线的持续时间相加。
#@CVRP ()
"""Capacited Vehicles Routing Problem (CVRP)."""
!pip install ortools
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp
from google.colab import drive
import pandas as pd
import numpy as np
import csv
reader = csv.reader(open("Duration.csv", "r"), delimiter=",")
x = list(reader)
result = np.array(x).astype("float")
def create_data_model():
"""Stores the data for the problem."""
data = {}
data['distance_matrix'] = result
# stops: huayuan, aocheng1, aocheng2, aocheng3, aocheng4, school, yangguang, aocheng back, olympics village, diamond hill
# wuyiyangguang, hopeland, haotian, !!shanhaitian!!, tianjiaoyuan, olympics tower, international building, tangchen, !!astor hotel!!,
# jinlanque, hongzonglv, lanwan, !!wangzuo!!, !!haiyi back!!, haiyi, liusuyuan, !!muxuyuan!!, swan lake, bandao, b!!andao back!!, mingquan, kameier, !!fulijinmenhu!!
#data['demands'] = [2, 35, 35, 35, 34, 0, 4, 4, 1, 3, 1, 1, 1, 0, 1, 3, 3, 3, 0, 6, 3, 4, 0, 0, 10, 6, 0, 3, 31, 0, 3, 3, 0]
#UPDATED stop names:huayuan, aocheng1, aocheng2, aocheng3, aocheng4, school, yangguang, aocheng back, olympics village, diamond hill
# wuyiyangguang, hopeland, haotian, tianjiaoyuan, olympics tower, international building, tangchen,
# jinlanque, hongzonglv, lanwan, haiyi, liusuyuan, swan lake, bandao, mingquan, kameier
data['demands'] = [2, 35, 35, 35, 34, 0, 4, 4, 1, 3, 1, 1, 1, 1, 3, 3, 3, 6, 3, 4, 10, 6, 3, 31, 3, 3]
data['vehicle_capacities'] = [45, 45, 45, 45, 45, 45, 49, 15, 15]
data['num_vehicles'] = 9
data['starts'] = [0, 6, 7, 11, 12, 13, 16, 24, 25]
data['ends'] = [5, 5, 5, 5, 5, 5, 5, 5, 5]
return data
def print_solution(data, manager, routing, solution):
"""Prints solution on console."""
total_distance = 0
total_load = 0
for vehicle_id in range(data['num_vehicles']):
index = routing.Start(vehicle_id)
plan_output = 'Route for vehicle {}:\n'.format(vehicle_id)
route_distance = 0
route_load = 0
while not routing.IsEnd(index):
node_index = manager.IndexToNode(index)
route_load += data['demands'][node_index]
plan_output += ' Stop {0} Students({1}) -> '.format(node_index, route_load)
previous_index = index
index = solution.Value(routing.NextVar(index))
route_distance += routing.GetArcCostForVehicle(
previous_index, index, vehicle_id)
plan_output += ' Stop {0} Students({1})\n'.format(manager.IndexToNode(index),
route_load)
plan_output += 'Duration of the route: {}m\n'.format(route_distance)
plan_output += 'Number of students of the route: {}\n'.format(route_load)
print(plan_output)
total_distance += route_distance
total_load += route_load
print('Total duration of all routes: {}m'.format(total_distance))
print('Total number of students of all routes: {}'.format(total_load))
def main():
"""Solve the CVRP problem."""
# Instantiate the data problem.
data = create_data_model()
# Create the routing index manager.
manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),
data['num_vehicles'], data['starts'],
data['ends'])
# 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 Capacity constraint.
def demand_callback(from_index):
"""Returns the demand of the node."""
# Convert from routing variable Index to demands NodeIndex.
from_node = manager.IndexToNode(from_index)
return data['demands'][from_node]
demand_callback_index = routing.RegisterUnaryTransitCallback(
demand_callback)
dimension_name = 'Capacity'
routing.AddDimensionWithVehicleCapacity(
demand_callback_index,
0, # null capacity slack
data['vehicle_capacities'], # vehicle maximum capacities
True, # start cumul to zero
dimension_name)
# Add Distance constraint.
dimension_name = 'Distance'
routing.AddDimension(
transit_callback_index,
0, # no slack
100, # 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)
search_parameters.local_search_metaheuristic = (
routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)
search_parameters.log_search = True
search_parameters.time_limit.FromSeconds(5)
# Solve the problem.
solution = routing.SolveWithParameters(search_parameters)
# Print solution.
if solution:
print_solution(data, manager, routing, solution)
#else:
#print('no solution')
if __name__ == '__main__':
main()
data = create_data_model()
#print(len(data['distance_matrix']))
#print(len(data['distance_matrix'][0]))
如果有人能帮助我,我将不胜感激!
默认情况下,空路由 Start -> End
的 arc 成本 为零。
因此,当使用 routing.GetArcCostForVehicle(previous_index, index, vehicle_id)
.
时,您的最后两条车辆路线为空,将 return 0
您可以使用 RoutingModel::ConsiderEmptyRouteCostsForVehicle(bool consider_costs, int vehicle)
启用费用。
恕我直言,这样的事情应该可行:
for v in range(manager.GetNumberOfVehicles()):
routing.ConsiderEmptyRouteCostsForVehicle(true, v)
我正在使用 OR 工具代码来优化具有距离和容量限制的公交路线。这是我得到的输出:
Route for vehicle 0:
Stop 0 Students(2) -> Stop 3 Students(37) -> Stop 5 Students(37)
Duration of the route: 48m
Number of students of the route: 37
Route for vehicle 1:
Stop 6 Students(4) -> Stop 4 Students(38) -> Stop 9 Students(41) -> Stop 19 Students(45) -> Stop 5 Students(45)
Duration of the route: 55m
Number of students of the route: 45
Route for vehicle 2:
Stop 7 Students(4) -> Stop 1 Students(39) -> Stop 8 Students(40) -> Stop 18 Students(43) -> Stop 5 Students(43)
Duration of the route: 56m
Number of students of the route: 43
Route for vehicle 3:
Stop 11 Students(1) -> Stop 10 Students(2) -> Stop 20 Students(12) -> Stop 23 Students(43) -> Stop 5 Students(43)
Duration of the route: 54m
Number of students of the route: 43
Route for vehicle 4:
Stop 12 Students(1) -> Stop 2 Students(36) -> Stop 22 Students(39) -> Stop 21 Students(45) -> Stop 5 Students(45)
Duration of the route: 58m
Number of students of the route: 45
Route for vehicle 5:
Stop 13 Students(1) -> Stop 14 Students(4) -> Stop 5 Students(4)
Duration of the route: 60m
Number of students of the route: 4
Route for vehicle 6:
Stop 16 Students(3) -> Stop 15 Students(6) -> Stop 17 Students(12) -> Stop 5 Students(12)
Duration of the route: 57m
Number of students of the route: 12
Route for vehicle 7:
Stop 24 Students(3) -> Stop 5 Students(3)
Duration of the route: 0m
Number of students of the route: 3
Route for vehicle 8:
Stop 25 Students(3) -> Stop 5 Students(3)
Duration of the route: 0m
Number of students of the route: 3
Total duration of all routes: 388m
Total number of students of all routes: 235
车辆 0-6 的持续时间似乎是正确的,但车辆 7 和 8 的持续时间为 0。我多次检查矩阵,看来我的 matrix/data 不是问题所在。我认为 def print_solution 下的 while not 部分可能有问题,但我不确定如何更改它。因为只有两站,所以我认为不是 运行 while not 部分将每条路线的持续时间相加。
#@CVRP ()
"""Capacited Vehicles Routing Problem (CVRP)."""
!pip install ortools
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp
from google.colab import drive
import pandas as pd
import numpy as np
import csv
reader = csv.reader(open("Duration.csv", "r"), delimiter=",")
x = list(reader)
result = np.array(x).astype("float")
def create_data_model():
"""Stores the data for the problem."""
data = {}
data['distance_matrix'] = result
# stops: huayuan, aocheng1, aocheng2, aocheng3, aocheng4, school, yangguang, aocheng back, olympics village, diamond hill
# wuyiyangguang, hopeland, haotian, !!shanhaitian!!, tianjiaoyuan, olympics tower, international building, tangchen, !!astor hotel!!,
# jinlanque, hongzonglv, lanwan, !!wangzuo!!, !!haiyi back!!, haiyi, liusuyuan, !!muxuyuan!!, swan lake, bandao, b!!andao back!!, mingquan, kameier, !!fulijinmenhu!!
#data['demands'] = [2, 35, 35, 35, 34, 0, 4, 4, 1, 3, 1, 1, 1, 0, 1, 3, 3, 3, 0, 6, 3, 4, 0, 0, 10, 6, 0, 3, 31, 0, 3, 3, 0]
#UPDATED stop names:huayuan, aocheng1, aocheng2, aocheng3, aocheng4, school, yangguang, aocheng back, olympics village, diamond hill
# wuyiyangguang, hopeland, haotian, tianjiaoyuan, olympics tower, international building, tangchen,
# jinlanque, hongzonglv, lanwan, haiyi, liusuyuan, swan lake, bandao, mingquan, kameier
data['demands'] = [2, 35, 35, 35, 34, 0, 4, 4, 1, 3, 1, 1, 1, 1, 3, 3, 3, 6, 3, 4, 10, 6, 3, 31, 3, 3]
data['vehicle_capacities'] = [45, 45, 45, 45, 45, 45, 49, 15, 15]
data['num_vehicles'] = 9
data['starts'] = [0, 6, 7, 11, 12, 13, 16, 24, 25]
data['ends'] = [5, 5, 5, 5, 5, 5, 5, 5, 5]
return data
def print_solution(data, manager, routing, solution):
"""Prints solution on console."""
total_distance = 0
total_load = 0
for vehicle_id in range(data['num_vehicles']):
index = routing.Start(vehicle_id)
plan_output = 'Route for vehicle {}:\n'.format(vehicle_id)
route_distance = 0
route_load = 0
while not routing.IsEnd(index):
node_index = manager.IndexToNode(index)
route_load += data['demands'][node_index]
plan_output += ' Stop {0} Students({1}) -> '.format(node_index, route_load)
previous_index = index
index = solution.Value(routing.NextVar(index))
route_distance += routing.GetArcCostForVehicle(
previous_index, index, vehicle_id)
plan_output += ' Stop {0} Students({1})\n'.format(manager.IndexToNode(index),
route_load)
plan_output += 'Duration of the route: {}m\n'.format(route_distance)
plan_output += 'Number of students of the route: {}\n'.format(route_load)
print(plan_output)
total_distance += route_distance
total_load += route_load
print('Total duration of all routes: {}m'.format(total_distance))
print('Total number of students of all routes: {}'.format(total_load))
def main():
"""Solve the CVRP problem."""
# Instantiate the data problem.
data = create_data_model()
# Create the routing index manager.
manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),
data['num_vehicles'], data['starts'],
data['ends'])
# 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 Capacity constraint.
def demand_callback(from_index):
"""Returns the demand of the node."""
# Convert from routing variable Index to demands NodeIndex.
from_node = manager.IndexToNode(from_index)
return data['demands'][from_node]
demand_callback_index = routing.RegisterUnaryTransitCallback(
demand_callback)
dimension_name = 'Capacity'
routing.AddDimensionWithVehicleCapacity(
demand_callback_index,
0, # null capacity slack
data['vehicle_capacities'], # vehicle maximum capacities
True, # start cumul to zero
dimension_name)
# Add Distance constraint.
dimension_name = 'Distance'
routing.AddDimension(
transit_callback_index,
0, # no slack
100, # 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)
search_parameters.local_search_metaheuristic = (
routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)
search_parameters.log_search = True
search_parameters.time_limit.FromSeconds(5)
# Solve the problem.
solution = routing.SolveWithParameters(search_parameters)
# Print solution.
if solution:
print_solution(data, manager, routing, solution)
#else:
#print('no solution')
if __name__ == '__main__':
main()
data = create_data_model()
#print(len(data['distance_matrix']))
#print(len(data['distance_matrix'][0]))
如果有人能帮助我,我将不胜感激!
默认情况下,空路由 Start -> End
的 arc 成本 为零。
因此,当使用 routing.GetArcCostForVehicle(previous_index, index, vehicle_id)
.
您可以使用 RoutingModel::ConsiderEmptyRouteCostsForVehicle(bool consider_costs, int vehicle)
启用费用。
恕我直言,这样的事情应该可行:
for v in range(manager.GetNumberOfVehicles()):
routing.ConsiderEmptyRouteCostsForVehicle(true, v)