【改进篇】Python实现VRP常见求解算法——禁忌搜索算法(TS)

基于python语言,实现经典禁忌搜索算法(TS)对车辆路径规划问题(CVRP)进行求解, 优化代码结构,改进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. 适用场景

  • 求解CVRP
  • 车辆类型单一
  • 车辆容量不小于需求节点最大需求
  • 单一车辆基地

2. 改进效果对比

这里做了简单的参数敏感性分析,比较不同参数组合下两个版本code的最优值与求解时间的差异。具体为:依次设定禁忌长度为10,20,30,其他参数固定不变:最大迭代次数为300,车辆容量为80。具体实验结果如下表:

【改进篇】Python实现VRP常见求解算法——禁忌搜索算法(TS)_第1张图片

可以看出,改进后的code,目标函数优化 3% 7% 不等,但牺牲了5倍左右的计算时间。这里计算时间以秒为单位。【在进行实验室计算机在同步执行其他程序,所以实验条件不能保证完全相同,但可反应总体情况】

3. 求解结果

(1)收敛曲线
【改进篇】Python实现VRP常见求解算法——禁忌搜索算法(TS)_第2张图片

(2)车辆路径
【改进篇】Python实现VRP常见求解算法——禁忌搜索算法(TS)_第3张图片

4. 改进内容

本期代码在前期代码的基础上做了以下改进:

  • 增加距离矩阵,减少代码中重复计算节点间距离代码
  • 引入文献中基于图论的Split方法,在给定节点id序列时,可求得最优分割方案

除了以上关键改动之外,还对代码做了细小调整。

5. 部分代码

(1)数据结构

# 数据结构:解
class Sol():
    def __init__(self):
        self.node_no_seq=None # 解的编码
        self.obj=None # 目标函数
        self.action_id=None # 算子id
        self.route_list=None # 解的解码
        self.route_distance = None  # 车辆路径的长度集合
# 数据结构:网络节点
class Demand():
    def __init__(self):
        self.id = 0 # 节点id
        self.x_coord = 0 # 节点平面横坐标
        self.y_coord = 0  # 节点平面纵坐标
        self.demand = 0 # 节点需求
# 数据结构:全局参数
class Model():
    def __init__(self):
        self.best_sol = None # 全局最优解
        self.demand_dict = {}  # 需求节点集合
        self.demand_id_list = []
        self.sol_list = []  # 解的集合
        self.depot = None # 车场节点
        self.number_of_nodes = 0 # 需求节点数量
        self.vehicle_cap = 80 # 车辆最大容量
        self.distance_matrix = {}
        self.tabu_list=None # 禁忌表
        self.TL=30 # 禁忌长度
        self.vehicle_cap=0  # 车辆最大容量

(2)距离矩阵

def calDistanceMatrix(model):
    for i in range(len(model.demand_id_list)):
        f_n = model.demand_id_list[i]
        for j in range(i + 1, len(model.demand_id_list)):
            t_n = model.demand_id_list[j]
            dist = math.sqrt((model.demand_dict[f_n].x_coord - model.demand_dict[t_n].x_coord) ** 2
                             + (model.demand_dict[f_n].y_coord - model.demand_dict[t_n].y_coord) ** 2)
            model.distance_matrix[f_n, t_n] = dist
            model.distance_matrix[t_n, f_n] = dist

        dist = math.sqrt((model.demand_dict[f_n].x_coord - model.depot.x_coord) ** 2
                         + (model.demand_dict[f_n].y_coord - model.depot.y_coord) ** 2)
        model.distance_matrix[f_n, model.depot.id] = dist
        model.distance_matrix[model.depot.id, f_n] = dist

(3)路径提取

def extractRoutes(node_no_seq,P,depot_id):
    route_list = []
    route = []
    p = P[node_no_seq[0]]
    for node_seq in node_no_seq:
        if P[node_seq] == p:
            route.append(node_seq)
        else:
            route.insert(0,depot_id)
            route.append(depot_id)
            route_list.append(route)
            route = [node_seq]
            p = P[node_seq]
    return route_list

(4)邻域算子

# 定义邻域算子
def createActions(n):
    action_list=[]
    nswap=n//2
    #第一种算子(Swap):前半段与后半段对应位置一对一交换
    for i in range(nswap):
        action_list.append([1,i,i+nswap])
    #第二中算子(DSwap):前半段与后半段对应位置二对二交换
    for i in range(0,nswap,2):
        action_list.append([2,i,i+nswap])
    #第三种算子(Reverse):指定长度的序列反序
    for i in range(0,n,4):
        action_list.append([3,i,i+3])
    return action_list

(5)收敛曲线

# 绘制目标函数收敛曲线
def plotObj(obj_list):
    plt.rcParams['font.sans-serif'] = ['SimHei']  #show chinese
    plt.rcParams['axes.unicode_minus'] = False  # Show minus sign
    plt.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()

(6)车辆路径

# 绘制优化车辆路径
def plotRoutes(model):
    for route in model.best_sol.route_list:
        x_coord=[]
        y_coord=[]
        for node_no in route:
            x_coord.append(model.demand_dict[node_no].x_coord)
            y_coord.append(model.demand_dict[node_no].y_coord)
        plt.plot(x_coord,y_coord,marker='s',color='b',linewidth=0.5)
    plt.show()

(7)输出结果

# 输出结果
def outPut(model):
    work=xlsxwriter.Workbook('result.xlsx')
    worksheet=work.add_worksheet()
    worksheet.write(0, 0, 'id')
    worksheet.write(0, 1, 'route')
    worksheet.write(0, 2, 'distance')
    worksheet.write(0, 3, 'total_distance')
    worksheet.write(1,3,model.best_sol.obj)
    for id,route in enumerate(model.best_sol.route_list):
        r=[str(i)for i in route]
        worksheet.write(id + 1, 0, f'v{str(id + 1)}')
        worksheet.write(id + 1, 1, '-'.join(r))
        worksheet.write(id + 1, 2, model.best_sol.route_distance[id])
    work.close()

6. 完整代码

如有错误,欢迎交流。
有偿获取

参考

  1. A simple and effective evolutionary algorithm for the vehicle routing problem

你可能感兴趣的:(车辆路径规划问题,智能优化算法,python,算法,禁忌搜索算法,VRP)