dist = sum(C[route[i], route[i + 1]] for i in range(len(route) - 1))
ws.write(row + 2, 0, f'{row + 1}')
ws.write(row+2,1,'-'.join(route_str))
ws.write(row + 2, 2, dist)
row += 1
wb.close()
# 建模和求解
def solve_model(N,I,J,K,Q,V_CAP,C,XY):
"""
:param N: 所有节点
:param I: 客户节点
:param J: 车场节点
:param K: 车辆节点
:param Q: 客户需求
:param V_CAP: 车辆容量
:param C: 成本矩阵
:param XY: 节点坐标
:return: nan
"""
model = Model('MDVRP')
# 添加变量
X = model.addVars(N,N,K,vtype=GRB.BINARY,name='X[i,j,k]')
U = model.addVars(K, N, vtype=GRB.CONTINUOUS, name='U[k,i]')
# 目标函数
obj = quicksum(X[i,j,k]*C[i,j] for i in N for j in N for k in K)
model.setObjective(obj,GRB.MINIMIZE)
# 需求覆盖约束
model.addConstrs( (quicksum(X[i,j,k] for j in N for k in K if i != j) == 1 for i in I),name='eq1' )
# 车辆容量约束
model.addConstrs( (quicksum(X[i,j,k]*Q[i] for i in I for j in N if i != j) <= V_CAP for k in K),name= 'eq2')
# 车辆起点约束
model.addConstrs( (quicksum(X[j,i,k] for j in J for i in I if i != j) == 1 for k in K),name='eq3' )
# 中间节点流平衡约束
model.addConstrs( (quicksum(X[i, j, k] for j in N if i != j) == quicksum(X[j, i, k] for j in N if i != j) for i in I for k in K),name='eq4' )
# 车辆终点约束
model.addConstrs( (quicksum(X[i,j,k] for i in I for j in J if i != j) == 1 for k in K), name='eq5' ) # 开放式
# model.addConstrs( (quicksum(X[j,i,k] for i in I) == quicksum(X[i,j,k] for i in I) for k in K for j in J), name='eq5') # 不开放式
# 破除子环
model.addConstrs(U[k, i] - U[k, j] + V_CAP * X[i, j, k] <= V_CAP - Q[i] for i in I for j in I for k in K)
model.addConstrs(Q[i] <= U[k, i] for k in K for i in I)
model.addConstrs(U[k, i] <= V_CAP for k in K for i in I)
# 避免车辆直接在车场间移动
model.addConstrs( X[i,j,k] == 0 for i in J for j in J for k in K )
# 求解
model.Params.TimeLimit = 300 # 设置求解时间上限
model.optimize()
if model.status == GRB.Status.OPTIMAL or model.status == GRB.Status.TIME_LIMIT:
route_list = extract_routes(I,J,X,K)
draw_routes(route_list, XY, I,J)
save_file(route_list, model.objVal, C)
else:
model.computeIIS()
model.write('model.ilp')
for c in model.getConstrs():
if c.IISConstr:
print(f'{c.constrName}')
print("no solution")
if __name__ == '__main__':
demand_file = r'./input/demand2.csv'
depot_file = r'./input/depot.csv'
N, I, J, C, Q, XY = read_csv_file(demand_file=demand_file, depot_file=depot_file)
K = list(range(0,10))
V_CAP = 80
solve_model(N, I, J, K, Q, V_CAP, C,XY)
复制代码
4. 求解结果
4.1 开放式车场
4.2 非开放式车场
参考
Ramos, T. R. P., Gomes, M. I., & Póvoa, A. P. B. (2019). Multi-depot vehicle routing problem: a comparative study of alternative formulations. International Journal of Logistics Research and Applications, 23(2), 103–120. https://doi.org/10.1080/13675567.2019.1630374