我有一个目标函数,其中包含一个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')
答案 0 :(得分:2)
由于x是决策变量,因此您可以not与标准python if语句一起使用它。相反,您需要添加一个二进制indicator变量(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。
答案 1 :(得分:0)
您是否正在寻找类似的东西?在这里,您只需要看起来像这样的数组的第一个和最后一个元素。因此,只有第一行和最后一行的每一列的总和> = 1。
array([[ 0, 1, 2, 3],
[ 4, -5, -6, -7],
[ 8, 9, 10, 11]])
num_suppliers, num_center = 3, 4
t = [1,2,3]
x = {
(0, 0): 0,
(0, 1): 1,
(0, 2): 2,
(0, 3): 3,
(1, 0): 4,
(1, 1): -5,
(1, 2): -6,
(1, 3): -7,
(2, 0): 8,
(2, 1): 9,
(2, 2): 10,
(2, 3): 11
}
sum(t[s] for s in range(num_suppliers) if sum(x[s, p] for p in range(num_center)) >= 1)
输出:4