1.思考题
2.编程题
2.1多辆车的路径规划 VRP
条件:经过中国33个城市,一共4辆车,每辆车最大行驶10000公里
目标:使得每辆车的行驶里程数更接近
需要注意:在VRP问题中,路径上给点赋的index和点实际的index不一样,需要使用IndexToNode方法进行转换才能得到实际的index
任务:
- 使用Ortools或其他工具完成代码
- 能在有限时间内,得到较好的结果
import pandas as pd
from ortools.constraint_solver import routing_enums_pb2,pywrapcp
class tsp(object):
def __init__(self, city_names=None):
# 设置城市名称
self.df = pd.read_excel('./cities.xlsx')
self.all_city = self.df['name'].values
if city_names is not None:
self.city_names = city_names
self.df = self.df[self.df['name'].isin(city_names)]
else:
self.city_names = self.all_city
def create_data_model(self):
data = {
}
temp = pd.read_excel('./distance.xlsx', index_col=0)
# 按照city_names进行筛选
temp = temp[(temp.index.isin(self.city_names))][self.city_names]
print(temp)
data['distance_matrix'] = temp.values/1000
data['num_vehicles'] = 1 # 车的数量
data['depot'] = 0 # 从哪个点出发
return data
# 输出结果
def get_solution(self,manager, routing, solution):
print('总行驶里程: {} 公里'.format(solution.ObjectiveValue()))
index = routing.Start(0)
# plan_output = '车辆的路径:\n'
route = []
route_distance = 0
while not routing.IsEnd(index):
# 使用indextonode将manager中的index转换为distance_matrix中的index
# plan_output += ' {} ->'.format(city_names[manager.IndexToNode(index)])
index_show = manager.IndexToNode(index)
# 添加到route
route.append(index_show)
previous_index = index
# 走到下一个节点
index = solution.Value(routing.NextVar(index))
# 统计previous_index到index节点的距离
route_distance += routing.GetArcCostForVehicle(previous_index, index, 0)
return route,route_distance
def work(self):
# step1,初始化得到三个参数字典
data = self.create_data_model()
# step2,创建路线管理,tsp_size(城市数量), num_vehicles(车的数量), depot(原点)
manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),
data['num_vehicles'], data['depot'])
# step3,创建 Routing Model.
routing = pywrapcp.RoutingModel(manager)
# step4,计算两点之间的距离。输入的是manager中两个节点的index,输出的是节点之间的距离
def distance_callback(from_index, to_index):
# 将index转换为distance_matrix中的节点index
# 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)
#step5,设置参数策略
# Setting first solution heuristic.
search_parameters = pywrapcp.DefaultRoutingSearchParameters()
search_parameters.first_solution_strategy = (
routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)
# step6,求解路径规划
solution = routing.SolveWithParameters(search_parameters)
# step7,输出结果
route, route_distance = self.get_solution(manager,routing,solution)
return route,route_distance
测试1:使用全量的城市,不对city_names进行筛选
model = tsp()
route, route_distance = model.work()
print(route)
print(route_distance)
"""
总行驶里程: 19799 公里
[0, 6, 22, 21, 23, 24, 26, 27, 25, 12, 32, 11, 31, 30, 10, 9, 8, 15, 13, 28, 29, 14, 20, 17, 18, 19, 7, 5, 16, 1, 4, 2, 3]
"""
测试2:city_names = [‘北京’, ‘天津’, ‘南京’]
city_names = ['北京', '天津', '南京']
model = tsp(city_names = city_names)
model.create_data_model()
route, route_distance = model.work()
print(route)
print(route_distance)
"""
北京 天津 南京
北京 0 122476 1002497
天津 122476 0 935319
南京 1002497 935319 0
北京 天津 南京
北京 0 122476 1002497
天津 122476 0 935319
南京 1002497 935319 0
总行驶里程: 2059 公里
[0, 1, 2]
2059
"""