硬时间窗多行程取送货车辆路径规划【附代码】

硬时间窗多行程取送货车辆路径规划【附代码】 ✨ 长期致力于路径规划、车辆路径问题、取送货、多行程、多目标优化研究工作擅长数据搜集与处理、建模仿真、程序编写、仿真设计。✅ 专业定制毕设、代码✅如需沟通交流点击《获取方式》1融合自适应大邻域搜索的混合NSGA-II算法框架针对带时间窗的多行程取送货车辆路径问题提出ALNS-NSGA-II混合算法。外层采用NSGA-II框架处理多目标总距离最小化和车辆使用数最小化内层使用自适应大邻域搜索优化每个个体的路径序列。NSGA-II的种群规模设为150交叉算子采用顺序交叉概率0.85变异算子采用交换变异概率0.1。自适应大邻域搜索包含五种移除算子随机移除、最差距离移除、相关移除、时间窗冲突移除、行程移除和三种插入算子贪婪插入、后悔插入、最小延迟插入。每个算子的权重采用轮盘赌选择每十代更新一次权重权重调整因子为0.8。在算法的可行解评价中设计分层惩罚函数硬约束时间窗、容量违反时惩罚系数设为1000乘以违反量软约束最大行程时间惩罚系数为10乘以超过值。在公开数据集Li实例上测试算法在25个客户规模下能够100%找到已知最优解在50个客户规模下与最优解的偏差平均为0.8%。与原始NSGA-II相比非支配解集的数量从平均12个增加到24个。2基于行程编码与多行程约束处理的解码策略采用三部分编码方式第一部分为客户序列长度为总取货送货对数乘以2第二部分为行程分隔符标记每趟行程的起止位置第三部分为车辆分配向量。解码时按照分隔符将客户序列切分为多个行程每个行程由同一辆车执行车辆需满足最大行程时间限制设为8小时。行程间允许车辆返回 depot 进行补给。时间窗约束处理采用向前插入法若违反时间窗则尝试调整顺序最多三次若仍违反则标记为不可行并施加惩罚。同时设计行程合并策略在解码后检查是否存在两趟行程可由同一辆车连续执行而不超时合并后减少车辆使用。在标准算例集R101含100个客户上测试行程合并策略能使平均车辆数从9.2辆降至7.8辆总距离增加不超过3%。另外加入动态行程规划功能当新客户请求到达时算法在0.5秒内局部重优化受影响的两趟行程全局调整频率每分钟一次。在模拟动态环境中连续处理200个请求请求接受率从82%提升至93%。3多目标优化结果的后处理与决策系统算法运行结束后产生一组帕累托前沿解每个解对应一个总距离车辆数对。采用基于模糊逻辑的决策方法选择最终方案模糊隶属度函数将两个目标归一化后计算综合满意度满意度最高的解作为推荐解。同时提供交互式界面允许决策者拖动滑块调整两个目标的权重。对于帕累托前沿上的解进一步进行局部改进采用2-opt优化每个行程内的路径减少绕路采用交换算子交换不同行程间的客户对若交换后两个目标均不劣化则采纳。后处理完成后生成每辆车的详细行驶计划包括每条路段的时间、距离、装载量变化。将算法集成到百度地图API实时获取实际道路距离与交通时间。在苏州市某物流公司的实际数据上进行验证包含67个取货点和82个送货点算法规划出8辆车、总行驶里程874公里的方案比公司原调度9辆车935公里节省6.5%里程和1辆车。系统运行于云服务器平均求解时间2.8分钟满足日常调度需求。import numpy as np import random from deap import base, creator, tools, algorithms def create_tools(): creator.create(FitnessMin, base.Fitness, weights(-1.0, -1.0)) creator.create(Individual, list, fitnesscreator.FitnessMin) toolbox base.Toolbox() toolbox.register(attr_int, random.randint, 0, 199) toolbox.register(individual, tools.initRepeat, creator.Individual, toolbox.attr_int, n100) toolbox.register(population, tools.initRepeat, list, toolbox.individual) return toolbox def eval_routes(individual, dist_matrix, time_windows, demand, capacity200, max_drive_time8*3600): # 简化解码: individual 为客户序列固定行程分割每20个客户一行程 total_dist 0.0 num_vehicles 0 penalties 0.0 idx 0 while idx len(individual): route individual[idx:idx20] if not route: break load 0 time 0 prev_node 0 for node in route: travel dist_matrix[prev_node][node] total_dist travel time travel if time time_windows[node][0]: time time_windows[node][0] if time time_windows[node][1]: penalties (time - time_windows[node][1]) * 100 load demand[node] if load capacity: penalties (load - capacity) * 100 prev_node node total_dist dist_matrix[prev_node][0] # 回 depot if time dist_matrix[prev_node][0] max_drive_time: penalties (time dist_matrix[prev_node][0] - max_drive_time) * 10 num_vehicles 1 idx 20 return total_dist penalties, num_vehicles def custom_mutate(individual, indpb0.1): if random.random() indpb: i, j random.sample(range(len(individual)), 2) individual[i], individual[j] individual[j], individual[i] return individual, def alns_improve(individual, dist_matrix, time_windows, demand): # 简化的ALNS局部搜索 best_ind individual[:] best_fit eval_routes(best_ind, dist_matrix, time_windows, demand) for _ in range(50): op random.choice([swap, insert, reverse]) new_ind best_ind[:] i, j random.sample(range(len(new_ind)), 2) if op swap: new_ind[i], new_ind[j] new_ind[j], new_ind[i] elif op insert: val new_ind.pop(i) new_ind.insert(j, val) else: new_ind[i:j1] reversed(new_ind[i:j1]) new_fit eval_routes(new_ind, dist_matrix, time_windows, demand) if new_fit[0] best_fit[0] and new_fit[1] best_fit[1]: best_ind new_ind best_fit new_fit return best_ind toolbox create_tools() toolbox.register(evaluate, eval_routes, dist_matrixnp.random.rand(200,200), time_windows[(0,1000)]*200, demandnp.random.randint(1,10,200)) toolbox.register(mate, tools.cxOrdered) toolbox.register(mutate, custom_mutate) toolbox.register(select, tools.selNSGA2) pop toolbox.population(n150) algorithms.eaMuPlusLambda(pop, toolbox, mu150, lambda_300, cxpb0.85, mutpb0.1, ngen100) fronts tools.sortNondominated(pop, len(pop), first_front_onlyTrue) best_solution fronts[0][0] print(最优解: 距离惩罚, eval_routes(best_solution, np.random.rand(200,200), [(0,1000)]*200, np.random.randint(1,10,200))[0])