繁体   English   中英

混合整数编程-仓库位置(Python + GLPK)

[英]Mixed Integer Programming - Warehouse Location (Python + GLPK)

我在优化方面相对较新,并且正在尝试优化有关仓库位置的问题(来自2年前Coursera的一次课程)。 问题是,它已经超过6个小时,并且仍在具有100个仓库和1000个客户的实例上运行。

问题如下。 我有一套可以打开或不打开的仓库。 打开它们中的每一个的成本为s_w。 而且,它们都具有最大容量cap_w。 另一方面,有一堆客户,所有客户都必须连接到一个(只有一个)开放式仓库。 他们每个人都有需求d_c,对于每个客户,每个仓库都有运输成本t_wc。 我要的是使总成本最小化。

因此,我有一个数组的大小等于称为x的仓库总数。 每个x [w]是整数{0,1},定义仓库w是否开放。 我还有一个0和1的矩阵,定义哪个仓库交付每个客户。 因此,存在与客户一样多的行,而与仓库一样多的列。 该矩阵称为y。 如果商品w交付客户c,则y [c] [w]为1,否则为0。

到现在为止还挺好。 推测这是一个MIP问题。 为了进行编码,我使用PuPL lib( https://pythonhosted.org/PuLP/pulp.html )和GLPK在Python上完成它来解决它。

现在,这是我的模型:

#!/usr/bin/python
# -*- coding: utf-8 -*-

from pulp import *

def solveIt(inputData):

# parse the input
lines = inputData.split('\n')

parts = lines[0].split()
warehouseCount = int(parts[0])
customerCount = int(parts[1])

warehouses = []
for i in range(1, warehouseCount+1):
    line = lines[i]
    parts = line.split()
    warehouses.append((int(parts[0]), float(parts[1])))

customerDemands = []
customerCosts = []

lineIndex = warehouseCount+1
for i in range(0, customerCount):
    customerDemand = int(lines[lineIndex+2*i])
    customerCost = map(float, lines[lineIndex+2*i+1].split())
    customerDemands.append(customerDemand)
    customerCosts.append(customerCost)



x = [LpVariable("x"+str(w),0,1,cat='Integer') for w in range(0,warehouseCount)]
y = [[LpVariable("y"+str(c)+","+str(w),0,1,cat='Integer') for w in range(0,warehouseCount)] for c in range(0,customerCount)]

prob = LpProblem("Warehouse Location",LpMinimize)

#Constraints
# y_cw <= x_w makes sure that no client is delivered by a closed warehouse
for w in range(0,warehouseCount):
    for c in range(0,customerCount):
        prob += y[c][w] <= x[w]

#A client is served by exactly one warehouse
for c in range(0,customerCount):
    affineExpression = []
    for w in range(0,warehouseCount):
        affineExpression.append((y[c][w],1))
    prob += LpAffineExpression(affineExpression) == 1

#For each warehouse, the sum of demand of all the clients it serves is lower than its capacity
for w in range(0,warehouseCount):
    affineExpression = []
    for c in range(0,customerCount):
        affineExpression.append((y[c][w],customerDemands[c]))
    prob += LpAffineExpression(affineExpression) <= warehouses[w][0]

#Objective
#The sum of all the warehouses opening plus the transportation costs has to be minimal
affineExpression = []
for w in range(0,warehouseCount):
    affineExpression.append((x[w],warehouses[w][1]))
    for c in range(0,customerCount):
        affineExpression.append((y[c][w],customerCosts[c][w]))

prob += LpAffineExpression(affineExpression)

print "#######################START SOLVING"
status = prob.solve(GLPK(mip=1,msg = 1))
print LpStatus[status]
for w in range(0,warehouseCount):
    print value(x[w])

solution = []
for c in range(0,customerCount):
    string = ""
    whichOne = -1
    for w in range(0,warehouseCount):
        string += str(value(y[c][w])) + " "
        if value(y[c][w]) == 1:
            whichOne = w
            solution.append(w)
    print string+ "   "+str(whichOne)


# calculate the cost of the solution
obj = sum([warehouses[x][1]*x[w] for x in range(0,warehouseCount)])
for c in range(0, customerCount):
    obj += customerCosts[c][solution[c]]

# prepare the solution in the specified output format
outputData = str(obj) + ' ' + str(0) + '\n'
outputData += ' '.join(map(str, solution))

return outputData

我知道我构建矩阵的方法不是最佳的,但实际上并不需要花费太长时间。 它开始解决,在某个时候我到达了GLPK说的一点:

OPTIMAL SOLUTION FOUND
Integer optimization begins...

我相信这意味着它解决了LP,现在使它变成整数了……但是它大约需要6个小时左右,并且一直在进步,现在还在,但是还没有结束。 在较小的情况下,它可以正常工作。

我的问题是,我的模型有问题吗? 我忘记了一些优化? 还是这个问题那么大?

另外,关于计算机,它的性能相当差:仅Intel Atom和1GB RAM ...

谢谢您的帮助!

编辑:这是日期: https : //github.com/ddeunagomez/DiscreteOptimization/blob/master/04_warehouse_location/warehouse/data/wl_100_1格式为:

NumberOfWarehouses NumberOfCustomers
CapacityWarehouse1 OpeningCostWarehouse1
CapacityWarehouse2 OpeningCostWarehouse2
.....
CapacityWarehouseN OpeningCostWarehouseN
DemandCustomer1
TransportCostW1_C1 TransportCostW2_C1 ....... TransportCostWN_C1
DemandCustomer2
TransportCostW1_C2 TransportCostW2_C2 ....... TransportCostWN_C2
.....
DemandCustomerN
TransportCostW1_CM TransportCostW2_CM ....... TransportCostWN_CM

这在事物方案中并不是一个真正的大问题-有专门的代码可以解决比此更大的仓库位置实例,而且像CPLEX这样的优质现货解决程序也可以轻松解决它。 我不知道GLPK / PuPL的效率如何,但是很可能使用简单的LP /分支绑定(它们正在做的事情)花费的时间太长。

您可以尝试做的一件事是允许y变量连续(0 <= y <= 1)而不是二进制。 这很可能会加快运行时间,因为求解程序无需在其上进行分支。 实际解释是,某些客户可以将他们的需求分配到多个仓库之间。 实际上,在大多数解决方案中,它们中可能很少。 如果容量足够大以至于无法绑定,那么任何需求都不会分裂,即使允许y连续,您也将始终获得二进制解。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM