如何通过Gurobi变量对字典进行索引——线性规划问题
Gurobi中用决策变量作为字典索引添加约束的解决方法
你遇到的问题核心是:Gurobi的整数决策变量x不是普通Python整数,无法直接作为字典键取值。需要把这个非线性的索引操作转化为Gurobi支持的线性约束,下面提供两种实用方案:
方案一:直接限制x的合法取值集合
先筛选出字典中值满足>=2.1的键,然后通过约束限制x只能取这些值:
import gurobipy as gp from gurobipy import GRB model = gp.Model() dic = {1: 0.5, 2: 1.45, 3: 3, 4: 0.3, 5: 2, 6: 2.8, 7: 1} x = model.addVar(vtype=GRB.INTEGER, lb=1, ub=7) # 筛选符合条件的索引 valid_indices = [i for i, val in dic.items() if val >= 2.1] # 方法1:排除所有不合法的索引(简单直观) invalid_indices = [i for i in dic.keys() if i not in valid_indices] for i in invalid_indices: model.addConstr(x != i) # 方法2:用SOS1约束(适合合法取值较多的场景,求解效率更高) # model.addSOS(GRB.SOS_TYPE1, x, valid_indices) # 方法3:用二进制变量组合(适合后续需要扩展约束的场景) # y = model.addVars(valid_indices, vtype=GRB.BINARY) # model.addConstr(gp.quicksum(y[i] for i in valid_indices) == 1) # model.addConstr(x == gp.quicksum(i * y[i] for i in valid_indices))
方案二:大M约束实现通用逻辑
如果需要将dic[x]作为线性项参与更复杂的约束(比如和其他变量做运算),可以用二进制变量+大M约束将索引操作转化为线性组合:
import gurobipy as gp from gurobipy import GRB model = gp.Model() dic = {1: 0.5, 2: 1.45, 3: 3, 4: 0.3, 5: 2, 6: 2.8, 7: 1} x = model.addVar(vtype=GRB.INTEGER, lb=1, ub=7) # 为每个字典键创建二进制变量,y[i]=1表示x=i y = model.addVars(dic.keys(), vtype=GRB.BINARY) # 约束1:x只能对应唯一的二进制变量为1 model.addConstr(gp.quicksum(y[i] for i in dic.keys()) == 1) # 约束2:将x与二进制变量关联 model.addConstr(x == gp.quicksum(i * y[i] for i in dic.keys())) # 将dic[x]转化为线性组合sum(dic[i]*y[i]),添加目标约束 model.addConstr(gp.quicksum(dic[i] * y[i] for i in dic.keys()) >= 2.1)
方案选择建议
- 若只是简单限制x的取值范围,优先用方案一,代码更简洁;
- 若需要将
dic[x]作为线性项参与其他约束计算,选择方案二,扩展性更强。
内容的提问来源于stack exchange,提问作者bobby
相关产品推荐
相关产品推荐

