我在优化方面相对较新,我正在尝试优化一个关于仓库位置的问题(来自Coursera的一个pas课程,2年前)。问题是,它已经运行了6个多小时,并且仍然在一个拥有100个仓库和1000个客户的实例上运行。
问题如下。我有一套仓库,我可以开也可以不开。打开每个仓库都有一个成本s_w。而且,它们都有最大容量cap_w。另一方面,有一堆客户端,所有这些客户端都必须连接到一个(且只有一个)开放的仓库。它们中的每一个都有一个需求d_c,并且对于每个客户,都有来自每个仓库t_wc的运输成本。很明显,我想要的是最小化总成本。
因此,我有一个大小等于仓库总数的数组,称为x。每个xw都是一个整数{0,1},定义仓库w是否开放。我还有一个由0和1组成的矩阵,定义了哪个仓库为每个客户提供服务。因此,有和客户一样多的行和和仓库一样多的列。该矩阵称为y。如果waregouse w提供客户c,则yc为1,否则为0。
到目前一切尚好。这被认为是MIP问题。为了对它进行编码,我在Python中使用GLPK库(https://pythonhosted.org/PuLP/pulp.html)和PuPL来解决它。
现在,这是我的模型:
#!/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和1 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发布于 2015-01-10 05:27:57
这在方案中并不是什么大问题--有专门的代码可以解决比这个大得多的仓库位置实例,而且像CPLEX这样优秀的现成解算器也可以很容易地解决这个问题。我不知道GLPK/PuPL的效率如何,但很可能是他们使用简单的LP/分支和界限(这就是他们正在做的)所花费的时间太长了。
您可以尝试的一件事是允许y变量是连续的(0 <= y <= 1)而不是二进制。这很可能会加快运行时间,因为求解器不需要对它们进行分支。物理解释是,一些客户可以将他们的需求在多个仓库中拆分。在实践中,它们中的很少可能会在大多数解决方案中被拆分。如果容量足够大到非绑定,那么所有需求都不会被拆分,即使您允许y是连续的,您也总是会得到二元解。
https://stackoverflow.com/questions/27848828
复制相似问题