遗传+粒子群 求解多配送中心车辆调度问题(python)
双层规划模型的车辆路径优化问题(python3)
考虑将粒子群算法与遗传算法结合起来研究车辆路径优化问题。
1.问题描述
LRP 问题既可以满足配送中心的最优数量和容量,又可以确定车辆的最优运输路线 ,是LAP问题(物流配送中心选址问题)和VRP问题的集成 。它可以描述为:至少有一 个位置及容量均己知的配送中心,若干个位置及需求量均己知的终端零售商,承载量己知的车辆若干,在这些约束条件下 ,选择出最佳配送中心选址方案和最优配送路径优化方案,从而使物流成本最低 、物流效率最高 。
建立双层规划模型求解该问题。上层规划是从好几个配送中心中选择出一个或多个配送中心的问题,下层规划是车辆配送方案的确定问题(也就是带时间窗的VRP问题),主要目的是通过上下层规划模型的相互作用达到冷链物流配送开放式车辆路径优化的目的。
2.算法实现过程介绍
当我兴致勃勃以为很简单的时候,才发现这多个配送中心并没有指定具体的客户,也就是说存在至少以下三个决策变量:(1)确定到底选择哪个配送中心以及选择配送中心的个数是一个还是多个;(2)确定配送中心到底服务哪些客户,以便决定车辆从配送中心到客户点间的距离矩阵;(3)车辆服务客户的顺序。
查阅文献,发现针对多配送中心的车辆调度问题,其中确定配送中心服务哪些客户的这个决策因素,采取的相对简单的方法是:最近分配方法。该方法的具体操作是通过计算某客户与各配送中心的距离,该客户离哪个配送中心最近,就将其分配给哪个配送中心 。
多配送中心车辆调度问题的算法步骤如下:
(1)先通过就近分配原则,确定配送中心的服务客户,降低问题的复杂度,将多配送中心问题转化为单配送中心问题求解;
(2)采用双层规划模型求解多配送中心的车辆调度问题。
上层模型求解到底需要几个配送中心的问题,采用遗传算法;下层模型在确定好配送中心的前提下解决VRPTW问题,采用粒子群算法。
3.关键技术
3.1 将粒子群算法封装成类
遗传算法和粒子群算法的常用函数,我在前两篇博文中已经给出了,就是将两种算法整合在一起进行调整的过程。下层模型如果重新定义粒子的编码结构,会增加求解的难度,既然多配送中心的问题转换成了一般的单配送中心问题,将文章提到的粒子群算法封装成类,多次调用就可以得到各个被选中的配送中心的总运输成本。
3.2 利用备忘录法记录遗传算法已经求解过的染色体
当备选配送中心的数量很小时,完全可以利用枚举的方式列出全部的可行解集合,例如,考虑三个配送中心,应该选择哪几个作为实际建设的配送中心以优化物流运输成本,将可行解的集合看作是S,S={{1},{2},{3},{1,2},{1,3},{2,3},{1,2,3}},一共有7种选择方案。可以利用python的itertools模块列出集合的全部子集(不包括空集),代码如下:
from itertools import combinations
L = [1, 2, 3]
result_list = sum([list(map(list, combinations(L, i))) for i in range(1, len(L) + 1)], [])
print('result_list =', result_list)
当备选配送中心的数量较大时,全部的非空子集个数为:2的n次方减1。可以通过遗传算法的进化规则使一些较劣解不参与计算,从而降低问题求解的规模。
4.算例代码
上层选择配送中心建设方案的过程采用枚举算法。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author : Logintern09from VRPTW_data import Data_class
import numpy as np
np.set_printoptions(threshold=np.inf) # 保证数组全部显示出来
from PSO_func import *demand_distance_graph = Data_class.demand_distance_graph # 需求点的距离矩阵
supply_distance_graph = Data_class.supply_distance_graph # 供给点的距离矩阵
demand_node_num = Data_class.demand_node_num # 需求节点的数量
supply_node_num = Data_class.supply_node_num # 供给节点的数量data_dict = dict()
data_dict['demand_quantity'] = Data_class.demand_quantity
data_dict['demand_time_window'] = Data_class.demand_time_window
data_dict['demand_service_time'] = Data_class.demand_service_time
data_dict['mile_max'] = 1000 # 每辆车的最大行驶里程数
data_dict['vehicle_capacity_max'] = 15 # 车辆的最大载重量
data_dict['unit_trans_cost'] = 10 # 配送中心到需求点,车辆的单位运输成本,单位:元/公里
data_dict['vehicle_useCost'] = 300 # 车辆的使用成本,单位:元
data_dict['vehicle_speed'] = 40 # 配送中心到需求点,车辆的单位行驶速度,单位:公里/小时
data_dict['vehicle_num'] = 4 # 供配送中心调配的车辆数
data_dict['unit_ET_cost'] = 0.5 # 早到机会惩罚成本系数
data_dict['unit_LT_cost'] = 1.5 # 不满足时间窗要求的晚到单位惩罚成本
data_dict['unit_loss_cost'] = 0.5 # 单位货损成本系数
data_dict['unit_built_cost'] = 0 # 配送中心的单位建设成本# 确定粒子群算法的参数
pso_parameter_dict = dict()
pso_parameter_dict['population_size'] = 100 # 粒子种群的大小
pso_parameter_dict['max_steps'] = 200
pso_parameter_dict['w'] = 0.6 # 惯性权重
pso_parameter_dict['p_c1'] = 2 # 个体学习因子
pso_parameter_dict['g_c2'] = 2 # 社会学习因子
pso_parameter_dict['solution_layer'] = 2 # 问题的自变量有两个,分别是确定车辆与客户的一对一关系,和确定车辆的配送顺序# 采用最近路径法分配客户给配送中心
def allocation_customer(location_index):""":param location_index: 选择的配送中心的序号,从小到大排列:return:location_customer_list: 第i个数组表示location_index-1的顾客集合"""if len(location_index) == 1:location_customer_list = []location_customer_list.append(range(Data_class.demand_node_num))return location_customer_listsupply_distance_graph = Data_class.supply_distance_graphdistance = supply_distance_graph[location_index, :]customer_to_location = np.argmin(distance, axis=0)location = list(set(customer_to_location))location.sort()location_customer_list = []for location_index in location:location_customer_list.append(np.where(customer_to_location == location_index)[0])return location_customer_listdef get_pathLen_time(supply_index):# 正式运算时用到的是distance_graphdemand_node_num = Data_class.demand_node_num # 需求节点的数量distance_graph = np.zeros((demand_node_num + 1, demand_node_num + 1))distance_graph[0, 1:] = supply_distance_graph[supply_index, :]distance_graph[1:, 1:] = demand_distance_graphdistance_graph[1:, 0] = np.transpose(supply_distance_graph[supply_index, :])vehicle_speed = Data_class.vehicle_speedpathTime_graph = (distance_graph / vehicle_speed) * 60 # 需求点间路段上的行驶时间,单位:分钟return distance_graph, pathTime_graphdef cal_built_cost(location_index):# 计算配送中心的建设成本return len(location_index)*data_dict['unit_built_cost']# 枚举出所有的可行解,即上层配送中心的选择方案
from itertools import combinations
location_list = range(0, supply_node_num)
upper_list = sum([list(map(list, combinations(location_list, i))) for i in range(1, len(location_list) + 1)], [])best_routes_list = []
fitness = []
for location_index in upper_list:location_customer_list = allocation_customer(location_index)ind_routes = []ind_value = 0for i in range(len(location_index)):supply_index = location_index[i]demand_nodes = location_customer_list[i]demand_nodes = [i+1 for i in demand_nodes] # 需求节点的编号从1开始demand_node_num = len(demand_nodes)# 采用粒子群算法针对需求节点的索引进行计算下层模型的成本pso_parameter_dict['dim'] = pso_parameter_dict['solution_layer'] * demand_node_num # 一个粒子的维度pso_parameter_dict['x_bound'] = [[1, data_dict['vehicle_num']], [1, demand_node_num]] # 自变量的上下限限制distance_graph, pathTime_graph = get_pathLen_time(supply_index)# 初始化粒子群类pso = pso_operation(pso_parameter_dict, data_dict,demand_nodes, distance_graph, pathTime_graph,)best_routes, best_value = pso.run()ind_routes += best_routesind_value += best_value# 记录每一个上层可行解的下层解码的结果best_routes_list.append(ind_routes) # ind_routes表示每一条染色体解码得到的路线(包含所有的需求点)fitness.append(ind_value + cal_built_cost(location_index))# 找到成本最小的解
min_value = min(fitness)
index = fitness.index(min_value)
best_solution = best_routes_list[index]
best_supply_solution = upper_list[index]
print('上下层成本最小值:', min_value)
print('下层最优的解结构', best_solution)
print('上层最优的解结构:', best_supply_solution)# 解码得到各个配送中心的下层车辆配送方案
customer_allocation = allocation_customer(best_supply_solution)
for index in range(len(customer_allocation)):allocate_plan = customer_allocation[index]allocate_plan = [i+1 for i in allocate_plan]routes_plan = []for i in range(len(allocate_plan)):node = allocate_plan[i]for routes in best_solution:if node in routes and (routes not in routes_plan):routes_plan.append(routes)print('%s 配送中心的配送方案为:%s' % (best_supply_solution[index], routes_plan))
5.结果展示
备选配送中心的个数为5个。
(1)不考虑配送中心的建设成本,总成本只是下层粒子群算法求解的总运输成本,总运输成本=车辆的固定使用成本+车辆运输路线成本+时间窗的惩罚成本+货损成本。
上下层成本最小值: 6970.5825
下层最优的解结构 [[0, 11, 10, 0], [0, 1, 0], [0, 2, 14, 3, 0], [0, 6, 13, 7, 0], [0, 8, 15, 5, 0], [0, 9, 4, 12, 0]]
上层最优的解结构: [0, 1, 2, 3, 4]
0 配送中心的配送方案为:[[0, 1, 0], [0, 11, 10, 0]]
1 配送中心的配送方案为:[[0, 2, 14, 3, 0]]
2 配送中心的配送方案为:[[0, 6, 13, 7, 0]]
3 配送中心的配送方案为:[[0, 8, 15, 5, 0]]
4 配送中心的配送方案为:[[0, 9, 4, 12, 0]]
(2)考虑上层配送中心的建设成本,当配送中心的建设成本较大时,理论上是少建配送中心,节约固定建设成本。当配送中心的固定建设成本为500时,
上下层成本最小值: 8563.9725
下层最优的解结构 [[0, 3, 14, 1, 0], [0, 11, 10, 0], [0, 13, 2, 6, 0], [0, 8, 7, 0], [0, 5, 15, 4, 12, 9, 0]]
上层最优的解结构: [0, 2, 4]
0 配送中心的配送方案为:[[0, 3, 14, 1, 0], [0, 11, 10, 0]]
2 配送中心的配送方案为:[[0, 13, 2, 6, 0], [0, 8, 7, 0]]
4 配送中心的配送方案为:[[0, 5, 15, 4, 12, 9, 0]]
5.小结
(1)下层的粒子群算法还有待改善。
(2)考虑采用多线程的方式实现下层粒子群算法的同步计算。
参考文献:
1.基于双层规划模型的冷链物流配送开放式车辆路径优化
2.城市生鲜食品冷链物流配送中心选址及路径优化问题研究
3.Python包中__init__.py作用
4.如何基于python生成list的所有的子集
遗传+粒子群 求解多配送中心车辆调度问题(python)相关推荐
- 货物配送问题的matlab,遗传算法matlab程序【基于遗传算法的无时限多配送中心车辆调度问题研究】...
[摘 要] 针对多配送中心车辆调度问题的复杂性特点,提出用最近距离分配法和遗传算法分两步求解多配送中心车辆调度问题,并进行了试验计算. [关键词] 多配送中心 车辆调度 最近距离分配法 遗传算法 一. ...
- 遗传-粒子群算法遗传-禁忌搜索算法求解TSP问题
1. 前言 上一篇博文[五种常见启发式算法求解TSP问题-总结篇]中,总结了五种常见启发式算法在求解TSP问题上的效果,其中遗传算法的求解质量最差,而粒子群算法和禁忌搜索算法的求解效果最佳,因此本文计 ...
- 爬山算法改进粒子群求解测试测试函数shubert,测试函数的100种优化方法之14
爬山算法粒子群求解测试测试函数 shubert函数属于周期性多峰函数,如图1所示拥有多个全局最优值,如图二所示在一个周期内只有一个全局最优值,局部最优解较多,适合测试算法的收敛性能,粒子群算法是一种收 ...
- 基于粒子群算法的智能车辆避障路径规划方法研究
基于粒子群算法的智能车辆避障路径规划方法研究 1.环境生成 1.1 环境生成方法的选择 1.2 坐标法生成环境 1.3 车辆简化 1.4 障碍物数据 2.粒子初始化 2.1 速度迭代设置 2.2 避障 ...
- 粒子群算法(PSO)的python实现
文章目录 前言 一.粒子群算法的原理 二.python代码实现 总结 前言 CSDN上找了一圈粒子群算法的python代码,全是以类来写的,由于对类不感冒(其实是不咋会用),于是参照matlab版本的 ...
- 基于组合遗传粒子群算法的旅行商问题求解
问题描述 一个商品推销员要去若干个城市推销商品,该推销员从一个城市出发,需要经过所有城市后,回到出发地.应如何选择行进路线,以使总的行程最短. 对于n个城市的TSP,本文利用python分别实现混合粒 ...
- 【布局优化】基于粒子群求解物流选址matlab源码
一.简介 粒子群优化(PSO)是一种基于群体智能的数值优化算法,由社会心理学家James Kennedy和电气工程师Russell Eberhart于1995年提出.自PSO诞生以来,它在许多方面都得 ...
- Binary Particle Swarm Optimization(BPSO) for Feature Selection(二进制粒子群求解特征选择)
文章目录 前言 一.粒子群算法学习过程 二.特征选择实战 1.数据集以及matlab源码 2.参数说明 3.实验结果 总结 前言 PSO算法是一种群智能优化算法,特点是布置速度快,收敛性强.同时面对着 ...
- 【配电网重构】基于粒子群求解配电网重构模型matlab源码
一.故障信息的数学表示 在上图中K表示断路器,每一个断路器上均有一个FTU装置,可以反馈断路器开关是否过流,用表示上传的故障信息,反映的是各分段开关处是否流过故障电流有故障电流为1,否则为0).即: ...
- 【微电网优化】基于粒子群求解CHP机组、气网、电网、储热罐和电锅炉微电网优化模型附matlab代码
1 简介 近年来随着全球性的环境污染问题与能源危机日益突出,人们的环保意识与节能意识不断提高,使得微电网成为了电力系统领域的研究热点之一.相对于传统的大电网,微电网具有自身的特点和优势,发电过程产生的 ...
最新文章
- arp/ip地址/路由--总之很乱
- lwip+freeRTOS 故障容错 客户端主动发起连接
- python 上传excel_简历批量合并Python+VBA小工具
- Javascript 中 Array.push 要比 Array.concat 快 945 倍
- 做游戏,学编程(C语言) 1 实现弹跳小球
- 30 位 90 后霸榜福布斯,有颜、有才、有头脑!
- ipv6单播地址包括哪两种类型_IPV6中为啥没有ARP了呢?一文带你搞懂NDP邻居发现协议...
- 「leetcode」本周小结!(回溯算法系列二)
- 两招轻松恢复误Ghost的硬盘
- miui android mmi,小米5miui9稳定版自改官包方法
- 数字逻辑与数字电路知识点整理
- springmvc 银联商家向用户转账
- 计算机网络教室环境的作用,网络教室环境与多媒体教室环境相比优势在什么地方...
- Mac下的平铺式桌面 - Yabai
- springboot使用jdbc连接mysql数据库时测试连接错误
- python 语料_用python将语料转化为可计算的形式
- Python py文件如何调用其他py文件
- 天道酬勤~我如此惬意
- Android基础四大组件详解
- 惠普HP打印机打印全黑是什么原因
热门文章
- GNSS NMEA-0183 协议
- power supply surges detected
- ubuntu记录pdf手写笔记: 数位板(硬件)+xournal(软件)
- Linux下调用wps的Tables接口,WPS二次开发简单示例
- rs422/rs485通信接口原理图
- 机械手基础知识(2)之机械手的正运动学和逆运动学问题
- 《三国演义》分章节梗概
- 2017年经典hadoop体系课程-徐培成-专题视频课程
- 详解 Python 字符串(一):字符串基础
- 从 Java 到 Kotlin,再从 Kotlin 回归 Java