曲线的生成算法实现_(FOCUS)装箱问题的列生成算法python&Gurobi 实现

本文介绍了如何利用列生成算法解决BPP问题,通过Python和Gurobi求解器实现。首先定义了BPP问题的输入、输出和约束,接着展示了一个小规模问题实例,并构建了整数规划模型。然后,提出了将问题转化为集合覆盖问题,并给出了列生成算法的步骤:A. 解线性松弛规划;B. 用对偶变量解子问题,如果子问题最优值大于0则终止,否则更新主问题;C. 解新主问题。文章末尾鼓励读者提问或提出建议。
摘要由CSDN通过智能技术生成

7c660c7c52c7d26ed9f133164a74f73c.png

最近忙,但是今天不更新不行啦啦啦!!!

参考文献:はじめての列生成法


装箱问题(bin packing problem)

我们可以这样定义BPP问题。

  1. 输入 bin的容量
    ,要装入bin的item的集合
    ,各个item
    的大小
  2. 输出 使用最少的bin的数量,把item装到bin里
  3. 约束 向bin里装的item的大小的和不能超过bin的容量
  4. 目标 被使用的bin的数量最小化

让我们考虑一个小规模的问题例子。 下面会用到。

作为整数规划问题建模

首先,定义bin的集合

其次,定义以下0-1变量

:如果把
装到
的时候为1,否则为0

:使用
的时候为1.否则为0

下面,我们给出整数规划模型

和上面给出小问题例子可以求得最优解为3。

列生成思想

我们来考虑假如我们提前把可能的pattern列举出来,然后选择哪个pattern会不会更好呢?

我们把pattern的集合设为

。给定一个矩阵
  • 如果item
    被pattern
    包含的时候
    为1
  • 否则,
    为0

那么我们可以用经典模型集合覆盖问题重新建模,如下

我们称

为主问题。

刚才的小问题的例子的可能的pattern,如下(知乎latex表不能用可能数学上不太严谨)

2091e9341744127faafc3c0098e6b1f8.png
所有的可行pattern

那么带入问题

我们可以得到

但是我们还有一个约束就是不要超过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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值