有没有运筹优化方面的同志帮忙看一下我写的代码,我的代码很简单。我的模型是想要求解一个电动公交的最优的行车链,以最大化企业收益为目标,约束条件包括发车约束,以及电动公交执行任务和充电时候的电量更新,没电要充电,就是那么简单,奈何我是这方面刚开始学。一直做不出来,麻烦各位同志帮我看看
from gurobipy import Model, GRB, quicksum, or_
import numpy as np
import gurobipy as gp
# 输入数据
B = 3 # 电动公交车辆数量
L = 20# 行程任务数量
F = L # 充电节点数量
M = 4 # 分割点集合
τ_p =6 # 每位乘客收入
E_p=28
T_p=15
τ_e = 2 # 电量成本
c_null = 1 # 空驶电量成本
W = 100000 # 大数值
SOC_full = 100 # 初始电量
t_min, t_max = 10, 40 # 最小最大发车间隔,放宽限制
Z_initiate, Z_end = 0, 450# 首末班车发车时刻
Y = 200 # 固定成本参数
γ = 0.1 # 固定成本参数
t_age, β, r_0, S_dr = 10, 0.9, 50, 30 # 固定成本参数
θ = 0.3 # 加权延误时间成本参数
# 修改后的节点顺序:交替出现任务节点和充电节点
task_nodes = list(range(1, L + 1))
charging_nodes = list(range(L + 1, 2 * L + 1))
nodes = [val for pair in zip(task_nodes, charging_nodes) for val in pair]
#e = np.random.uniform(30,38, (H)) # 电量消耗
#p = np.random.randint(20, 50, (H)) # 乘客数量
p=[13, 50, 20, 86, 39, 31]
e=[13.28, 21.54, 18.21, 21.88, 19.75, 14.71]
ρ = [0.33,0.06, 0.33, 0.01, 0.13,0.14] # 情景发生概率
t = [26.81659693, 87.24644013,40.70677871, 126.112585, 47.89251773, 30.89393045]
H = len(ρ) # 情景数量
o, d = 0, 2 * L + 1 # 出发和到达节点
N = [o] + nodes + [d]
print(N)
# 初始化模型
model = Model("ElectricBusScheduling")
c_points = [0, 10, 30,50] # Example custom points for charging time
a_points = [0, 30, 90, 100] # Example custom points for SOC
print(type(c_points[0]))
# 定义后继节点字典
successors = {nodes[i]: nodes[i+1] for i in range(0, len(nodes)-1)}
successors.update({nodes[i+1]: nodes[i+2] if i+2 < len(nodes) else d for i in range(0, len(nodes)-1, 2)})
successors[o] = nodes[0]
successors[d] = [d]
# 定义变量
Z = model.addVars(task_nodes+charging_nodes, vtype=GRB.INTEGER, name="Z")
Z1 = model.addVars(task_nodes, B, vtype=GRB.INTEGER, name="Z1")
Z2 = model.addVars(task_nodes, B, vtype=GRB.INTEGER, name="Z2")
Z3 = model.addVars(charging_nodes, B, vtype=GRB.INTEGER, name="Z3")
Z4 = model.addVars(charging_nodes, B, vtype=GRB.INTEGER, name="Z4")
SOC = model.addVars(nodes,B, lb=0,ub=100,vtype=GRB.CONTINUOUS, name="SOC")
SOC1 = model.addVars(task_nodes+charging_nodes, B,lb=0,ub=100, vtype=GRB.CONTINUOUS, name="SOC1")
SOC2 = model.addVars(task_nodes+charging_nodes, B,lb=0,ub=100, vtype=GRB.CONTINUOUS, name="SOC2")
#E3 = model.addVars(charging_nodes, B,lb=0,ub=100, vtype=GRB.CONTINUOUS, name="SOC1")
#E4 = model.addVars(charging_nodes, B,lb=0,ub=100, vtype=GRB.CONTINUOUS, name="SOC2")
o=model.addVars(task_nodes+charging_nodes, B, vtype=GRB.BINARY, name="o")
Oa = model.addVars(task_nodes, B, H, vtype=GRB.BINARY, name="oa")
x = model.addVars(nodes, nodes, B, vtype=GRB.BINARY, name="x")
#x1 = model.addVars(task_nodes, charging_nodes, B, vtype=GRB.BINARY, name="x")
#x2= model.addVars(charging_nodes, task_nodes, B, vtype=GRB.BINARY, name="x1")
u = model.addVars(L, B, vtype=GRB.BINARY, name="u")
y1 = model.addVars(charging_nodes, B, M, vtype=GRB.CONTINUOUS, name="y1")
y2 = model.addVars(charging_nodes, B, M, vtype=GRB.CONTINUOUS, name="y2")
w1 = model.addVars(charging_nodes, B, M, vtype=GRB.BINARY, name="w1")
w2 = model.addVars(charging_nodes, B, M, vtype=GRB.BINARY, name="w2")
charge_time = model.addVars(charging_nodes,B, vtype=GRB.CONTINUOUS, name="charge_time")
# 弧集合
arcs = set()
arcs1 = set()
# 添加起点到任务节点的弧
arcs.add(('o', f'{task_nodes[0]}'))
arcs1.add(('o', f'{task_nodes[0]}'))
arcs.add((f'{task_nodes[-1]}','d' ))
arcs1.add(('o', f'{task_nodes[0]}'))
arcs.add((f'{charging_nodes[-1]}','d' ))
# 添加任务节点到充电节点的弧,充电节点到其他任务节点或终点的弧
for i in task_nodes:
for j in charging_nodes:
if j==i+20:
arcs.add((i, j)) # Task node to corresponding charging node
for i in task_nodes:
for j in task_nodes[i:]:
arcs1.add((i,j)) # Task node to task node
for j in charging_nodes:
for r in task_nodes:
if r+21>=j:
arcs.add((j,r))
def has_arc_connection(node1, node2, arc_set):
return (node1, node2) in arc_set
print(arcs1)
#for i in task_nodes:
# for j in task_nodes:
# if has_arc_connection(i, j, arcs1):
# print(f"There is an arc connection between {i} and {j}")
# else:
# print(f"There is no arc connection between {i} and {j}")
#sorted_arcs = sorted(list(arcs1))
#print(sorted_arcs)
def calculate_charging_time(SOC_start, SOC_end, charging_rate):
# Placeholder logic for calculating charging time
if charging_rate == 0:
return 0
return (SOC_end - SOC_start) / charging_rate
# Define variables
charge_time = model.addVars(charging_nodes, B, vtype=GRB.CONTINUOUS, name="charge_time")
charging_rate = 10 # Example constant charging rate
# Define charging time calculation within the constraints
# 目标函数
last_task_node=task_nodes[0]
print(task_nodes)
income = quicksum((p[h] * T_p * ρ[h] * o[i, b]) for i in task_nodes for h in range(H) for b in range(B))
cost = quicksum((SOC2[a,b]-SOC1[a,b])* E_p * ρ[h] * o[a, b] + c_null * 5 * x[i, a, b] for i in task_nodes for a in charging_nodes for b in range(B) for h in range(H))
fixed_cost = (Y * (1 - γ) / (t_age * β * 365) + r_0 + S_dr) / M
for i in task_nodes:
if i == last_task_node:
continue # 跳过最后一个点
delay_cost = quicksum((θ * p[h] * (Z[i+1] - Z[i]) * ρ[h]) for h in range(H) for b in range(B))
model.setObjective(income - cost - fixed_cost - delay_cost, GRB.MAXIMIZE)
model.addConstr(Z[1] == Z_initiate)
model.addConstr(Z[L] == Z_end)
model.addConstr(Z1[1, 0] == Z_initiate)
for b in range(B):
for i in task_nodes:
a=successors[i]
model.addConstr(SOC2[i, b] >= 40 * (1 - x[i, a, b]))
model.addConstr(SOC1[a, b] >= 40 * (1 - o[a, b]))
for i in task_nodes:
#model.addConstrs((quicksum(Oa[i, b, h] for b in range(B)) == 1 for h in range(H)), name=f"TaskAssigned1_{i}")
model.addConstr((quicksum(o[i, b] for b in range(B)) == 1),name=f"TaskAssign2_{i}")
#model.addConstrs((Oa[i, (i % B), h] == 1 for h in range(H)), name=f"TaskAssignmentOrder_{i}")
model.addConstr((o[i, (i % B)] == 1), name=f"TaskAssignmentOrder2_{i}")
model.addConstr((Z[i + 1] - Z[i] >= t_min), name=f"DepartureInterval_LowerBound2_{i}")
model.addConstr((Z[i + 1] - Z[i] <= t_max), name=f"DepartureInterval_UpperBound2_{i}")
for a in charging_nodes:
model.addConstr((quicksum(o[a, b] for b in range(B)) == 1),name=f"TaskAssign2_{i}")
#model.addConstrs((Oa[i, (i % B), h] == 1 for h in range(H)), name=f"TaskAssignmentOrder_{i}")
model.addConstr((o[a, (a % B)] == 1), name=f"TaskAssignmentOrder2_{i}")
for i in task_nodes[1:]:
for j in task_nodes[:i]:
if i != j:
for r in task_nodes[i:]:
if i != r:
model.addConstr(((quicksum(x[j, i, b] for b in range(B)) == quicksum(x[i, r, b] for b in range(B)))), name=f"TaskAssigned1_{i}_{j}_{r}")
for i in task_nodes:
model.addConstr((quicksum(x[i, successors[i], b] for b in range(B)) <= 1 ),name=f"TaskAssigned_a_2_{i}")
model.addConstr((quicksum(x[i,j,b]for j in nodes[i:] for b in range(B)) == 1), name=f"TaskAssigned_2_{i}")
for a in charging_nodes:
model.addConstrs((quicksum(x[a, j, b] for b in range(B))<= 1 for j in task_nodes[a:]), name=f"TaskAssigned_a_3_{j}")
model.addConstr(SOC[1, b] == SOC_full, name=f"SOC_Full1_{b}") #满电约束
model.addConstr(SOC1[1, b] == SOC_full, name=f"SOC_Full2_{b}")
for b in range(B):
for i in task_nodes:
#任务时刻更新
model.addConstr(Z[i] <= Z1[i, b]+W * (1 - o[i, b]) )
model.addConstr(Z[i] >= Z1[i, b]-W * (1 - o[i, b]) )
#开始时间电量更新
model.addConstr((SOC1[i, b] - E_p +W * (1 - o[i, b])>=SOC2[i,b]),name=f"SOC_UpperBound6_{i}_{b}")
model.addConstr((SOC1[i, b] -E_p -W * (1 - o[i, b] )<= SOC2[i,b]),name=f"SOC_LowerBound7_{i}_{b}")
model.addConstr((Z1[i,b] +15 +W * (1 - o[i, b]) >=Z2[i,b] ),name=f"Z2_LowerBound8_{i}_{b}")
model.addConstr((Z1[i,b] +15- W * (1 - o[i, b]) <= Z2[i,b]),name=f"Z2_UpperBound9_{i}_{b}")
for j in task_nodes[i:]:
if has_arc_connection(i, j, arcs1):
#print(b,i,j)
model.addConstr((Z2[i,b] +1-W * (1 - x[i, j, b]) <=Z[j] ),name=f"Z2_LowerBound8_{i}")
model.addConstr((Z2[i,b]+1+ W * (1 - x[i, j, b])>=Z[j] ), name=f"Z2_LowerBound9_{i}")
model.addConstr((SOC2[i, b]-5+W * (1 - x[i, j, b])>=SOC1[j,b]),name=f"SOC2_LowerBound8_{i}")
model.addConstr((SOC2[i, b]-5- W * (1 - x[i, j, b]) <=SOC1[j,b]), name=f"SOC2_LowerBound9_{i}")
model.addConstr((Z2[i, b] + 1 - W * (1 - x[i, j, b]) <= Z1[j,b]), name=f"Z2_LowerBound8_{i}")
model.addConstr((Z2[i, b] + 1 + W * (1 - x[i, j, b]) >= Z1[j,b]), name=f"Z2_LowerBound9_{i}")
model.addConstr((SOC2[i, b] - 5 + W * (1 - x[i, j, b]) >= SOC1[j, b]),name=f"SOC2_LowerBound8_{i}")
model.addConstr((SOC2[i, b] - 5 - W * (1 - x[i, j, b]) <= SOC1[j, b]), name=f"SOC2_LowerBound9_{i}")
for a in charging_nodes:
if has_arc_connection(i, a, arcs):
print(b, i, a)
model.addConstr((SOC2[i, b] - 5 + W * (1 - x[i, a, b]) >= SOC1[a, b]), name=f"SOC_UpperBound6_{i}")
model.addConstr((SOC2[i, b] - 5 - W * (1 - x[i, a, b]) <= SOC1[a, b]), name=f"SOC_LowerBound7_{i}")
model.addConstr((Z2[i, b] + 1 - W * (1 - x[i, a, b]) <= Z3[a, b]), name=f"Z2_LowerBound8_{i}")
model.addConstr((Z2[i, b] + 1 + W * (1 - x[i, a, b]) >= Z3[a, b]), name=f"Z2_LowerBound9_{i}")
model.addConstr(Z2[i, b] + 1 + W * (1 - x[i, a, b]) >= Z[a], name=f"Z_a_LowerBound7_{a}")
model.addConstr(Z2[i, b] + 1 - W * (1 - x[i, a, b]) <= Z[a], name=f"Z_a_UpperBound8_{a}")
model.addConstr(SOC2[i, b] - 5 + W * (1 - x[i, a, b]) >= SOC[a, b], name=f"SOC_a_LowerBound7_{a}_{b}")
model.addConstr(SOC2[i, b] - 5 - W * (1 - x[i, a, b]) <= SOC[a, b], name=f"SOC_a_UpperBound8_{a}_{b}")
model.addConstr(SOC1[a, b] + 30 + W * (1 - o[a, b]) >= SOC2[a, b], name=f"SOC_a_LowerBound7_{a}_{b}")
model.addConstr(SOC1[a, b] + 30 - W * (1 - o[a, b]) <= SOC2[a, b], name=f"SOC_a_LowerBound7_{a}_{b}")
model.addConstr(Z3[a, b] + 10 + W * (1 - o[a, b]) >= Z4[a, b], name=f"SOC_a_LowerBound7_{a}_{b}")
model.addConstr(Z3[a, b] + 10 - W * (1 - o[a, b]) <= Z4[a, b], name=f"SOC_a_LowerBound7_{a}_{b}")
model.addConstr(SOC[a,b] + 30 + W * (1 - o[a, b]) >= SOC2[a, b], name=f"SOC_a_LowerBound7_{a}_{b}")
model.addConstr(SOC[a,b] + 30 - W * (1 - o[a, b]) <= SOC2[a, b], name=f"SOC_a_LowerBound7_{a}_{b}")
model.addConstr(Z[a] + 10 + W * (1 - o[a, b]) >= Z4[a, b], name=f"SOC_a_LowerBound7_{a}_{b}")
model.addConstr(Z[a] + 10 - W * (1 - o[a, b]) <= Z4[a, b], name=f"SOC_a_LowerBound7_{a}_{b}")
for k in task_nodes[i:]:
if has_arc_connection(a, k, arcs):
print(b,i,a,k)
model.addConstr((SOC2[a, b] - 5 + W * (1 - x[a, k, b]) >= SOC1[k, b]),name=f"SOC_k_Update1_{a}_{b}")
model.addConstr((SOC2[a, b]- 5 - W * (1 - x[a,k ,b]) <= SOC1[k, b]),name=f"SOC_k_Update2_{a}_{b}")
model.addConstr((Z4[a, b] + 1 + W * (1 - x[a, k,b]) >= Z1[k, b]),name=f"Z_k_Update1_{a}_{b}")
model.addConstr((Z4[a, b] + 1 - W * (1 - x[a,k, b]) <= Z1[k, b]),name=f"Z_k_Update2_{a}_{b}")
#.addConstrs((SOC[a, a % B] - 5 + charge_time[a, a % B] * 2 + W * (1 - x[a, k, a % k % B]) >= SOC[k, k % B]),name=f"SOC1_k_UpperBound_{a}")
#model.addConstrs((SOC[a, a % B] - 5 + charge_time[a, a % B] * 2 - W * (1 - x[a, k, a % k % B]) <= SOC[k, k % B]),name=f"SOC1_k_LowerBound_{a}")
#model.addConstrs((Z[a] + 1 + charge_time[a, a % B] + W * (1 - x[a, k, a % k % B]) >= Z[k]),name=f"Z1_k_LowerBound_{a}")
#model.addConstrs((Z[a] + 1 + charge_time[a, a % B] - W * (1 - x[a, k, a % k % B]) <= Z[k]),name=f"Z1_k_UpperBound_{a}")
# Assuming you need to calculate and constrain charge_time based on SOC1, SOC2, and charging_rate
#model.addConstr(charge_time[a, a % B] == calculate_charging_time(SOC1[a, a % B], SOC2[a, a % B], charging_rate),name=f"ChargingTime_{a}_{b}")
# Optimize the model
model.optimize()
print(x[1,20,2].X)
print(o[7,1].X)
print(o[10,1].X)
# Check for constraint violations
def check_constraints():
violations = []
if model.status == GRB.OPTIMAL:
for constr in model.getConstrs():
slack = constr.getAttr(GRB.Attr.Slack)
if slack < 0:
violations.append(constr.ConstrName)
else:
print("Model did not reach an optimal solution. Status:", model.status)
return violations
if model.status == GRB.OPTIMAL:
for b in range(B):
for a in charging_nodes:
for i in task_nodes:
#print(a,b)
if x[i,a, b].X > 0.5:
charge_start = Z3[a,b].X
charge_end = Z4[a, b].X
soc_start = SOC1[a, b].X
soc_end = SOC2[a, b].X
print(f" Charging at node {a}: Start time = {charge_start}, End time = {charge_end}, SOC start = {soc_start}, SOC end = {soc_end}")
#
# Output results if optimal solution is found
if model.status == GRB.OPTIMAL:
for b in range(B):
print(f"Bus {b }:")
for i in task_nodes:
for j in task_nodes:
if x[i,j, b].X > 0.5:
print(f" Task {i}: Departure time = {Z1[i,b].X},{Z2[i,b].X},SOC:={SOC1[i,b].X},{SOC2[i,b].X}")
for i in charging_nodes:
print(Z[i])
# Save the model
model.computeIIS()
model.write(r"D:/model.ilp")
model.write(r"D:/electric_bus_scheduling_with_charging.lp")
#Check violated constraints()
#violated_constraints = check_constraints()
#if violated_constraints:
# print(f"Violated constraints: {violated_constraints}")
# Check for infeasibility or unboundedness
if model.status == GRB.UNBOUNDED:
print("Model is unbounded. Checking constraints and variables...")
model.computeIIS()
model.write(r"D:/model.ilp")
print("Irreducible inconsistent subsystem written to 'model.ilp'")
elif model.status == GRB.INFEASIBLE:
print("Model is infeasible. Checking for conflicts...")
model.computeIIS()
model.write(r"D:/model.ilp")
print("Irreducible inconsistent subsystem written to 'model.ilp'")
elif model.status == GRB.OPTIMAL:
print("Optimal solution found.")
else:
print(f"Optimization ended with status {model.status}")