python - 如何在 Gurobi Python 目标函数中对“if”条件进行建模?
问题描述
我有一个if
有条件的目标函数。我无法在 Gurobi Python 中实现它。
背景
有s
供应商和p
工厂。x[s][p]
是一个变量,表示从supplier-x
到的项目数plant-p
。c[s][p]
表示从供应商向中心供应一件商品的成本。
此外,每个供应商都有固定成本t[s]
。如果供应商向任何中心供货,则会产生此固定成本(此固定成本不取决于项目数量)。
我想使用像这样的目标函数来最小化成本 -
第一部分很容易建模sum(x[s, p] * spc[s, p] for s in range(num_suppliers) for p in range(num_center))
。
对于第二个学期,我该如何建模?(第二部分基本上意味着只有当供应商实际上是任何工厂的任何供应商时才添加供应商的固定成本)。
编辑
这是我现在拥有的代码。注意:这不会产生最小值 -
from gurobipy import *
supplier_capacity = [
5, 10
]
plant_demand = [
2, 4
]
num_suppliers = len(supplier_capacity)
num_plants = len(plant_demand)
t = [
100, 1
]
c = {
(0, 0): 1,
(0, 1): 4,
(1, 0): 4,
(1, 1): 2
}
x = {} # flow between each supplier to plant
m = Model()
xl = [(s, p) for s in range(num_suppliers) for p in range(num_plants)]
x = m.addVars(xl, vtype=GRB.INTEGER, lb=0, name='flow')
for s in range(num_suppliers):
m.addConstr(x.sum(s, '*') <= supplier_capacity[s])
for p in range(num_plants):
m.addConstr(x.sum('*', p) >= plant_demand[p])
m.setObjective(
(
sum(x[s, p] * c[s, p] for s in range(num_suppliers) for p in range(num_plants)) +
sum(t[s] for s in range(num_suppliers) if x.sum(s, '*') >= 0)
), GRB.MINIMIZE
)
m.update()
m.optimize()
if m.status == GRB.Status.OPTIMAL:
print('==== RESULTS ====')
print('Min Cost: {}'.format(m.ObjVal))
for v in m.getVars():
print('{} = {}'.format(v.VarName, v.X))
else:
print('Infeasible model')
解决方案
由于 x 是一个决策变量,因此您不能将它与标准 python if 语句一起使用。相反,您需要添加一个二进制指标变量 (y_s),只要任何装运变量 (x_sp) 非零,该变量就会被强制为值 1。然后将指标变量添加到系数为 t_s 的目标函数中。
y = [m.addVar(vtype='B', obj=t_s) for t_s in t]
for s, y_s in enumerate(y):
for p in range(num_plants):
big_M = min(supplier_capacity[s], plant_demand[p])
m.addConstr(big_M * y_s >= x[(s, p)]
如果将任何东西运送到任何工厂,这些限制就会迫使每个供应商“开工”。big_M 值是供应商可以运送到工厂的数量的上限。由于 y 是一个二进制变量,因此如果任何相关的 x 变量不为零,则它必须为 1。相反,如果 y 为 1,则任何或所有相关的 x 变量将有效地不受约束。由于 y 变量的系数都是正数,并且您正在最小化,因此如果所有 x 都为零,则不需要 y 为 0 的显式约束。
推荐阅读
- php - 关于“打开流失败:HTTP请求失败!HTTP/1.0 403 Forbidden”
- html - 带有Firefox的Ajax越野车吧
- javascript - HTML/CSS/JavaScript 幻灯片中的 setTimeout
- c++ - 如何在未排序的数组中找到元素 x 的最大出现次数,使得 (x>=Y || x<=Z) 在具有最少探测器数量的子数组中?
- c# - 如何使用 C# 从 Telegram bot 下载 Windows 服务器上的大文件(大于 20MB)
- deep-learning - pytorch 中的 Wasserstein GAN 实现。如何实现损失?
- javascript - Mongoose createConnection 在 Jest 中时返回 undefined
- oracle - 连接表以汇总订购项目的数量
- macos - Cocoa:如何一次关闭多个模态窗口/模态视图控制器?
- java - 像这样 Java“实例过滤”[RabbitMQ] 处理消息的最 Pythonic 方式是什么