【进阶四】Python实现(MD)HVRP常见求解算法——差分进化算法(DE)
差分进化算法+Split 求解异构车辆路径规划问题
碧海蓝天 吹吹风
目录
- 信息传递
- 1. 适用场景
- 2. 求解效果
- 3. 代码分析
- 4. 数据格式
- 5. 分步实现
- 6. 完整代码
- 参考
信息传递
- python实现6种智能算法求解CVRP问题
- python实现7种智能算法求解MDVRP问题
- python实现7种智能算法求解MDVRPTW问题
- Python版MDHFVRPTW问题智能求解算法代码【TS算法】
- Python版MDHFVRPTW问题智能求解算法代码【SA算法】
- Python版MDHFVRPTW问题智能求解算法代码【GA算法】
- Python版MDHFVRPTW问题智能求解算法代码【DPSO算法】
- Python版MDHFVRPTW问题智能求解算法代码【DE算法】
- Python版MDHFVRPTW问题智能求解算法代码【ACO算法】
- Python版HVRP问题智能求解算法代码【GA算法】
- Python版HVRP问题智能求解算法代码【DPSO算法】
1. 适用场景
- 求解HVRP或MDHVRP
- 多车辆类型
- 车辆容量不小于需求节点最大需求
- (多)车辆基地
- 车场车辆总数满足实际需求
2. 求解效果
(1)收敛曲线
(2)车辆路径
3. 代码分析
Christian Prins给出的HVRP的Split方法过程如下:
以上算法在搜索过程中需求节点的备选标签规模会非常大,占用内存且降低搜索效率,因此采用了帕累托思想来遗传非支配解(19行~21行)。为了进一步控制备选标签数量,本期文章还附加实现了通过剩余容量与剩余需求来判断是否产生新的备选标签,提前避免产生不可行的标签。尽管如此,当考虑的异构车辆类型较多、需求点规模较大时,求解效率依然较低(代码结构、python特性、硬件环境)。所以本期文章进一步加入了最大标签数量参数来控制每个需求节点的备选标签规模,通过调节该参数实现速度与质量的相对均衡。
4. 数据格式
这里采用solomon开源数据对算法进行测试,数据文件结构如下图所示,共100个需求点,3个车场,3类车辆,以.csv文件储存数据。
demand.csv文件内容如下图,其中第一行为标题栏,节点id从0开始递增编号。
depot.csv文件内容如下图,其中第一行为标题栏,依次为:车场id,车场平面x坐标,车场平面y坐标,车辆类型,车辆装载量,车辆数量,固定成本,单位里程运输成本。
5. 分步实现
(1)代码整体架构
(2)数据结构
定义Sol()类,Demand()类,Vehicle()类,Model()类,其属性如下表:
- Sol()类,表示一个可行解
属性 | 描述 |
---|---|
node_id_list | 需求节点id有序排列集合 |
obj | 优化目标值 |
route_list | 车辆路径集合,对应MDVRPTW的解 |
- Demand()类,表示一个需求节点
属性 | 描述 |
---|---|
id | 物理节点id,需唯一 |
x_coord | 物理节点x坐标 |
y_coord | 物理节点y坐标 |
demand | 物理节点需求 |
- Vehicle()类,表示一个车队节点
属性 | 描述 |
---|---|
depot_id | 车辆归属的车场节点节点id,需唯一 |
x_coord | 车辆归属车场节点x坐标 |
y_coord | 车辆归属车场节点y坐标 |
type | 车辆类型 |
capacity | 车辆容量 |
free_speed | 车辆运营速度 |
fixed_cost | 车辆固定成本 |
variable_cost | 车辆变动成本 |
- Model()类,存储算法参数
属性 | 描述 |
---|---|
best_sol | 全局最优解,值类型为Sol() |
demand_dict | 需求节点集合(字典),值类型为Demand() |
vehicle_dict | 车队集合(字典),值类型为Vehicle() |
vehicle_type_list | 车队id集合 |
demand_id_list | 需求节点id集合 |
sol_list | 种群,值类型为Sol() |
distance_matrix | 节点距离矩阵 |
number_of_demands | 需求节点数量 |
Cr | 差分交叉概率 |
F | 差分变异概率 |
popsize | 种群规模 |
(3)数据读取
"参数读取"
def readCSVFile(demand_file,depot_file,model):with open(demand_file,'r') as f:demand_reader=csv.DictReader(f)for row in demand_reader:demand = Demand()demand.id = int(row['id'])demand.x_coord = float(row['x_coord'])demand.y_coord = float(row['y_coord'])demand.demand = float(row['demand'])model.demand_dict[demand.id] = demandmodel.demand_id_list.append(demand.id)model.number_of_demands=len(model.demand_id_list)with open(depot_file, 'r') as f:depot_reader = csv.DictReader(f)for row in depot_reader:vehicle = Vehicle()vehicle.depot_id = row['depot_id']vehicle.x_coord = float(row['x_coord'])vehicle.y_coord = float(row['y_coord'])vehicle.type = row['vehicle_type']vehicle.capacity=float(row['vehicle_capacity'])vehicle.numbers=float(row['number_of_vehicle'])vehicle.fixed_cost=float(row['fixed_cost'])vehicle.variable_cost=float(row['variable_cost'])model.vehicle_dict[vehicle.type] = vehiclemodel.vehicle_type_list.append(vehicle.type)
(4)距离计算
"距离矩阵计算"
def calDistanceMatrix(model):for i in range(len(model.demand_id_list)):from_node_id = model.demand_id_list[i]for j in range(i + 1, len(model.demand_id_list)):to_node_id = model.demand_id_list[j]dist = math.sqrt((model.demand_dict[from_node_id].x_coord - model.demand_dict[to_node_id].x_coord) ** 2+ (model.demand_dict[from_node_id].y_coord - model.demand_dict[to_node_id].y_coord) ** 2)model.distance_matrix[from_node_id, to_node_id] = int(dist)model.distance_matrix[to_node_id, from_node_id] = int(dist)for _, vehicle in model.vehicle_dict.items():dist = math.sqrt((model.demand_dict[from_node_id].x_coord - vehicle.x_coord) ** 2+ (model.demand_dict[from_node_id].y_coord - vehicle.y_coord) ** 2)model.distance_matrix[from_node_id, vehicle.type] = int(dist)model.distance_matrix[vehicle.type, from_node_id] = int(dist)
(5)路径成本计算
"计算解的成本"
def calTravelCost(route_list,model):obj=0for route in route_list:vehicle=model.vehicle_dict[route[0]]distance=0fixed_cost=vehicle.fixed_costvariable_cost=vehicle.variable_costfor i in range(len(route) - 1):from_node = route[i]to_node = route[i + 1]distance += model.distance_matrix[from_node, to_node]obj += fixed_cost + distance * variable_costreturn obj
(6)目标函数计算
"目标函数"
def calObj(node_id_list,model):vehicle_routes = splitRoutes(node_id_list, model)if vehicle_routes:return calTravelCost(vehicle_routes,model),vehicle_routeselse:return 10**9,None
(7)差分变异
"差分变异;变异策略:DE/rand/1/bin"
def muSol(model,v1,v2,v3):x1=model.sol_list[v1].node_id_listx2=model.sol_list[v2].node_id_listx3=model.sol_list[v3].node_id_listmu_x=[min(int(x1[i]+model.F*(x2[i]-x3[i])),len(model.demand_id_list)-1) for i in range(len(model.demand_id_list)) ]return mu_x
(8)差分交叉
"差分交叉"
def crossSol(model,vx,vy):cro_x=[]for i in range(len(model.demand_id_list)):if random.random()<model.Cr:cro_x.append(vy[i])else:cro_x.append(vx[i])cro_x=adjustRoutes(cro_x,model)return cro_x
(9)绘制收敛曲线
def plotObj(obj_list):plt.rcParams['font.sans-serif'] = ['SimHei'] #show chineseplt.rcParams['axes.unicode_minus'] = False # Show minus signplt.plot(np.arange(1,len(obj_list)+1),obj_list)plt.xlabel('Iterations')plt.ylabel('Obj Value')plt.grid()plt.xlim(1,len(obj_list)+1)plt.show()
(10)绘制车辆路径
def plotRoutes(model):for route in model.best_sol.route_list:x_coord=[model.vehicle_dict[route[0]].x_coord]y_coord=[model.vehicle_dict[route[0]].y_coord]for node_id in route[1:-1]:x_coord.append(model.demand_dict[node_id].x_coord)y_coord.append(model.demand_dict[node_id].y_coord)x_coord.append(model.vehicle_dict[route[-1]].x_coord)y_coord.append(model.vehicle_dict[route[-1]].y_coord)plt.grid()if route[0]=='v1':plt.plot(x_coord,y_coord,marker='o',color='black',linewidth=0.5,markersize=5)elif route[0]=='v2':plt.plot(x_coord,y_coord,marker='o',color='orange',linewidth=0.5,markersize=5)elif route[0]=='v3':plt.plot(x_coord,y_coord,marker='o',color='r',linewidth=0.5,markersize=5)else:plt.plot(x_coord, y_coord, marker='o', color='b', linewidth=0.5, markersize=5)plt.xlabel('x_coord')plt.ylabel('y_coord')plt.show()
(11)输出结果
def outPut(model):work=xlsxwriter.Workbook('result.xlsx')worksheet=work.add_worksheet()worksheet.write(0, 0, 'obj')worksheet.write(0, 1,model.best_sol.obj)worksheet.write(1, 0,'vehicleID')worksheet.write(1, 1,'depotID')worksheet.write(1, 2, 'vehicleType')worksheet.write(1, 3,'route')for row,route in enumerate(model.best_sol.route_list):worksheet.write(row+2,0,str(row+1))depot_id=model.vehicle_dict[route[0]].depot_idworksheet.write(row+2,1,depot_id)worksheet.write(row+2,2,route[0])r=[str(i)for i in route]worksheet.write(row+2,3, '-'.join(r))work.close()
(12)主函数
def run(demand_file,depot_file,epochs,Cr,F,popsize):""":param demand_file: 需求节点文件路径:param depot_file: 车场节点文件路径:param epochs:迭代次数:param Cr:差分交叉概率:param F:缩放因子:param popsize:种群规模:param v_cap:车辆容量:param opt_type:优化类型:0:最小化车辆数,1:最小化行驶距离:return:"""model=Model()model.Cr=Crmodel.F=Fmodel.popsize=popsizereadCSVFile(demand_file,depot_file,model)calDistanceMatrix(model)best_sol = Sol()best_sol.obj = float('inf')model.best_sol = best_solgenInitialSol(model)history_best_obj = []start_time = time.time()for ep in range(epochs):for i in range(popsize):v1 = iv2,v3= random.sample(range(0, popsize), 2)sol=model.sol_list[v1]mu_x=muSol(model,v1,v2,v3)u=crossSol(model,sol.node_id_list,mu_x)u_obj,u_routes=calObj(u,model)if u_obj<=sol.obj:sol.node_id_list=copy.deepcopy(u)sol.obj=copy.deepcopy(u_obj)sol.route_list=copy.deepcopy(u_routes)if sol.obj<model.best_sol.obj:model.best_sol=copy.deepcopy(sol)history_best_obj.append(model.best_sol.obj)print("%s/%s, best obj: %.3f runtime: %.3f" % (ep, epochs, model.best_sol.obj,time.time()-start_time))plotObj(history_best_obj)plotRoutes(model)outPut(model)
6. 完整代码
如有错误,欢迎交流。
有偿获取
参考
- Order-first split-second methods for vehicle routing problems: A review
【进阶四】Python实现(MD)HVRP常见求解算法——差分进化算法(DE)相关推荐
- 【进阶四】Python实现(MD)HVRP常见求解算法——蚁群算法(ACO)
蚁群算法+Split 求解异构车辆路径规划问题 目录 信息传递 1. 适用场景 2. 求解效果 3. 代码分析 4. 数据格式 5. 分步实现 6. 完整代码 参考 信息传递 python实现6种智能 ...
- 【进阶一】Python实现MDCVRP常见求解算法——差分进化算法(DE)
基于python语言,实现差分进化算法(DE)对多车场车辆路径规划问题(MDCVRP)进行求解. 目录 往期优质资源 1. 适用场景 2. 求解效果 3. 代码分析 4. 数据格式 5. 分步实现 6 ...
- 【进阶二】Python实现VRPTW常见求解算法——差分进化算法(DE)
基于python语言,实现经典差分进化算法(DE)对带有时间窗的车辆路径规划问题( VRPTW )进行求解. 目录 往期优质资源 1. 适用场景 2. 求解效果 3. 代码分析 4. 数据格式 5. ...
- Python实现VRP常见求解算法——差分进化算法(DE)
基于python语言,实现经典差分进化算法(DE)对车辆路径规划问题(CVRP)进行求解. 目录 1. 适用场景 2. 求解效果 3. 问题分析 4. 数据格式 5. 分步实现 6. 完整代码 参考 ...
- 【进阶二】Python实现(MD)VRPTW常见求解算法——自适应大邻域搜索算法(ALNS)
基于python语言,实现经典自适应大邻域搜索算法(ALNS)对(多车场)带有时间窗的车辆路径规划问题( (MD) VRPTW )进行求解. 目录 往期优质资源 1. 适用场景 2. 求解效果 3. ...
- 机器学习中四类进化算法的详解(遗传算法、差分进化算法、协同进化算法、分布估计算法)
1.遗传算法(Genetic Algorithm,GA) GA算法原理 首先我们来介绍进化算法的先驱遗传算法,遗传算法(Genetic Algorithm,简称GA)是一种最基本的进化算法,它是模拟达 ...
- 差分进化算法python_差分进化算法Python实现
本文you清华大学硕士大神金天撰写,欢迎大家转载,不过请保留这段版权信息,对本文内容有疑问欢迎联系作者微信:jintianiloveu探讨,多谢合作~ 导语 差分进化算法是一种寻优算法,提出时间比遗传 ...
- 智能计算作业——差分进化算法求解函数最值
下面是智能计算作业,哎呀,你们快来抄我作业呀╭(╯^╰)╮ 问题描述: 算法理论我省略了,你们自己去百科上抄吧╭(╯^╰)╮ 求解步骤: (这个好像也是百科上的╭(╯^╰)╮我根据自己的需要改了一下) ...
- 差分进化算法python 指派问题_多目标优化算法
本书实用性强,摒弃工具书中难懂的理论讲解,通过使用具体数值实例进行浅显易懂的讲解,保证大学低年级学生凭借现有的数学基础知识也可以完全理解书中介绍的网络数学模型和遗传算法的解法.书中丰富的数值实例能够加 ...
最新文章
- 【C#】Out与ref是干什么的?
- Python3创建目录文件夹
- 赛题出简单了,让我们情何以堪?
- 本地Windows远程桌面连接阿里云Ubuntu服务器
- WordPress插件制作教程概述
- adobe photoshop cc 复制css链接
- Python 文件读和写
- SpringBoot通过yml和xml文件配置日志输出
- 大道至简,仅需4行代码提升多标签分类性能!ICCV21 南大提出Residual Attention
- 洛谷——P1307 [NOIP2011 普及组] 数字反转
- C# 笔记2 - 数组、集合与与文本文件处理
- 自己手写WEB程序框架并执行
- matlab 7.0安装教程
- 阿里矢量图标库的使用方法
- Kafka的Topic删不掉
- Java进阶-面向对象
- MCS51 系列单片机的最小系统
- android jsp界面设计,Android 4.0设计规范-UI博客精选
- POJ3984迷宫问题
- php 中文加密如何解密,求教PHP中文加密解密代码