【MIP】Benders Decomposition & MIP

Benders decomposition

Consider the following general LP, where x x x is a real valued variable and y y y is a variable whose domain is defined by polyhedron Y \mathbb{Y} Y. y y y is a complicating variable:
min ⁡ c T x + f T y s . t . A x + B y ≥ b x ≥ 0 , y ∈ Y \begin{aligned} &\min & c^Tx+f^Ty\\ &s.t. & Ax+By\geq b\\ &&x\geq 0, y\in \mathbb{Y} \end{aligned} mins.t.cTx+fTyAx+Bybx0,yY
The Benders decomposition method partitions the problem in two: a master problem containing the y y y variables and a sub-problem containing the x x x variables. With q ( y ) q(y) q(y) as the incumbent value for the x x x part, thus, we can define a LP using only variable y y y:
min ⁡ f T y + q ( y ) s . t . y ∈ Y \begin{aligned} &\min &f^Ty+q(y)\\ &s.t.&y\in\mathbb{Y} \end{aligned} mins.t.fTy+q(y)yY
Then, we have the sub-problem in terms of x x x. Note that if the sub-problem is unbounded, the original problem is unbounded as well. Under the assumption of bounded, we calculate the value of q ( y ) q(y) q(y) by solving the following LP:
min ⁡ c T x s . t . A x ≥ b − B y x ≥ 0 (Sub) \begin{aligned} &\min &c^Tx\\ &s.t. & Ax\geq b-By\\ &&x\geq 0 \end{aligned}\tag{Sub} mins.t.cTxAxbByx0(Sub)
Considering the dual variable, α \alpha α associated with the sub-problem:
max ⁡ α T ( b − B y ) s . t . A T α ≤ c α ≥ 0 (Dual) \begin{aligned} &\max &\alpha^T(b-By)\\ &s.t.& A^T\alpha\leq c\\ &&\alpha\geq 0 \end{aligned}\tag{Dual} maxs.t.αT(bBy)ATαcα0(Dual)
When the solution space is not empty, we can enumerate all extreme rays ρ i , i ∈ [ 1 , I ] \rho_i, i\in[1, I] ρi,i[1,I] and extreme points π j , j ∈ [ 1 , J ] \pi_j, j\in[1, J] πj,j[1,J] of the feasible region. Given a solution vector y ∗ y^* y, we can solve the dual problem by checking if we can find:

  • ρ i \rho_i ρi such that: ρ i T ( b − B y ∗ ) > 0 \rho_i^T(b-By^*)>0 ρiT(bBy)>0, in which case the dual is unbounded;
  • π i \pi_i πi maximizing: π j T ( b − B y ∗ ) \pi_j^T(b-By^*) πjT(bBy), in which case both the primal and dual have infinite solutions.

Rewriting the sub-problem in terms of a single variable q q q. We have the master problem in terms of y y y and q q q only, and the constraints are called cuts in Benders:
min ⁡ f T y + q s . t . ρ i T ( b − B y ) ≤ 0 ∀ i ∈ [ 1 , I ] ( 1 ) π j T ( b − B y ) ≤ q ∀ j ∈ [ 1 , J ] ( 2 ) q ∈ R , y ∈ Y \begin{aligned} &\min & f^Ty+q\\ &s.t.& \rho_i^T(b-By)\leq 0 & \forall i\in [1, I] & (1)\\ &&\pi_j^T(b-By)\leq q & \forall j \in [1, J] & (2)\\ &&q\in\mathbb{R}, y\in \mathbb{Y} \end{aligned} mins.t.fTy+qρiT(bBy)0πjT(bBy)qqR,yYi[1,I]j[1,J](1)(2)
Since there is an exponential number of extreme points and extreme rays, and because their enumeration is N P NP NP-hard, Benders starts without any cut and solves a relaxed master problem which gives a candidate solution ( y ∗ , q ∗ ) (y^*, q^*) (y,q). Using this solution, it solves the sub-problem to obtain a value q ( y ∗ ) q(y^*) q(y). If q ∗ = q ( y ∗ ) q^*=q(y^*) q=q(y) then the candidate solution is optimal for the original problem. Otherwise we have two cases:

  • the dual is unbounded, then we select an extreme ray to generate a constraint of type ( 4 ) (4) (4), which is called a feasibility cut.
  • we have q ( y ∗ ) > q ∗ q(y^*)>q^* q(y)>q, then we select and exteren point to add a constraint of type ( 5 ) (5) (5), which is called an optimality cut as it gives a lower bound for the incumbent.

The algorithm then repeats the previous steps: it solves the master problem, now with an additional constraint, and checks wheter the solution is optimal or if a new cut is needed.

Xpress demo

Problem:
min ⁡ c 1 ∗ x + c 2 ∗ y s . t . A 1 ∗ x + A 2 ∗ y ≤ b \begin{aligned} &\min & c_1*x+c_2*y\\ &s.t.&A_1*x+A_2*y\leq b \end{aligned} mins.t.c1x+c2yA1x+A2yb
x x x binary, n 1 n_1 n1-dimensional vector
y ≥ 0 y\geq 0 y0 continuous, n 2 n_2 n2 dimensional vector

import xpress as xp

def demo_1():
    x1 = xp.var(vartype=xp.integer, name='x1', lb=-10, ub=10)
    x2 = xp.var(name='x2')
    p = xp.problem(x1, x2,       # variables of the problem 
                   x1**2+2*x2,   # objective function
                   x1+3*x2>=4,   # constraints
                   name='myexample')

    p.solve()
    print('solution: {0}={1}; {2}={3}'.format(x1.name, p.getSolution(x1), x2.name, p.getSolution(x2)))


import sys
def demo_2():
    c1 = [1, 6, 5, 7]       # n1 * 1
    c2 = [9, 3, 0, 2, 3]    # n2 * 1
    b = [-3, -4, 1, 4, 5]   # m * 1
    A1 = [[0, -2, 3, 2],
          [-5, 0, -3, 1],
          [1, 0, 4, -2],
          [0, -3, 4, -1],
          [-5, -4, 3, 0]]

    A2 = [[3, 4, 2, 0, -5],
          [0, 2, 3, -2, 1],
          [2, 0, 1, -3, -5],
          [-5, 3, -2, -3, 0],
          [-2, 3, -1, 2, -4]]

    m, n1, n2 = len(b), len(c1), len(c2)

    ## Define variables
    p = xp.problem()
    x = [xp.var(vartype=xp.binary) for _ in range(n1)]
    y = [xp.var() for _ in range(n2)] # positive real variable
    p.addVariable(x, y)

    ## Define constraints
    cons = [xp.Sum(A1[i][j]*x[j] for j in range(n1)) + xp.Sum(A2[i][j]*y[j] for j in range(n2))<=b[i] for i in range(m)]
    p.addConstraint(cons)

    ## Define objective
    p.setObjective(xp.Sum(c1[j]*x[j] for j in range(n1))+xp.Sum(c2[j]*y[j] for j in range(n2)),sense=xp.minimize)

    # solve & retrieve solution
    p.solve()
    if p.getProbStatus() != xp.mip_optimal:
        raise RuntimeError('Problem could not be solved to MIP optimality')
    
    y_opt = p.getSolution(y)
    print('The optimal value is: ', p.getObjVal())
    print('The first stage variables are: ', p.getSolution(x))
    print('The second stage variables are: ', y_opt)
    print('The objective of the second stage is:', sum(c2[j]*y_opt[j] for j in range(n2)))
def main():
    # demo_1()
    demo_2()


if __name__ == '__main__':
    main()

Reference

Benders blog
Gurobi列生成和Benders分解
Sparse portfolio selection with uncertain probability distribution

猜你喜欢

转载自blog.csdn.net/qq_18822147/article/details/116327360