使用Gurobi Solver求解线性规划时遇TypeError错误求助
问题排查与修正
错误核心原因
- 你调用
model.addVars()得到的x是Gurobi的tupledict对象,并非普通Python列表或numpy数组。当你在c1函数里将变量与numpy数组运算后,返回的是gurobipy.LinExpr对象,该对象不支持索引访问(即不能用[i]),这就是触发TypeError: 'gurobipy.LinExpr' object is not subscribable的直接原因。 - 额外问题:代码中存在大量重复的数据加载逻辑,既冗余又易出错;约束
c2是全局CFE目标约束,不需要循环添加500次。
修正步骤
- 提前预处理数据:一次性提取所有需要用到的切片数据,避免在每个函数里重复操作。
- 直接用Gurobi变量构建表达式:不要试图将Gurobi变量转成numpy数组,而是通过循环或Gurobi内置方法直接构建目标函数与约束。
- 修正约束逻辑:
c1是500个逐时段的能量平衡约束,需逐个构建;c2是单个全局约束,无需循环。
修正后的完整代码
import pandas as pd import gurobipy as gp from gurobipy import GRB import numpy as np # 预处理数据(仅执行一次) TEST = pd.read_excel('/Users/Desktop/project/Datasets/Test2031.xlsx') TEST_matrix = TEST.to_numpy() load_slice = TEST_matrix[:500, 0].flatten() wind_slice = TEST_matrix[:500, 1].flatten() solar_slice = TEST_matrix[:500, 2].flatten() gridPrice_slice = TEST_matrix[:500, 4].flatten() COSTWIND = 70 COSTSOLAR = 70 target = 0.85 # CFE目标值 # 创建Gurobi模型 model = gp.Model() # 定义变量:明确含义,避免索引混淆 x1 = model.addVar(lb=0, ub=10000000, name="Wind_MW") x2 = model.addVar(lb=0, ub=10000000, name="Solar_MW") y = model.addVars(500, lb=0, ub=10000000, name="Grid_MWh") z = model.addVars(500, lb=0, ub=10000000, name="Excess_WindSolar_MWh") # 构建目标函数 obj = (x1 * COSTWIND * np.sum(wind_slice) + x2 * COSTSOLAR * np.sum(solar_slice) + gp.quicksum(gridPrice_slice[t] * y[t] for t in range(500))) model.setObjective(obj, GRB.MINIMIZE) # 添加逐时段能量平衡约束(原c1) for t in range(500): model.addConstr( x1 * wind_slice[t] + x2 * solar_slice[t] + y[t] - z[t] == load_slice[t], name=f"Energy_Balance_{t}" ) # 添加全局CFE目标约束(原c2) total_generation = x1 * np.sum(wind_slice) + x2 * np.sum(solar_slice) total_excess = gp.quicksum(z[t] for t in range(500)) total_load = np.sum(load_slice) model.addConstr( (total_generation - total_excess) / total_load >= target, name="CFE_Target" ) # 执行优化 model.optimize() # 输出结果 if model.status == GRB.OPTIMAL: print("找到最优解") print("目标函数值:", model.objVal) print("变量解:") print(f"风电装机容量 (MW): {x1.x}") print(f"光伏装机容量 (MW): {x2.x}") # 若需查看逐时段购电/弃电量,可取消以下注释 # for t in range(500): # print(f"时段{t}购电量(MWh): {y[t].x}, 弃电量(MWh): {z[t].x}") else: print("优化失败,状态码:", model.status)
关键改进点说明
- 变量命名清晰:用
x1、x2、y[t]、z[t]替代模糊的索引命名,便于理解维护。 - 规避LinExpr索引错误:通过循环逐个构建约束,不再将LinExpr当作数组处理。
- 简化表达式构建:使用Gurobi的
quicksum替代numpy的sum,更适配Gurobi变量运算。 - 修正约束逻辑:
c2改为单个全局约束,符合CFE目标(总有效发电量/总负荷)的定义。
内容的提问来源于stack exchange,提问作者Charles
相关产品推荐
相关产品推荐

