批處理作業調度_分支限界法


一、    問題描述

    給定 n 個作業的集合 j = {j1, j2, …, jn}。每一個作業 j[i] 都有兩項任務分別在兩台機器上完成。每一個作業必須先由機器1 處理,然后由機器2處理。作業 j[i] 需要機器 j 的處理時間為 t[j][i] ,其中i = 1, 2, …, n, j = 1, 2。對於一個確定的作業 調度,設F[j][i]是作業 i 在機器 j 上的完成處理的時間。所有作 業在機器2上完成處理的時間之和 f = sigma F[2][i] 稱為該作業 調度的完成時間之和。

批處理作業調度問題要求對於給定的 n 個作業,制定最佳作業調度 方案,使其完成時間和達到最小。

二、  解題思路及所選算法策略的可行性分析

   用優先隊列式分支限界法解決此問題。由於要從n個作業的所有排列中找出有最小完成時間和的作業調度,所以批處理作業調度問題的解空間樹是一顆排列樹。對於批處理作業調度問題,可以證明存在最佳作業調度使得在機器1和機器2上作業以相同次序完成(因為每個作業必須先在機器1上完成作業才能在機器2上進行作業)。

    如果對於未安排的作業,對於其中一個作業,每當該作業在機器1上完成處理后都能立即在機器2上開始處理,則機器1沒有空閑時間,達到滿工作狀態,將此情況的未安排作業在機器2上的工作時間總和記為S1,同理將機器2滿工作狀態的情況下的工作時間總和記為S2,則必有:

    所有作業機器2上完工時間和 >= 已安排作業機器2上完工時間和 + max{S1,S2}

其中當未安排作業按照在機器1、2上工作時間非遞減順序進行調度時,S1和S2同時取得極小值且和調度無關,由此可作為分支限界法中的限界函數。

偽代碼描述及復雜度分析

bbFlow(){

    對各作業在機器1和2上作旭時間排序

    do{

        if(到達葉結點){

            if(當前作業安排機器2上完成時間和 < bestc){

                更新bestc;

                更新最優解;

            }

        }else{

            For(int i=enode.已安排作業數; i<總作業數; i++){

                求得當前下屆bb;

                If(bb < bestc){

                    結點插入最小堆;

                }

            }

        }

        取下一個拓展結點;

    }while(enode!=null&&enode.s<=n)

}

 

三、  代碼實現

package 分支限界法;

public class Nodes implements Comparable {
    int s;//已安排作業數
    int sf2;//當前機器2上的完成時間和
    int bb;//當前完成時間和下界
    int[] f;//f[1]機器1上最后完成時間,f[2]機器2上最后完成時間
    int[] x;//當前作業調度
    
    public Nodes(int n){
        //最小堆結點初始化
        x=new int[n];
        for(int i=0;i<n;i++)
            x[i]=i;
        s=0;
        f=new int[3];
        f[1]=0;
        f[2]=0;
        sf2=0;
        bb=0;
    }
    
    public Nodes(Nodes e,int[] ef,int ebb,int n){
        //最小堆新結點
        x=new int[n];
        for(int i=0;i<n;i++)
            x[i]=e.x[i];
        f=ef;
        sf2=e.sf2+f[2];
        bb=ebb;
        s=e.s+1;
    }
 
    @Override
    public int compareTo(Object o) {
        int xbb=((Nodes) o).bb;
        if(bb<xbb) return -1;
        if(bb==xbb) return 0;
        return 1;
    }
}

public class BBFlow {
    public int n;//作業數
    public int bestc;//最小完成時間和
    public int [][]m;//n個作業所需的處理時間數組
    public int [][]b;//n個作業所需的處理時間排序數組
    public int[][] a;//數組m和b的對應關系數組
    public int[] bestx;//最優解
    public boolean[][] y;//工作數組
    
    public BBFlow(int n,int[][] m){
        this.n=n;
        bestc=10000;
        this.m=m;
        b=new int[n][2];
        a=new int[n][2];
        bestx=new int[n];
        y=new boolean[n][2];
    }
    public void swap(int[][] b,int i,int j,int k,int t){
        int temp=b[i][j];
        b[i][j]=b[k][t];
        b[k][t]=temp;
    }
    public void swap(int[] x,int i,int j){
        int temp=x[i];
        x[i]=x[j];
        x[j]=temp;
    }
    /**
     * 對n個作業在機器1和2上所需時間排序
     */
    public void sort(){
        int[] c=new int[n];
        for(int j=0;j<2;j++){
            for(int i=0;i<n;i++){
                b[i][j]=m[i][j];
                c[i]=i;
            }
            for(int i=0;i<n-1;i++){
                for(int k=n-1;k>i;k--){
                    if(b[k][j]<b[k-1][j]){
                        swap(b,k,j,k-1,j);
                        swap(c,k,k-1);
                    }
                }
            }
            for(int i=0;i<n;i++)
                a[c[i]][j]=i;
        }
    }
    /**
     * 計算完成時間和下界
     * @param enode
     * @param f
     * @return
     */
    public int bound(Nodes enode,int[] f){
        for(int k=0;k<n;k++){
            for(int j=0;j<2;j++){
                y[k][j]=false;
            }
        }
        for(int k=0;k<enode.s;k++){
            for(int j=0;j<2;j++){
                y[a[enode.x[k]][j]][j]=true;
            }
        }
        f[1]=enode.f[1]+m[enode.x[enode.s]][0];
        f[2]=((f[1]>enode.f[2])?f[1]:enode.f[2])+m[enode.x[enode.s]][1];
        int sf2=enode.sf2+f[2];
        int s1=0;
        int s2=0;
        int k1=n-enode.s;
        int k2=n-enode.s;
        int f3=f[2];
        //計算s1的值
        for(int j=0;j<n;j++){
            if(!y[j][0]){
                k1--;
                if(k1==n-enode.s-1)
                    f3=(f[2]>f[1]+b[j][0])?f[2]:f[1]+b[j][0];
                s1+=f[1]+k1*b[j][0];
            }
        }
        //計算s2的值
        for(int j=0;j<n;j++){
            if(!y[j][1]){
                k2--;
                s1+=b[j][1];
                s2+=f3+k2*b[j][1];
            }
        }
        //返回完成時間和下界
        return  sf2+((s1>s2)?s1:s2);
    }
    /**
     * 優先隊列式分支限界法解批處理作業調度問題
     * @param nn
     * @return
     */
    public int bbFlow(int nn){
        n=nn;
        sort();//對n個作業在機器1和2上所需時間排序
        LinkedList<Nodes> heap=new LinkedList<Nodes>();
        Nodes enode =new Nodes(n);
        //搜索排列空間樹
        do{
            if(enode.s==n){
                //葉節點
                if(enode.sf2<bestc){
                    bestc=enode.sf2;
                    for(int i=0;i<n;i++){
                        bestx[i]=enode.x[i];
                    }
                }
            }else{
                //產生當前擴展結點的兒子結點
                for(int i=enode.s;i<n;i++){
                    swap(enode.x,enode.s,i);
                    int[] f=new int[3];
                    int bb=bound(enode,f);
                    if(bb<bestc){
                        //子樹可能含有最優解
                        //結點插入最小堆
                        Nodes node=new Nodes(enode,f,bb,n);
                        heap.add(node);
                        Collections.sort(heap);
                    }
                    swap(enode.x,enode.s,i);
                }//完成結點擴展
            }
            //取下一個擴展結點
            enode=heap.poll();
        }while(enode!=null&&enode.s<=n);
        return bestc;
    }
 
    
    
    public static void main(String[] args) {
        int n=3;
        int[][] m={{2,1},{3,1},{2,3}};//m的下標從0開始
        BBFlow f=new BBFlow(n,m);
        f.bbFlow(n);
        System.out.println("最優批處理作業調度順序為:");
        for(int i=0;i<n;i++)
            System.out.print((f.bestx[i]+1)+" ");
        System.out.println();
        System.out.println("最優調度所需的最短時間為:"+f.bestc);
    }
}

/*************************
*運行結果
*最優批處理作業調度順序為:
*1 3 2 
*最優調度所需的最短時間為:18
*************************/

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM