Python Gurobi求解二元决策变量乘积型非线性约束问题
问题解答
可以在Python中调用Gurobi求解这类含二元决策变量乘积的约束,你原代码运行异常有两个核心原因:
- 语法错误:
y_kc[k[, c]多写了多余的左方括号,会直接触发语法报错 - 非线性约束问题:直接写两个二元变量的乘积会被Gurobi识别为二次约束,求解效率低,且容易出现误判不可行的情况,建议通过大M法线性化处理后再添加约束
约束逻辑说明
你需要实现的逻辑为:当门店i归属总部k(x_ik[i,k] = 1)、且总部k位于城市街区c(y_kc[k,c] =1)时,门店i到街区c的距离d_ic.at[i,c]必须小于等于300。
正确实现方式
方式1:直接使用二次约束(不推荐)
仅修正语法错误即可运行,但求解效率远低于线性化写法:
for k in K: for c in C: for i in I: modelo.addConstr(x_ik[i, k] * y_kc[k, c] * d_ic.at[i, c] <= 300, name=f"c7_{i}_{k}_{c}")
方式2:大M法线性化实现(推荐)
无需引入额外辅助变量,求解效率更高,其中M取所有d_ic的最大值加1即可:
# 计算大M取值 M = d_ic.max().max() + 1 for k in K: for c in C: for i in I: modelo.addConstr( d_ic.at[i, c] <= 300 + M * (1 - x_ik[i, k]) + M * (1 - y_kc[k, c]), name=f"c7_{i}_{k}_{c}" )
优化写法(适用已约束每个总部仅选址一个街区的场景)
如果你已经为y_kc添加了sum(y_kc[k,c] for c in C) == 1的约束(每个总部仅位于一个街区),可以简化为二重循环,进一步提升性能:
M = d_ic.max().max() + 1 for i in I: for k in K: modelo.addConstr( sum(d_ic.at[i, c] * y_kc[k, c] for c in C) <= 300 + (1 - x_ik[i, k]) * M, name=f"c7_{i}_{k}" )
内容的提问来源于stack exchange,提问作者Ana
相关产品推荐
相关产品推荐

