我目前正在处理一个需要改变垃圾箱包装问题的问题。我的问题不同,因为箱数是有限的。我有三个箱子,最小的箱子放入物品的成本最低,中型箱子比小箱子贵一点,第三个箱子理论上无限容量,但放置物品的成本过高。
我能够在线找到一个Python脚本,以类似的方式解决bin问题。我的问题是如何重写脚本以更接近我原来的问题?有问题的剧本使用相同的箱子。
我在底部包含了一些线来讨论我更喜欢看垃圾箱的方式。此外,有没有办法为每个bin设置单独的约束?谢谢你的帮助!
from openopt import *
N = 30 #Length of loan dataset
items = []
for i in range(N):
small_vm = {
'name': 'small%d' % i,
'cpu': 2,
'mem': 2048,
'disk': 20,
'n': 1
}
med_vm = {
'name': 'medium%d' % i,
'cpu': 4,
'mem': 4096,
'disk': 40,
'n': 1
}
large_vm = {
'name': 'large%d' % i,
'cpu': 8,
'mem': 8192,
'disk': 80,
'n': 1
}
items.append(small_vm)
items.append(med_vm)
items.append(large_vm)
bins = {
'cpu': 48*4, # 4.0 overcommit with cpu
'mem': 240000,
'disk': 2000,
}
p = BPP(items, bins, goal = 'min')
r = p.solve('glpk', iprint = 0)
print(r.xf)
print(r.values) # per each bin
print "total vms is " + str(len(items))
print "servers used is " + str(len(r.xf))
for i,s in enumerate(r.xf):
print "server " + str(i) + " has " + str(len(s)) + " vms"
##OP Interjection: Ideally my bins would look something like:
bin1 = {
'size': 10000,
'cost': 0.01*item_weight,
}
bin2 = {
'size': 20000,
'cost': 0.02*item_weight,
}
bin3 = {
'size': 100000,
'cost': 0.3*item_weight,
}
答案 0 :(得分:3)
您正在描述的具有可变箱尺寸的箱装箱问题的变体至少是np-hard。
我不知道包openopt,项目网站似乎已经失效。 Openopt似乎使用GLPK将问题解决为混合整数程序。您无法直接访问模型公式,因为BPP()是一种抽象。您可能需要修改openopt包以为各个bin添加约束。
通常很容易将变量bin大小添加为约束,扩展this formulation,您需要将index i添加到容量V,以便每个bin具有不同的容量。
我建议您查看一些维护的库来建模并解决此问题:库PuLP,CyLP和SCIP。我认为后者不能免费用于商业用途。
由于bin打包是一个非常常见的问题,我找到了PuLP库的一个例子。我认为它默认使用CoinOR Solver,你也可以使用不同的商业解决方案。
easy_install pulp
安装PuLP后,可以使用easy_install进行扩展,您可以在this example上进行扩展。 我根据你的问题修改了这个例子:
from pulp import *
items = [("a", 5), ("b", 6), ("c", 7)]
itemCount = len(items)
maxBins = 3
binCapacity = [11, 15, 10]
binCost = [10, 30, 20]
y = pulp.LpVariable.dicts('BinUsed', range(maxBins), lowBound = 0, upBound = 1, cat = pulp.LpInteger)
possible_ItemInBin = [(itemTuple[0], binNum) for itemTuple in items for binNum in range(maxBins)]
x = pulp.LpVariable.dicts('itemInBin', possible_ItemInBin, lowBound = 0, upBound = 1, cat = pulp.LpInteger)
# Model formulation
prob = LpProblem("Bin Packing Problem", LpMinimize)
# Objective
prob += lpSum([binCost[i] * y[i] for i in range(maxBins)])
# Constraints
for j in items:
prob += lpSum([x[(j[0], i)] for i in range(maxBins)]) == 1
for i in range(maxBins):
prob += lpSum([items[j][1] * x[(items[j][0], i)] for j in range(itemCount)]) <= binCapacity[i]*y[i]
prob.solve()
print("Bins used: " + str(sum(([y[i].value() for i in range(maxBins)]))))
for i in x.keys():
if x[i].value() == 1:
print("Item {} is packed in bin {}.".format(*i))
此实现具有强大的优势,即您可以完全控制模型公式,并且在openopt的情况下,您不受某些抽象层的限制,如BPP()。