当前位置:   article > 正文

蚁群算法求解VRPTW问题_tsp问题和vrp问题的区别

tsp问题和vrp问题的区别

一、VRP和TSP的区别

VRP(Vehicle Routing Problem)问题和TSP(Traveling Salesman Problem)问题都是优化问题,但它们在问题设置和目标函数上存在一些区别。

TSP问题是经典的组合优化问题,其目标是找到一条最短路径,使得一名推销员从一个城市出发,经过所有其他城市后回到起点城市,同时每个城市只能访问一次。TSP问题的目标是最小化总的旅行距离或旅行时间。

VRP问题是在TSP问题的基础上进行扩展的一类问题。VRP问题考虑的是在给定一组客户需求和一组配送车辆的情况下,如何安排车辆的路径,以便满足所有客户的需求,并且使得总的配送成本最小化。VRP问题通常包括以下要素:

  1. 客户需求:每个客户对应一个需求量,表示需要配送的货物数量或服务时间。
  2. 车辆容量:每辆车有一个容量限制,表示车辆能够携带的货物数量或服务时间的上限。
  3. 距离或时间矩阵:表示各个客户之间的距离或行驶时间。
  4. 路径限制:每辆车的路径应满足起始点和终点相同的条件。

在VRP问题中,目标是找到一组车辆的路径,使得满足客户需求的同时,总的配送成本最小化。这个成本可以是行驶距离、行驶时间、车辆数量等。

因此,可以说VRP问题是TSP问题的一种扩展形式,考虑了更多实际配送问题的约束和要素。在VRP问题中,需要解决的是如何合理分配车辆、安排路径以及满足客户需求的问题,而不仅仅是寻找最短路径。

二、VRPTW介绍

VRPTW(Vehicle Routing Problem with Time Windows)

在VRPTW中,有一组客户需要被服务,这些客户位于不同的位置,每个客户有特定的需求量和时间窗口。时间窗口定义了每个客户允许被访问的时间范围,即服务必须在时间窗口内完成。此外,还有一个或多个车辆可用于服务客户,并且每辆车有容量限制。

VRPTW的目标是找到一组最优路径,使得所有客户的需求得到满足,并且最小化总的路程和车辆的数量。解决VRPTW问题可以帮助优化物流和配送等领域的路线规划,提高效率和降低成本。

三、数学模型

参数:

决策变量:

目标函数:

约束条件:
  • 每个乘客必须且只能访问一次

  • 每个车辆的路径必须从仓库出发并返回仓库

  • 车辆容量限制

  • 时间窗口约束

其中M是一个足够大的正数。

这个数学模型描述了VRPTW问题的基本约束和目标,您可以根据具体情况进行进一步的修改和扩展。

四、CPLEX求解

  1. import cplex
  2. from cplex.exceptions import CplexError
  3. # 读取数据
  4. def read_data(filename):
  5. # 从文件中读取服务点、客户的位置
  6. data = {}
  7. node_list = []
  8. with open(filename, 'rt') as f:
  9. count = 1
  10. for line in f:
  11. if count == 5:
  12. vehicle_num, vehicle_capacity = line.split()
  13. vehicle_num = int(vehicle_num)
  14. vehicle_capacity = int(vehicle_capacity)
  15. elif count >= 10:
  16. node_list.append(line.split())
  17. count += 1
  18. for item in node_list:
  19. customer_id = int(item[0])
  20. x = float(item[1])
  21. y = float(item[2])
  22. demand = float(item[3])
  23. ready_time = float(item[4])
  24. due_date = float(item[5])
  25. service_time = float(item[6])
  26. data[customer_id] = {
  27. 'x': x,
  28. 'y': y,
  29. 'demand': demand,
  30. 'ready_time': ready_time,
  31. 'due_date': due_date,
  32. 'service_time': service_time
  33. }
  34. return data, vehicle_num, vehicle_capacity
  35. # 构建VRPTW模型
  36. def build_model(data, num_vehicles, vehicle_capacity):
  37. model = cplex.Cplex()
  38. model.objective.set_sense(model.objective.sense.minimize)
  39. # 创建决策变量
  40. x_vars = {}
  41. for i in data:
  42. for j in data:
  43. for k in range(1, num_vehicles+1):
  44. x_vars[(i, j, k)] = model.variables.get_num()
  45. model.variables.add(obj=[data[i]['x']-data[j]['x'], data[i]['y']-data[j]['y']], lb=[0.0], ub=[1.0], types=['B'])
  46. t_vars = {}
  47. for i in data:
  48. t_vars[i] = model.variables.get_num()
  49. model.variables.add(obj=[0.0], lb=[data[i]['ready_time']], ub=[data[i]['due_date']], types=['C'])
  50. # 添加约束条件
  51. # 每个客户节点必须且仅能被访问一次
  52. for i in data:
  53. model.linear_constraints.add(lin_expr=[[x_vars[(i, j, k)] for j in data] + [x_vars[(j, i, k)] for j in data]], senses=['E'], rhs=[1.0])
  54. # 每个车辆的路径必须从仓库出发并返回仓库
  55. for k in range(1, num_vehicles+1):
  56. model.linear_constraints.add(lin_expr=[[x_vars[(0, j, k)] for j in data]], senses=['E'], rhs=[1.0])
  57. model.linear_constraints.add(lin_expr=[[x_vars[(i, 0, k)] for i in data]], senses=['E'], rhs=[1.0])
  58. # 车辆容量限制
  59. for j in data:
  60. for k in range(1, num_vehicles+1):
  61. model.linear_constraints.add(lin_expr=[[x_vars[(i, j, k)] for i in data]], senses=['L'], rhs=[data[j]['demand']])
  62. # 时间窗口约束
  63. M = max(data[j]['due_date'] for j in data) + max(data[j]['service_time'] for j in data)
  64. for i in data:
  65. for j in data:
  66. for k in range(1, num_vehicles+1):
  67. model.linear_constraints.add(lin_expr=[[t_vars[i], data[i]['service_time'], data[i]['demand'], -M, x_vars[(i, j, k)], t_vars[j]]], senses=['L'], rhs=[data[j]['due_date']])
  68. return model
  69. # 解决VRPTW模型
  70. def solve_model(model, data, num_vehicles):
  71. try:
  72. model.solve()
  73. solution = model.solution
  74. if solution.get_status() == solution.status.optimal:
  75. print('最优解已找到')
  76. print('目标函数值:', solution.get_objective_value())
  77. print('路径安排:')
  78. for k in range(1, num_vehicles+1):
  79. print('车辆', k, ':')
  80. for i in data:
  81. for j in data:
  82. if solution.get_values(x_vars[(i, j, k)]) > 0.9:
  83. print(i, '->', j)
  84. print()
  85. else:
  86. print('求解失败')
  87. except CplexError as e:
  88. print('求解失败:', e)
  89. # 主函数
  90. if __name__ == '__main__':
  91. data, num_vehicles, vehicle_capacity = read_data('C101.txt')
  92. model = build_model(data, num_vehicles, vehicle_capacity)
  93. solve_model(model, data, num_vehicles)

五、蚁群算法求解

  1. import numpy as np
  2. import random
  3. # 读取数据
  4. def read_data(filename):
  5. # 从文件中读取服务点、客户的位置
  6. data = {}
  7. node_list = []
  8. with open(filename, 'rt') as f:
  9. count = 1
  10. for line in f:
  11. if count == 5:
  12. vehicle_num, vehicle_capacity = line.split()
  13. vehicle_num = int(vehicle_num)
  14. vehicle_capacity = int(vehicle_capacity)
  15. elif count >= 10:
  16. node_list.append(line.split())
  17. count += 1
  18. for item in node_list:
  19. customer_id = int(item[0])
  20. x = float(item[1])
  21. y = float(item[2])
  22. demand = float(item[3])
  23. ready_time = float(item[4])
  24. due_date = float(item[5])
  25. service_time = float(item[6])
  26. data[customer_id] = {
  27. 'x': x,
  28. 'y': y,
  29. 'demand': demand,
  30. 'ready_time': ready_time,
  31. 'due_date': due_date,
  32. 'service_time': service_time
  33. }
  34. return data, vehicle_num, vehicle_capacity
  35. # 计算两个节点之间的距离
  36. def calculate_distance(node1, node2):
  37. return np.sqrt((node1['x'] - node2['x'])**2 + (node1['y'] - node2['y'])**2)
  38. # 计算节点间的信息素初始值
  39. def initialize_pheromone(data):
  40. num_nodes = len(data)
  41. pheromone = np.ones((num_nodes, num_nodes))
  42. return pheromone
  43. # 更新信息素
  44. def update_pheromone(pheromone, ants, best_ant, evaporation_rate, Q):
  45. pheromone *= (1 - evaporation_rate) # 蒸发信息素
  46. for ant in ants:
  47. for i in range(len(ant['path']) - 1):
  48. node1 = ant['path'][i]
  49. node2 = ant['path'][i+1]
  50. pheromone[node1][node2] += Q / ant['total_distance'] # 更新路径上的信息素
  51. best_path = best_ant['path']
  52. for i in range(len(best_path) - 1):
  53. node1 = best_path[i]
  54. node2 = best_path[i+1]
  55. pheromone[node1][node2] += Q / best_ant['total_distance'] # 更新最佳路径上的信息素
  56. return pheromone
  57. # 选择下一个节点
  58. def select_next_node(pheromone, current_node, available_nodes, alpha, beta):
  59. probabilities = []
  60. total = 0
  61. for node in available_nodes:
  62. pheromone_value = pheromone[current_node][node]
  63. distance_value = 1 / calculate_distance(data[current_node], data[node])
  64. probability = (pheromone_value**alpha) * (distance_value**beta)
  65. probabilities.append(probability)
  66. total += probability
  67. probabilities = [p / total for p in probabilities]
  68. next_node = random.choices(available_nodes, probabilities)[0]
  69. return next_node
  70. # 构建初始路径
  71. def construct_initial_path(pheromone, alpha, beta):
  72. num_nodes = len(data)
  73. current_node = 0 # 仓库节点
  74. available_nodes = list(range(1, num_nodes)) # 可选节点
  75. path = [current_node]
  76. total_distance = 0
  77. while available_nodes:
  78. next_node = select_next_node(pheromone, current_node, available_nodes, alpha, beta)
  79. path.append(next_node)
  80. total_distance += calculate_distance(data[current_node], data[next_node])
  81. available_nodes.remove(next_node)
  82. current_node = next_node
  83. path.append(0) # 返回仓库节点
  84. total_distance += calculate_distance(data[current_node], data[0])
  85. return path, total_distance
  86. # 更新最佳路径
  87. def update_best_path(path, total_distance, best_ant):
  88. if total_distance < best_ant['total_distance']:
  89. best_ant['path'] = path
  90. best_ant['total_distance'] = total_distance
  91. # 蚁群算法求解VRPTW
  92. def solve_vrptw(data, num_vehicles, vehicle_capacity, num_ants, num_iterations, alpha, beta, evaporation_rate, Q):
  93. num_nodes = len(data)
  94. best_ant = {
  95. 'path': [],
  96. 'total_distance': float('inf')
  97. }
  98. pheromone = initialize_pheromone(data)
  99. for _ in range(num_iterations):
  100. ants = []
  101. for _ in range(num_ants):
  102. ant = {}
  103. ant['path'], ant['total_distance'] = construct_initial_path(pheromone, alpha, beta)
  104. ants.append(ant)
  105. update_best_path(ant['path'], ant['total_distance'], best_ant)
  106. pheromone = update_pheromone(pheromone, ants, best_ant, evaporation_rate, Q)
  107. return best_ant['path'], best_ant['total_distance']
  108. # 主函数
  109. if __name__ == '__main__':
  110. data, num_vehicles, vehicle_capacity = read_data('C101.txt')
  111. num_ants = 10 # 蚂蚁数量
  112. num_iterations = 100 # 迭代次数
  113. alpha = 1 # 信息素重要程度参数
  114. beta = 2 # 距离的重要程度参数
  115. evaporation_rate = 0.5 # 信息素蒸发率
  116. Q = 100 # 信息素增强强度
  117. best_path, best_distance = solve_vrptw(data, num_vehicles, vehicle_capacity, num_ants, num_iterations, alpha, beta, evaporation_rate, Q)
  118. print('最佳路径:', best_path)
  119. print('最佳路径总距离:', best_distance)

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号