基于python语言,实现经典粒子群算法(DPSO)对车辆路径规划问题(CVRP)进行求解, 优化代码结构,改进Split函数
往期优质资源
-
CVRP系列
-
遗传算法
蚁群算法
禁忌搜索算法
模拟退火算法
自适应大邻域算法
粒子群算法
量子粒子群算法
差分进化算法
MDVRP系列
-
遗传算法
蚁群算法
禁忌搜索算法
模拟退火算法
自适应大邻域算法
粒子群算法
量子粒子群算法
差分进化算法
VRPTW系列
-
遗传算法
蚁群算法
禁忌搜索算法
模拟退火算法
自适应大邻域算法
粒子群算法
量子粒子群算法
差分进化算法
HVRP系列
-
遗传算法
蚁群算法
禁忌搜索算法
模拟退火算法
自适应大邻域算法
粒子群算法
量子粒子群算法
差分进化算法
MDHFVRPTW系列
-
遗传算法
蚁群算法
禁忌搜索算法
模拟退火算法
自适应大邻域算法
粒子群算法
量子粒子群算法
差分进化算法
1. 适用场景
- 求解CVRP
- 车辆类型单一
- 车辆容量不小于需求节点最大需求
- 单一车辆基地
2. 改进效果对比
这里做了简单的参数敏感性分析,比较不同参数组合下两个版本code的最优值与求解时间的差异。具体为:1)设定权重w为0.7,0.8,0.9 ;2)设定学习因子c1为[0.5,4]步长为0.5等不同值,c2为[0.5,4]步长为0.5;其他参数:最大迭代次数为300,车辆容量为80。
2.1 实验结果汇总
改进后的split算子是基于图论的,相对比较耗时,但有一定提升效果。
2.2 目标函数对比
w=0.7
w=0.8
w=0.9
2.3 求解时间对比
w=0.7
w=0.8
w=0.9
3. 求解结果
(1)收敛曲线
(2)车辆路径
(3)输出文件
4. 部分代码
(1)数据结构
# 数据结构:解
class Sol():
def __init__(self):
self.node_no_seq=None # 解的编码
self.obj=None # 目标函数
self.route_list=None # 解的解码
self.route_distance = None # 车辆路径的长度集合
# 数据结构:网络节点
class Node():
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.node_id_list=[] # 需求节点集合
self.sol_list=[] # 解的集合
self.demand_dict={} #需求节点映射id集合
self.distance_matrix = {}
self.depot=None # 车场节点
self.number_of_demands=0 # 需求节点数量
self.vehicle_cap=0 # 车辆最大容量
self.Cr=0.5 # 差分交叉概率
self.F=0.5 # 差分变异概率
self.popsize=0
(2)距离矩阵
# 计算距离矩阵
def calDistanceMatrix(model):
for i in model.node_id_list:
for j in model.node_id_list:
d=math.sqrt((model.demand_dict[i].x_coord-model.demand_dict[j].x_coord)**2+
(model.demand_dict[i].y_coord-model.demand_dict[j].y_coord)**2)
model.distance_matrix[i,j]=d
dist = math.sqrt((model.demand_dict[i].x_coord - model.depot.x_coord) ** 2
+ (model.demand_dict[i].y_coord - model.depot.y_coord) ** 2)
model.distance_matrix[i, model.depot.id] = dist
model.distance_matrix[model.depot.id, i] = dist
(3)路径提取
def extractRoutes(node_no_seq,P,depot_id):
route_list = []
j = len(node_no_seq)
while True:
i = P[node_no_seq[j-1]]
route = [depot_id]
route.extend(node_no_seq[k] for k in range(i+1, j))
route.append(depot_id)
route_list.append(route)
j = i+1
if i == -1:
break
return route_list
(4)位置更新
# 更新位置
def updatePosition(model):
w=model.w
c1=model.c1
c2=model.c2
pg = model.pg
for id,sol in enumerate(model.sol_list):
x=sol.node_no_seq
v=model.v[id]
pl=model.pl[id].node_no_seq
r1=random.random()
r2=random.random()
new_v=[]
for i in range(model.number_of_demands):
v_=w*v[i]+c1*r1*(pl[i]-x[i])+c2*r2*(pg[i]-x[i])
if v_>0:
new_v.append(min(v_,model.Vmax))
else:
new_v.append(max(v_,-model.Vmax))
new_x=[min(int(x[i]+new_v[i]),model.number_of_demands-1) for i in range(model.number_of_demands) ]
new_x=adjustRoutes(new_x,model)
model.v[id]=new_v
new_x_obj,new_x_route_list,new_x_route_distance=calObj(new_x,model)
if new_x_obj<model.pl[id].obj:
model.pl[id].node_no_seq=copy.deepcopy(new_x)
model.pl[id].obj=new_x_obj
model.pl[id].route_list=new_x_route_list
model.pl[id].route_distance = new_x_route_distance
if new_x_obj<model.best_sol.obj:
model.best_sol.obj=copy.deepcopy(new_x_obj)
model.best_sol.node_no_seq=copy.deepcopy(new_x)
model.best_sol.route_list=copy.deepcopy(new_x_route_list)
model.best_sol.route_distance = copy.deepcopy(new_x_route_distance)
model.pg=copy.deepcopy(new_x)
model.sol_list[id].node_no_seq = copy.deepcopy(new_x)
model.sol_list[id].obj = copy.deepcopy(new_x_obj)
model.sol_list[id].route_list = copy.deepcopy(new_x_route_list)
model.sol_list[id].routes_distance = copy.deepcopy(new_x_route_distance)
5. 完整代码
如有错误,欢迎交流。
私信,有偿
参考
- A simple and effective evolutionary algorithm for the vehicle routing problem