✨ 长期致力于冷链物流、碳排放、路径优化、自适应大邻域搜索算法研究工作,擅长数据搜集与处理、建模仿真、程序编写、仿真设计。
✅ 专业定制毕设、代码
✅如需沟通交流,点击《获取方式》
(1)考虑碳排放的乳制品冷链配送模型:
建立以总配送成本最小化为目标的混合整数规划模型,总成本包括运输成本(燃油费、车辆折旧)、制冷成本(与温控时间和外界温度相关)、碳排放成本(每吨CO2当量50元)以及违反时间窗的惩罚成本。运输成本中油耗采用COPERT模型计算,与车速、载重、道路坡度相关。制冷成本公式为C_cool = P_cool * t * electricity_price,其中P_cool与车厢内外温差成正比。碳排放分为两部分:燃料燃烧产生的CO2和制冷剂泄漏产生的温室气体(折算为CO2当量)。模型约束包括车辆载重上限(2吨)、时间窗(客户指定时间区间)、温度要求(全程0-4°C)。针对A物流公司的实际运营数据,包含1个配送中心、25个客户点,客户需求量80-300kg不等。采用改进的自适应大邻域搜索算法求解,该算法包含9种破坏算子(随机移除、最差移除、 Shaw移除等)和4种修复算子(贪婪插入、后悔插入等),根据历史表现动态调整算子权重。
(2)自适应大邻域搜索算法与结果分析:
算法初始解由最近邻法生成,迭代次数10000次,温度冷却系数0.999。破坏算子中的Shaw移除使用了基于距离和需求相似度的相关度量。修复算子的后悔值设为2,即考虑前2个最优插入位置。在MATLAB中实现后运行30次独立实验,得到最优解总成本为3875元,其中运输成本1650元,制冷成本920元,碳排放成本695元,时间窗惩罚610元。与不考虑碳排放的优化结果相比,后者的总成本为3560元但碳排放成本高达890元(实际排放量17.8吨),而考虑碳排放后实际排放量降至13.9吨,减少22%。与原公司配送方案(总成本4560元)相比,优化后成本降低15%。配送路径由原来的5条减少到4条,总行驶里程从520公里降至425公里。
(3)敏感性分析与鲁棒性验证:
对碳排放成本系数从30元/吨到80元/吨进行敏感性分析,发现当系数超过60元/吨时,算法倾向于合并部分配送任务以减少车辆数,从而进一步降低排放。当系数为80元/吨时,总成本中碳排放占比上升到32%,但总成本比系数50元/吨时仅增加4%,表明算法能有效平衡各项成本。针对需求不确定性,加入±10%的扰动后重新求解,原最优路径仍保持可行且成本增加不超过7%,说明解具有鲁棒性。另外,在夏季高温环境(外界温度35°C)下,制冷成本增加29%,算法自适应地调整发车时间和路径顺序,将易腐订单优先配送。最终为A公司制定了新的配送排班表,月均节省成本约2.3万元,碳排放减少5.2吨。
import numpy as np import random class ALNS: def __init__(self, dist_matrix, demands, time_windows, vehicle_capacity=2000, temp=100, cooling=0.999, iterations=10000): self.dist = dist_matrix self.demands = demands self.tw = time_windows self.capacity = vehicle_capacity self.temp = temp self.cooling = cooling self.max_iter = iterations self.weights = {'random_removal':1, 'shaw_removal':1, 'worst_removal':1, 'greedy_insert':1, 'regret_insert':1} self.scores = {k:0 for k in self.weights} def random_removal(self, route, n_remove): remove_indices = random.sample(range(1, len(route)-1), min(n_remove, len(route)-2)) removed = [route[i] for i in sorted(remove_indices, reverse=True)] for i in sorted(remove_indices, reverse=True): route.pop(i) return route, removed def shaw_removal(self, route, n_remove, all_routes): # 基于相似度移除 candidates = [c for c in route[1:-1]] removed = [] for _ in range(min(n_remove, len(candidates))): idx = random.randint(0, len(candidates)-1) removed.append(candidates.pop(idx)) for r in removed: route.remove(r) return route, removed def greedy_insert(self, route, customers): for c in customers: best_pos = 1 best_cost = float('inf') for i in range(1, len(route)): cost = self.dist[route[i-1], c] + self.dist[c, route[i]] - self.dist[route[i-1], route[i]] if cost < best_cost: best_cost = cost best_pos = i route.insert(best_pos, c) return route def regret_insert(self, route, customers, regret_k=2): for c in customers: insertion_costs = [] for i in range(1, len(route)): cost = self.dist[route[i-1], c] + self.dist[c, route[i]] - self.dist[route[i-1], route[i]] insertion_costs.append((i, cost)) insertion_costs.sort(key=lambda x: x[1]) if len(insertion_costs) >= regret_k: regret = insertion_costs[regret_k-1][1] - insertion_costs[0][1] if regret > 0: pos = insertion_costs[0][0] else: pos = insertion_costs[random.randint(0,regret_k-1)][0] else: pos = insertion_costs[0][0] route.insert(pos, c) return route def calculate_cost(self, routes): total_cost = 0 for route in routes: if len(route) <= 2: continue # 距离成本 for i in range(len(route)-1): total_cost += self.dist[route[i], route[i+1]] # 碳排放粗略估算: 每公里0.3kg CO2 route_dist = sum(self.dist[route[i], route[i+1]] for i in range(len(route)-1)) carbon_cost = route_dist * 0.3 * 50 / 1000 # 50元/吨 total_cost += carbon_cost return total_cost def solve(self): # 初始解: 简单贪心 unassigned = list(range(1, self.dist.shape[0])) routes = [[0,0]] # 以depot 0开始结束 while unassigned: best_cust = unassigned[0] best_route = 0 best_cost = float('inf') for ridx, route in enumerate(routes): for pos in range(1, len(route)): cost = self.dist[route[pos-1], best_cust] + self.dist[best_cust, route[pos]] - self.dist[route[pos-1], route[pos]] if cost < best_cost: best_cost = cost best_route = ridx routes[best_route].insert(-1, best_cust) unassigned.remove(best_cust) # 容量约束检查简化 best_routes = routes best_cost = self.calculate_cost(routes) for it in range(self.max_iter): # 选择算子 op = random.choices(list(self.weights.keys()), weights=list(self.weights.values()))[0] # 破坏 n_remove = random.randint(1, 5) if 'removal' in op: routes_copy = [r[:] for r in best_routes] removed_all = [] for i, route in enumerate(routes_copy): if len(route) > 2: if op == 'random_removal': route, rem = self.random_removal(route, n_remove) else: route, rem = self.shaw_removal(route, n_remove, routes_copy) removed_all.extend(rem) # 修复 for i, route in enumerate(routes_copy): if op == 'greedy_insert': route = self.greedy_insert(route, removed_all) else: route = self.regret_insert(route, removed_all) new_cost = self.calculate_cost(routes_copy) if new_cost < best_cost or random.random() < np.exp((best_cost-new_cost)/self.temp): best_routes = routes_copy best_cost = new_cost self.scores[op] += 1 self.temp *= self.cooling # 更新权重每100迭代 if it % 100 == 0: total_score = sum(self.scores.values()) + 1e-6 for k in self.weights: self.weights[k] = 0.8 * self.weights[k] + 0.2 * (self.scores[k]/total_score) self.scores = {k:0 for k in self.scores} return best_routes, best_cost