分支限界(Branch and Bound )算法

分支定界 (branch and bound) 算法

是一种在问题的解空间树上搜索问题的解的方法。但与回溯算法不同,分支定界算法采用广度优先或最小耗费优先的方法搜索解空间树,并且,在分支定界算法中,每一个活结点只有一次机会成为扩展结点。
除少数整数规划可以用线性规划的单纯形法直接求解外,一般整数规划必需寻找新的求解方法。这里我们介绍全整数规划的分枝定界方法,它也可以用于求解混合整数规划问题和0-1规划问题。下面我们从一个例子出发来讨论它的思路和步骤。

例1 解下面的整数规划问题

![这里写图片描述](https://imgconvert.csdnimg.cn/aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTUwNTIyMTAzMDU3Mjc0?x-oss-process=image/format,png)
解: >(1)首先我们注意到问题(4.3)的可行解集为图4-2的阴影部分内的整数格子点组成的集合,暂时不考虑整数限制条件(5)。解相应的线性规划(1)~(4),即(4.3)的松弛问题:
![这里写图片描述](https://imgconvert.csdnimg.cn/aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTUwNTIyMTAzMjAyMDQy?x-oss-process=image/format,png)
用线性规划的方式得到如下的图案
![图 4-2](https://imgconvert.csdnimg.cn/aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTUwNTIyMTAzMTQ5NjI0?x-oss-process=image/format,png)
得最优解
![这里写图片描述](https://imgconvert.csdnimg.cn/aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTUwNTIyMTAzMzM2NDUz?x-oss-process=image/format,png)
由(1)和(5)可知ILP的最优解![这里写图片描述](https://imgconvert.csdnimg.cn/aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTUwNTIyMTAzNjIxMzgx?x-oss-process=image/format,png),且必为整数,从而可以断言 ![这里写图片描述](https://imgconvert.csdnimg.cn/aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTUwNTIyMTAzNjQ0MjM1?x-oss-process=image/format,png)。这一过程称为定界,即给出ILP0问题目标函数最优解z*的下界和上界。 >(2)其次我们注意到线性规划(4.4)的解$x_1=2.25,x_2=3.75$具有小数,但这两个变量在(4.3)中都必须是整数,那就是说必须把小数部分__划掉__。我们注意到,对$x_2$,最终的最优解不会在3和4之间取值,亦即必然有: >$$ \left. \begin{array}{l} max\ z = 5x_1+8x_2\\ \begin{cases} 5x_1+9x_2 \leq 45\\ x_1+x_2 \leq 6\\ x_2 \leq 3\\ x1,x2 \geq 0 \end{cases} \end{array} \right\} =ILP1 $$ >$$ \left. \begin{array}{l} max\ z = 5x_1+8x_2\\ \begin{cases} 5x_1+9x_2 \leq 45\\ x_1+x_2 \leq 6\\ x_2 \geq 4\\ x1,x2 \geq 0 \end{cases} \end{array} \right\} =ILP2 \tag{4.5} $$ > >这种表达式实际上是将$x_2$在3和4间的小数部分划掉了,把可行域分成了$x_2\leq 3$和$x_2\geq 4$ ,显然这种分法把原来线性规划的解A点**(2.25,3.75)**排除出去了。但没有排除任何整数可行解。这一过程称为**分枝**,即用两个矛盾的约束条件(4.5)分别代入原问题(4.3)形成两个子问题ILP1和ILP2。

解ILP1的松弛问题ILP1得到
( x 1 , x 2 ) = ( 3 , 3 ) , z m a x = 39 (x_1, x_2)=(3, 3), z_{max} = 39 (x1,x2)=(3,3),zmax=39
解ILP2的松弛问题ILP2得到
( x 1 , x 2 ) = ( 1.8 , 4 ) , z m a x = 41 (x_1, x_2)=(1.8, 4), z_{max} = 41 (x1,x2)=(1.8,4),zmax=41
(3)修改上下界:从LP1和LP2的解我们知道有 39 ≤ z ∗ ≤ 41 39\leq z^*\leq 41 39z41
(4)再分枝:
下面我们就是要划掉LP2的解中 x 1 x_1 x1的小数部分,增加约束 x 1 ≤ 1 x_1\leq 1 x11 x 1 ≥ 2 x_1\geq 2 x12对ILP2进一步的分枝,即
m a x   z = 5 x 1 + 8 x 2 { 5 x 1 + 9 x 2 ≤ 45 x 1 + x 2 ≤ 6 x 2 ≥ 4 x 1 ≤ 1 x 1 , x 2 ≥ 0 } = I L P 3 \left. \begin{array}{l} max\ z = 5x_1+8x_2\\ \begin{cases} 5x_1+9x_2 \leq 45\\ x_1+x_2 \leq 6\\ x_2 \geq 4\\ x_1 \leq 1\\ x1,x2 \geq 0 \end{cases} \end{array} \right\} =ILP3 max z=5x1+8x25x1+9x245x1+x26x24x11x1,x20=ILP3
m a x   z = 5 x 1 + 8 x 2 { 5 x 1 + 9 x 2 ≤ 45 x 1 + x 2 ≤ 6 x 2 ≥ 4 x 1 ≥ 2 x 1 , x 2 ≥ 0 } = I L P 4 (4.6) \left. \begin{array}{l} max\ z = 5x_1+8x_2\\ \begin{cases} 5x_1+9x_2 \leq 45\\ x_1+x_2 \leq 6\\ x_2 \geq 4\\ x_1 \geq 2\\ x1,x2 \geq 0 \end{cases} \end{array} \right\} =ILP4 \tag{4.6} max z=5x1+8x25x1+9x245x1+x26x24x12x1,x20=ILP4(4.6)

求解LP3得:
( x 1 , x 2 ) = ( 1 , 4 ) , z m a x = 40 (x_1, x_2)=(1, 4), z_{max}=40 (x1,x2)=(1,4),zmax=40
对于LP4,不难看出,无可行解。
(5)再修改界,此时我们又有 39 ≤ z ∗ ≤ 40 39\leq z^* \leq 40 39z40
(6)再分枝,继续对ILP3进行分枝,又得到
m a x   z = 5 x 1 + 8 x 2 { 5 x 1 + 9 x 2 ≤ 45 x 1 + x 2 ≤ 6 x 2 ≥ 4 x 1 ≤ 1 x 2 ≤ 4 x 1 , x 2 ≥ 0 } = I L P 5 \left. \begin{array}{l} max\ z = 5x_1+8x_2\\ \begin{cases} 5x_1+9x_2 \leq 45\\ x_1+x_2 \leq 6\\ x_2 \geq 4\\ x_1 \leq 1\\ x_2 \leq 4\\ x1,x2 \geq 0 \end{cases} \end{array} \right\} =ILP5 max z=5x1+8x25x1+9x245x1+x26x24x11x24x1,x20=ILP5
m a x   z = 5 x 1 + 8 x 2 { 5 x 1 + 9 x 2 ≤ 45 x 1 + x 2 ≤ 6 x 2 ≥ 4 x 1 ≥ 2 x 2 ≥ 5 x 1 , x 2 ≥ 0 } = I L P 6 (4.7) \left. \begin{array}{l} max\ z = 5x_1+8x_2\\ \begin{cases} 5x_1+9x_2 \leq 45\\ x_1+x_2 \leq 6\\ x_2 \geq 4\\ x_1 \geq 2\\ x_2 \geq 5\\ x1,x2 \geq 0 \end{cases} \end{array} \right\} =ILP6 \tag{4.7} max z=5x1+8x25x1+9x245x1+x26x24x12x25x1,x20=ILP6(4.7)
求解LP5得到:
( x 1 , x 2 ) = ( 1 , 4 ) , z m a x = 37 (x_1, x_2)=(1, 4),z_{max}=37 (x1,x2)=(1,4),zmax=37
求解LP6得到:
( x 1 , x 2 ) = ( 0 , 5 ) , z m a x = 40 (x_1, x_2)=(0, 5),z_{max}=40 (x1,x2)=(0,5),zmax=40
至此,所有的子问题都已探明,求解结束。寻找到上下界 39 ≤ z ∗ ≤ 40 39\leq z^*\leq 40 39z40
我们得到了ILP0(即原问题)的最优解:
z ∗ = 40 z^*=40 z=40

分枝定界法的一般步骤如下:

第一步,先不考虑原问题的整数限制,求解相应的松弛问题,若求得最优解,检查它是否符合整数约束条件;如符合整数约束条件,即转下一步。


第二步,定界。在各分枝问题中,找出目标函数值最大者作为整数规划最优值 z ∗ z^* z的上界记为 U z Uz Uz,从已符合整数条件的分枝中,找出目标函数值最大者作为下界,记为 L z Lz Lz。即 L z ≤ z ∗ ≤ U z Lz\leq z^*\leq Uz LzzUz


第三步,分枝。根据对变量重要性的了解,在最优解中选择一个不符合整数条件的变量 x i = n u m x_i=num xi=num(num不为整数)则用下列两个约束条件:
⌊ n u m ⌋ ≤ x i ≤ ⌊ n u m ⌋ + 1 \lfloor num \rfloor \leq x_i \leq \lfloor num \rfloor+1 numxinum+1

其中 ⌊ n u m ⌋ \lfloor num \rfloor num表示不超过 n u m num num的最大整数,分别加入问题形成两个子问题。


第四步,应用对目标函数估界的方法,或对某一分枝重要性的了解,确定出首先要解的某一分枝的后继问题,并解此问题。若所获得的最优解符合整数条件,则就是原问题的解,若不符合整数条件,再回到第二步,并参照第四步终止后继问题。

在上述过程中,要不断应用分枝、定界、估界来进行判断。当我们求解某子问题的松弛问题时,只要出现下列情况之一,该问题就已探明:

  1. 松弛问题没有可行解,则原问题也没有可行解;
  2. 松弛问题的最优解恰好全取整数,则该最优解也是其对应的子问题的最优解;
  3. 松弛问题的最大值小于现有的下界z,则无论其最优解是否取整数值,都将对应的子问题剪枝;

已探明的子问题就不再用分枝了,如果所有的子问题都已探明,则原整数规划的最优解就一定可以求出,或可以判定它无解。


JAVA实现分支定界代码:

Github地址

package sy2;
import sy1.*;
/*
 * 假设这里所解的整数规划问题的目标函数取的是max
 */
public class FenZhiDingJie {
    double A[][];  //原矩阵的系数矩阵
    String D[];   //原矩阵的符号矩阵
    double b[];    //原矩阵的常数矩阵
    public int count=0;
    int index=-1;
    public double C[];//目标函数的初始系数向量
    public double Uz;//目标函数值下界
    public double Lz;//目标函数值上界
    public double z;//现在的目标函数值
    public double X[];//定义最优解
    public double zX[];//定义最优解
    public double yX[];//定义最优解
    public double Z;//定义整数线性规划的最优值
    public double Ix[];//定义整数线性规划的最优解
    public double As[][];
    public double bs[];
    public String Ds[];
    public double Xs[];
    public int lc;
    int M,N;
    //初始化分支定解法
    FenZhiDingJie(double[][] a,double[] B,String[] d,double[] c){
        M=B.length;
        N=c.length;
        A=a;
        b=B;
        D=d;
        C=c;
        X=new double[N];
        zX=new double[N];
        yX=new double[N];
        Ix=new double[N];
    }
    //分支定解过程
    public void FZDJ(double[][] a,double[] B,String[] d,double[] c,double x[]){
        boolean flag1=true;
        boolean flag2=true;
        //利用两阶段法解出该整数线性规划的最优值的上界(第一次使用两阶段法)
        while(count<10){
            if(count==0){
                System.out.println("\n第 "+count+" 次迭代");
                TwoStepMethod tm=new TwoStepMethod(A,b,D,C);
                if(!tm.flag){
                    break;
                }
                X=tm.X;
                x=X;
                Lz=0;
                Uz=-tm.z;
                System.out.print("该整数线性规划问题对应的松弛线性规划问题的最优解是:x={");
                for(int i=0;i=Uz){
                flag=true;//表示该分支继续往下分不可能找到一个可行解
            }// if
            else{
                flag=false;
            }
            return flag;
    }
    //判断所给向量的元素是否全为整数如果不是返回对应第一个非整数的下标
    public int AllInteger(double X[],int index){
        boolean flag=true;
        for(int i=0;i
package sy2;

import java.util.Scanner;

import sy1.TwoStepMethod;

/*
 * 代码测试程序
 */
public class Text {
    public static void main(String args[]){
        int M=2,N=2;//M是约束条件个数,N是未知数个数
        double A[][]=new double[M][N];
        double b[]=new double[M];
        String D[]=new String[M];//原符号向量
        double C[]=new double[N];//原目标函数的系数向量
        Scanner S=new Scanner(System.in);
        for(int i=0;i

你可能感兴趣的:(数学建模,机器学习与数学模型,分支定界法,数学建模,整数规划)