首页 > 解决方案 > 如何在 Gurobi Python 目标函数中对“if”条件进行建模?

问题描述

我有一个if有条件的目标函数。我无法在 Gurobi Python 中实现它。

背景

s供应商和p工厂。x[s][p]是一个变量,表示从supplier-x到的项目数plant-pc[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')

标签: pythonmathematical-optimizationlinear-programminggurobi

解决方案


由于 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 的显式约束。


推荐阅读