作者简介:本人擅长运筹优化建模及算法设计,包括各类车辆路径问题、生产车间调度、二三维装箱问题,熟悉CPLEX和gurobi求解器
微信公众号:运筹优化与学习
问题描述
多车场的电动公交车调度问题(Multi Depot Electric Vehicle Scheduling Problem, MDEVSP)可描述为:已知具有固定始末点,始末时间的车次集合,寻找一种车次任务安排方案,使得:
(1) 每辆公交车按顺序完成一系列车次;
(2) 每个车次仅完成一次;
(3) 执行所有车次的费用最小.
数据输入包括:车次集合、车辆集合、车场集合以及充电站集合。每个车次有特定的开始时间、结束时间、旅行距离。每辆车具有有限的行驶距离,必须从车场出发,最后返回初始车场。假设车辆放电量与行驶里程呈线性关系(放电量=行驶里程乘以百公里耗电量)。每辆车可以在任意的充电站进行完全或部分充电,且充电量与充电时间呈线性关系。
模型构建
代码实现
定义模型变量及约束
def setup_constraints(mdl, Data, Time, Distance, M, g, r, Depot, V, R, T):
# setup_variables
arc = setup_arcs(Data, Time, R, T, V, Depot)
A = [(i, j, k) for i in V for j in V for k in range(Data.depotNum)]
H = [i for i in R]
mdl.x = mdl.binary_var_dict(A, name='x')
mdl.h = mdl.continuous_var_dict(H, lb=0, name='h')
mdl.z = mdl.continuous_var_dict(V, lb=0, name='z') # arrival time
mdl.y = mdl.continuous_var_dict(V, lb=0, ub=capacity, name='y') # remaining battery charge
for i in V:
for j in V:
for k in range(Data.depotNum):
if arc[i][j] == 0:
mdl.add_constraint(mdl.x[i, j, k] == 0)
# (1) 每个车次只被服务一次
for i in T:
mdl.add_constraint(mdl.sum(mdl.x[i, j, k] for k in range(Data.depotNum)
for j in Depot[1] + R + T) == 1)
# (2) 同一个充电站每辆车最多只能充电一次
for k in range(Data.depotNum):
for i in R:
mdl.add_constraint(mdl.sum(mdl.x[i, j, k] for j in R + T) <= 1)
# (3)
for index in range(Data.depotNum):
i = Depot[0][index]
mdl.add_constraint(mdl.sum(mdl.x[i, j, k] for k in range(Data.depotNum)
for j in Depot[1] + R + T if index != k) == 0)
# (4)
for index in range(Data.depotNum):
j = Depot[1][index]
mdl.add_constraint(mdl.sum(mdl.x[i, j, k] for k in range(Data.depotNum) if index != k
for i in Depot[0] + R + T) == 0)
# (5)
for k in range(Data.depotNum):
for i in R + T:
mdl.add_constraint(mdl.sum(mdl.x[i, j, k] for j in Depot[1] + R + T)
== mdl.sum(mdl.x[j, i, k] for j in Depot[0] + R + T))
# (6) 车次节点在指定的开始时间开始服务
mdl.add_constraints(mdl.z[i] == Time.readyTime[i] for i in T)
# (7) 车场与充电站只在规定时间窗内服务
mdl.add_constraints(Time.readyTime[i] <= mdl.z[i] for i in Depot[0] + Depot[1] + R)
mdl.add_constraints(Time.dueTime[i] >= mdl.z[i] for i in Depot[0] + Depot[1] + R)
# (8)
for i in T:
for j in V:
mdl.add_constraint(mdl.z[i] + Time.consume[i] + Distance[i][j] -
M * (1 - mdl.sum(mdl.x[i, j, k] for k in range(Data.depotNum))) <= mdl.z[j])
# (9)
for i in R:
for j in Depot[1] + T:
mdl.add_constraint(mdl.z[i] + Distance[i][j] + g * mdl.h[i] -
M * (1 - mdl.sum(mdl.x[i, j, k] for k in range(Data.depotNum))) <= mdl.z[j])
# (10)
for i in Depot[0] + T:
for j in Depot[1] + R + T:
mdl.add_constraint(mdl.y[i] - Time.consume[i] - r * Distance[i][j] +
M * (1 - mdl.sum(mdl.x[i, j, k] for k in range(Data.depotNum))) >= mdl.y[j])
# (11)
for i in R:
for j in R + T:
mdl.add_constraint(mdl.y[i] + mdl.h[i] - r * Distance[i][j] +
M * (1 - mdl.sum(mdl.x[i, j, k] for k in range(Data.depotNum))) >= mdl.y[j])
# (12)
mdl.add_constraints(mdl.h[i] <= capacity - mdl.y[i] for i in R)
获取完整代码,请关注微信公众号:运筹优化与学习,联系我们