[英]How can I write an IF condition for my decision variable for Mixed Integer Linear Programming (MILP) using PuLP GLPK on Python?
[英]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.