最近忙,但是今天不更新不行啦啦啦!!!
参考文献:はじめての列生成法
装箱问题(bin packing problem)
我们可以这样定义BPP问题。
- 输入 bin的容量
,要装入bin的item的集合,各个item的大小
- 输出 使用最少的bin的数量,把item装到bin里
- 约束 向bin里装的item的大小的和不能超过bin的容量
- 目标 被使用的bin的数量最小化
让我们考虑一个小规模的问题例子。 下面会用到。
作为整数规划问题建模
首先,定义bin的集合
其次,定义以下0-1变量
:如果把
装到
的时候为1,否则为0
:使用
的时候为1.否则为0
下面,我们给出整数规划模型
用
和上面给出小问题例子可以求得最优解为3。
列生成思想
我们来考虑假如我们提前把可能的pattern列举出来,然后选择哪个pattern会不会更好呢?
我们把pattern的集合设为
。给定一个矩阵
- 如果item
被pattern包含的时候为1
- 否则,
为0
那么我们可以用经典模型集合覆盖问题重新建模,如下
我们称
为主问题。
刚才的小问题的例子的可能的pattern,如下(知乎latex表不能用可能数学上不太严谨)
那么带入问题
我们可以得到
但是我们还有一个约束就是不要超过bin的容量。下面我们给出模型
这里
是
约束条件的对偶变量。另外
的目标函数为称为被覆费用。这是一个经典的
背包问题。
下面我们给出列生成算法的框架
- step A 生成可行解,解主问题的线性松弛规划问题,得到对偶变量
- step B 得到的主问题的线性松弛规划问题的对偶变量作为参数,解子问题
- step B-1 如果得到的子问题的最优值大于0,终止
- step B-2 否则,子问题得到的最优解作为系数加入到主问题
- step C 解主问题
代码
from gurobipy import *
import numpy as np
m=4
s=[1,3,6,7]
B=8
a=[]
a1=[0,0,1,0]
a2=[0,0,0,1]
a3=[0,1,0,0]
a4=[1,0,0,0]
a.append(a1)
a.append(a2)
a.append(a3)
a.append(a4)
n=len(a)
master=Model("master")
x={}
for j in range(n):
x[j]=master.addVar(vtype="B",name="x(%s)"%j)
orders={}
for i in range(m):
orders[i]=master.addConstr(
quicksum(a[j][i]*x[j] for j in range(n))>=1,"order(%s)"%i
)
master.setObjective(quicksum(x[j] for j in range(n)), GRB.MINIMIZE)
master.update()
iter = 0
dual=[]
EPS = 1.e-6
while True:
iter += 1
print("*****relaxation for master problem*****")
relax=master.relax()
relax.optimize()
pi=[c.pi for c in relax.getConstrs()]
sub=Model("sub")
y={}
for i in range(m):
y[i]=sub.addVar(vtype="B")
sub.addConstr(quicksum(y[i]*s[i] for i in range(m))<=B)
sub.setObjective(quicksum(pi[i]*y[i] for i in range(m)),GRB.MAXIMIZE)
print("***** sub problem*****")
sub.optimize()
for i in range(m):
print(y[i].x)
if sub.ObjVal <1+EPS:
break
var=[]
for i in range(m):
var.append(y[i].x)
a.append(var)
print(a)
col=Column()
for i in range(m):
col.addTerms(a[n][i],orders[i])
x[n]=master.addVar(obj=1,vtype="B",name="x(%s)"%n,column=col)
master.update()
master.write("MP" + str(iter) + ".lp")
n+=1
dual.append(pi)
print("*****integer problem*****")
master.update()
master.optimize()
print(a)
for j in range(n):
print(x[j].x)
如果有什么疑问或者建议,可以给我发邮件。➡ zhaoyou728 at outlook.com