使用PuLP优化电动汽车充电站选址遇不可行问题求助
问题排查与解决
模型不可行的核心原因
你的PuLP模型存在多处逻辑错误,导致与实际可行的全充电站场景冲突,具体如下:
变量定义错误
E变量的定义使用了range(len(e)),但代码中从未定义过e这个变量,应该替换为range(n)(n是候选节点数量,等于len(e_c))。初始状态约束错误
未定义S_start变量,且初始约束完全不符合实际流程:实际初始是出发前电量100kWh,行驶到第一个节点后电量才会减少,而不是直接将某个节点的电量设为100。电量流转逻辑颠倒
你的约束E[i+1] == E[i] - e_c[i] + (e_r[i] * X[i])假设先消耗路段电量再充电,但实际流程是到达节点后充电,再消耗电量行驶到下一个节点,逻辑完全相反。缺失关键约束
合理性验证中检查了行驶后电量不能为负,但模型中没有添加“到达节点后的电量≥0”的约束,同时对充电后电量上限的约束位置错误。
修正后的模型实现
重新梳理逻辑
明确变量代表的物理意义:
X[i]:二进制变量,1=在节点i建充电站,0=不建E_arrive[i]:到达节点i后的电量(行驶完对应路段后的剩余电量)E_leave[i]:离开节点i时的电量(若充电则为充电后的电量,不超过电池容量)
流程约束:
- 初始出发电量100kWh,行驶到第一个节点后电量为
100 - e_c[0] - 每个节点到达后电量不能为负
- 充电仅在节点i进行,充电后电量不超过100kWh
- 离开节点i时的电量必须足够行驶到下一个节点(最后一个节点除外)
修正后的代码
from pulp import * # 原参数保持不变 BC = 100 # battery capacity SOC_in = 1.0 # (%) initial state of charge SOC_max = 1.0 #(%) maximum SOC e_c = [23.5, 4.6, 4.4, 33.8, 89.5, 0. , 24.5, 4.7, 21.5, 0. , 0. , 16.2, 4.8, 20.1, 0. , 62.8, 0.6, 40.8, 41.1, 5.1, 16.7, 0. , 39.6, 9.6, 9.8, 23.7, 0. , 0. , 23.4, 5.3, 8.6, 23.7, 18.6, 5.8, 9.1, 0.1, 0. , 0.1, 0. , 0.3, 19.8, 0. , 4.9, 23.4, 7.7, 9.6, 8. , 1. , 0. , 0. , 0. , 0. , 28.1, 5.5, 9.3, 0. , 0.1, 27.9, 41.3, 2.8, 20.8, 6.4, 5.7, 28.4, 7.7, 35.2, 2.8, 21. , 11.8, 0.1, 21.6, 7.4, 13.5, 8.6, 7.5, 0. , 12.8, 10.5, 0.4, 0. , 0. , 0.5, 37.2, 5.8, 19. , 10.7, 21.7, 17.1, 0.9, 0. , 17.1, 12. , 7.9, 2.4, 0.2, 20.6, 4.9, 21.1] e_r = [30.7, 64.8, 31.2, 181.2, 2.2, 66.5, 30.3, 52.8, 43.8, 54.1, 151.1, 33.9, 22.2, 68.3, 66.4, 70.2, 170.5, 260.2, 32.7, 72.6, 89.1, 138.1, 54.6, 70.2, 24.3, 42.2, 44.4, 38. , 38.8, 30.1, 28.7, 179.4, 48.6, 96.6, 0.2, 38.5, 44.5, 0.4, 0.4, 28.8, 13.5, 25.5, 44.9, 196.8, 269.8, 215.7, 81.1, 166.6, 0.4, 0.4, 0.1, 22.3, 111.9, 36.9, 43.3, 38. , 712.2, 9.7, 25.2, 242.3, 24.5, 49.4, 31.6, 231.6, 0.4, 27.5, 228.6, 31.7, 685.1, 812.4, 84.5, 36.7, 28.4, 214.7, 0.5, 46. , 61.3, 0.4, 0.4, 22.4, 0.4, 0.5, 47.5, 27. , 43.8, 182.3, 24.2, 76.3, 54. , 748.8, 72. , 46. , 31.3, 113.2, 0.4, 22.7, 70.6, 78.9] candidate_nodes = range(len(e_c)) n = len(candidate_nodes) # Define optimization problem model = LpProblem("EV_charging_optimization", LpMinimize) ### Decision variables X = LpVariable.dicts("UseLocation", candidate_nodes, cat=LpBinary) # 到达节点i后的电量 E_arrive = LpVariable.dicts("EnergyArrive", candidate_nodes, lowBound=0, upBound=BC, cat=LpContinuous) # 离开节点i时的电量 E_leave = LpVariable.dicts("EnergyLeave", candidate_nodes, lowBound=0, upBound=BC, cat=LpContinuous) ### Objective function model += lpSum(X[i] for i in candidate_nodes) ### Constraints # 初始约束:出发电量100kWh,行驶到第一个节点后的电量 model += E_arrive[0] == SOC_in * BC - e_c[0] for i in candidate_nodes: # 到达节点后的电量不能为负(已通过lowBound保证,但显式约束更清晰) model += E_arrive[i] >= 0 # 充电逻辑:不充电则离开电量=到达电量;充电则加上e_r[i] model += E_leave[i] == E_arrive[i] + X[i] * e_r[i] # 充电后电量不超过电池容量 model += E_leave[i] <= BC * SOC_max # 行驶到下一个节点的约束(除最后一个节点) for i in range(n-1): # 到达下一个节点的电量 = 离开当前节点的电量 - 下一段路的能耗 model += E_arrive[i+1] == E_leave[i] - e_c[i+1] # 离开当前节点的电量必须足够行驶到下一个节点 model += E_leave[i] >= e_c[i+1] # Solve status = model.solve() # 输出结果 print(f"求解状态: {LpStatus[status]}") print(f"最少充电站数量: {int(value(model.objective))}") # 输出选中的节点 selected_nodes = [i for i in candidate_nodes if value(X[i]) == 1] print(f"选中的充电站节点: {selected_nodes}")
验证说明
修正后的模型完全匹配你合理性验证的逻辑:全充电站场景下,X[i]全部为1,此时每个节点充电后电量被限制在100kWh,行驶过程中电量不会为负,模型会返回可行解。
内容的提问来源于stack exchange,提问作者llamawithgrass
相关产品推荐
相关产品推荐

