如何在 Gurobi 中正确实现成本最小化 objective 功能?

How to implement a cost minimization objective function correctly in Gurobi?

给定运输成本,从三个配送中心到十个独立商店的超市的每单位交付。

注意:请查看我的代码的 #data 部分,以查看我不允许以照片形式 post 的数据。另请注意,虽然我的成本是一个包含 30 个条目的向量。每个配送中心每次只能存取10个成本。所以 DC1 成本 = 条目 1-10,DC2 成本 = 条目 11-20 等..


我想根据 10 家商店的需求(以送货为单位)将运输成本降至最低。

这可以通过检查来完成。最低成本为 150313 美元。使用 Python 和 Gurobi 实施解决方案并产生相同结果的问题。


到目前为止,我尝试过的是 Gurobi 问题的一个有点草率的模型。我不确定如何正确索引和迭代生成结果所需的集合。

这是我的主要问题:我定义的用于最小化运输成本的 objective 函数不正确,因为我生成了一个非答案。

虽然代码"runs"。如果我改为最大化,我只会遇到一个无限的问题。所以我觉得我绝对没有调用正确的 data/iterations through sets in play.

到目前为止我的解决方案很小,所以我觉得我可以将其格式化为问题并一路评论。

from gurobipy import *

#Sets
Distro = ["DC0","DC1","DC2"]
Stores = ["S0", "S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9"]
D = range(len(Distro))
S = range(len(Stores))

在这里我定义了我的配送中心集和商店集。我不确定在哪里或如何准确定义 DS 迭代变量以获得正确答案。


#Data
Demand  = [10,16,11,8,8,18,11,20,13,12]
Costs = [1992,2666,977,1761,2933,1387,2307,1814,706,1162,
           2471,2023,3096,2103,712,2304,1440,2180,2925,2432,
           1642,2058,1533,1102,1970,908,1372,1317,1341,776]

只是我相关数据的一部分。考虑到每个配送中心只能访问 10 个成本而不是 30 个,我不确定我的成本数据是否应该是 3 个独立的集合。或者如果有办法将我的成本保持为一组但确保每个中心只能访问成本与自身相关我不知道。

m = Model("WonderMarket")
#Variables
X = {}
for d in D:
    for s in S:
        X[d,s] = m.addVar()

正在声明我的 objective 变量。同样,我在这一点上盲目地迭代以产生有效的东西。我以前从未编程过。但我正在学习并尽可能多地思考这个问题。

#set objective
m.setObjective(quicksum(Costs[s] * X[d, s] * Demand[s] for d in D for s in S), GRB.MINIMIZE)

我的 objective 函数试图根据商店的需求乘以从中心到商店的每次送货成本,然后使其成为可能的最小值。我还没有非零约束。我最终会需要一个吗?!但现在我有更大的鱼要炸。

m.optimize()

我生成了一个 0 行、30 列和 0 个非零条目模型,该模型给出了 0 的解。我需要设置我的程序,以便获得可以轻松手动计算的值。我认为问题是我对变量的一般声明以及对迭代和一般 "what goes where" 问题的了解不足。多多思考只是为了学习练习!

感谢所有通读的人。感谢您提前提供任何提示或帮助。

您的 objective 为 0,因为您没有定义任何约束。默认情况下,所有变量的下限均为 0,因此最小化无约束问题会将所有变量置于此下限。

几点评论:

除非您需要配送中心和商店的名称,否则您可以按如下方式定义它们:

D = 3
S = 10
Distro = range(D)
Stores = range(S)

您可以将成本定义为二维数组,例如

Costs = [[1992,2666,977,1761,2933,1387,2307,1814,706,1162],
       [2471,2023,3096,2103,712,2304,1440,2180,2925,2432],
       [1642,2058,1533,1102,1970,908,1372,1317,1341,776]]

然后从配送中心d到商店s的运输成本存储在Costs[d][s]

您可以一次添加所有变量,我假设您希望它们是二进制的:

X = m.addVars(D, S, vtype=GRB.BINARY)

(如果您需要使用名称,则使用 DistroStores 而不是 DS)。

您对 objective 函数的定义将变为:

m.setObjective(quicksum(Costs[d][s] * X[d, s] * Demand[s] for d in Distro for s in Stores), GRB.MINIMIZE)

(这都是假设每个商店只能从一个配送中心发货,但由于您的配送中心没有最大容量,这似乎是一个合理的假设。)

您需要限制以确保商店的需求得到实际满足。为此,确保每个商店都从一个配送中心发货就足够了,即对于每个 s 一个 X[d, s] 是 1.

m.addConstrs(quicksum(X[d, s] for d in Distro) == 1 for s in Stores)

当我优化这个时,我确实得到了一个最优解,值为 150313。