运筹学读书笔记---Benders Decomposition

1、前言

最近在读这本厚厚的运筹学书籍,发现这本书写的真的好。大规模优化方法系列,有个叫benders分解的算法,之前只是听过名字,不懂具体原理。仔细啃了一下,还是很有意思的。

2、分解策略

                              min (cx+fy)

      (BP)\quad s.t.\quad Ax+Fy\geq b\\ ""\qquad \qquad \qquad x\geq 0,y\geq 0 \quad y\ is\ integer

如果y值固定,上述问题就变成一个线性规划问题。因此,在第l次迭代时。选取部分整数决策变量y(l)并固定相应的值,从而将整数规划转化为只包含连续决策变量的问题,如下所示:

                      min (cx+f y(l))

(BP(l))\quad s.t.\quad Ax\geq b-Fy(l)\\ ""\qquad \qquad \qquad x\geq 0

由BP(l)的对偶问题得到第l次迭代的Benders的子问题。

                     max\ v(b-Fy(l)) + fy(l)

(BD(l))\quad s.t.\quad vA\leq c\\ ""\qquad \qquad \quad\qquad v\geq 0

当求解对偶子问题(BD(l))时,可能会出现两种情形:子问题的最优解对应一个极点v(i)或者子问题无界,最优解对应一个极方向v(j)。因此,在benders主问题求解变量y的整数规划模型如下形式:

                        min z

(BM)\quad s.t.\quad z\geq fy+v(i)(b-Fy) ,i\in\ P\\ ""\qquad \qquad \qquad \quad 0\geq v(j)(b-Fy),j\in\ D\\ ""\qquad \qquad \qquad \quad y\geq 0, y\ is\ integer

当考虑所有的极点和极方向时,BM问题一定可以找到最优的y,但此时的模型可能包含指数级别的数量的极点和大量的极方向。和列生成算法类似,限制主问题只考虑当前迭代时生成的极点和极方向,每次迭代会逐步添加新的极点和极方向。

                     min z

(BM(l))\quad s.t.\quad z\geq fy+v(i)(b-Fy) ,i\in\ P(l)\\ ""\qquad \qquad \qquad \quad 0\geq v(j)(b-Fy),j\in\ D(l)\\ ""\qquad \qquad \qquad \quad y\geq 0, y\ is\ integer

3、最优性原理

如果第l次迭代(BD(l))模型的值小于等于上一次迭代得到的限制主问题最优目标函数值小,即v(BD(l))\leq v(BM(l-1))

因为(BD(l))的约束比(BM)的约束少,所以(BD(l))(BM)的上界,即v(BD(l))\geq v(BM)。随着迭代过程BM(l)中约束条件越来越多,v(BM(l))的值应该是增加的,所以v(BM(l-1))v(BM)的下界,即v(BM(l-1))\leq v(BM)。所以每次迭代中会有v(BD(l))\geq v(BM)\geq v(BM(l-1)),一旦v(BD(l))\le v(BM(l-1)),迭代达到终止条件。

4、整体流程

第0步:初始化。l=1

第1步:Benders子问题(BD(l-1))求解。若目标函数值有界限,得到极点,进入第2步。若目标函数无界,得到极方向,进入第3步。

第2步:算法终止判断。如果停止,得到y(l),进而求解x(l)

第3步:限制主问题更新,将新得到的极点和极方向以约束条件的形式添加到(BM(l))zhong。

第4步:主问题求解。求解BM(l)得到y(l)和目标函数z。l=l+1,返回第1步。

5、基于Gurobi模型构建

import gurobipy as gp
from gurobipy import GRB
import numpy as np

class Benders_Example(object):
    def __init__(self,i_num,j_num):
        self.j_num = j_num
        self.i_num = i_num
        self.f = [400, 250, 300]
        self.d = [75, 90, 81, 26, 57]
        self.cost = [[4, 7, 3, 12, 15],
                     [13, 11, 17, 9, 19],
                     [8, 12, 10, 7, 5]]

    def build_model(self):
        model = gp.Model("Benders")
        x_ij = model.addVars(self.i_num,self.j_num,vtype=GRB.CONTINUOUS,obj=self.cost,lb=0,ub=GRB.INFINITY,name="x")
        y_i = model.addVars(self.i_num,vtype=GRB.BINARY,obj=self.f,name="y")
        model.modelSense=GRB.MINIMIZE

        #add constr
        model.addConstrs((x_ij.sum(i,"*") <= y_i[i] * sum(self.d) for i in range(self.i_num)),name='c1')

        model.addConstrs((x_ij.sum("*",j) == self.d[j] for j in range(self.j_num)),name='c2')

        model.write("benders.lp")
        model.optimize()
        print("model obj = ",model.objVal)
        for i in range(self.i_num):
            print("y(%d)=%lf" % (i,y_i[i].x))
            for j in range(self.j_num):
                print(x_ij[i,j].x)

6、基于Gurobi实现Benders算法

只是粗略的实现,直接建模型求解和用benders算法求解。代码框架还需要优化,后边有时间再打磨。

github:https://github.com/IELBHJY/OperationsResearch/tree/master/Benders

 

 

 

 

参考资料:本文资料是来自<<Optimization in Operations Research 2nd Edition>>

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值