【问题标题】:Memory Choke on Branch And Bound Knapsack ImplementationBranch And Bound Knapsack 实现中的内存阻塞
【发布时间】:2011-09-19 17:38:37
【问题描述】:

我基于pseudo-Java code from here 编写了分支定界背包算法的实现。不幸的是,在问题的大型实例like this 上,内存阻塞。为什么是这样?我怎样才能使这个实现更有效地使用内存?

链接上文件的输入格式如下:

 numberOfItems maxWeight
    profitOfItem1 weightOfItem1
    .
    .
    .
    profitOfItemN weightOfItemN



// http://books.google.com/books?id=DAorddWEgl0C&pg=PA233&source=gbs_toc_r&cad=4#v=onepage&q&f=true

import java.util.Comparator;
import java.util.LinkedList;
import java.util.PriorityQueue;

class ItemComparator implements Comparator {

public int compare (Object item1, Object item2){

    Item i1 = (Item)item1;
    Item i2 = (Item)item2;

    if ((i1.valueWeightQuotient)<(i2.valueWeightQuotient))
           return 1;
    if ((i2.valueWeightQuotient)<(i1.valueWeightQuotient))
           return -1;
    else { // costWeightQuotients are equal

        if ((i1.weight)<(i2.weight)){

            return 1;

        }

        if ((i2.weight)<(i1.weight)){

            return -1;

        }

    }


        return 0;

}

}

class Node
{
    int level;
    int profit;
    int weight;
        double bound;


}

class NodeComparator implements Comparator {


    public int compare(Object o1, Object o2){

        Node n1 = (Node)o1;
        Node n2 = (Node)o2;

        if ((n1.bound)<(n2.bound))
               return 1;
        if ((n2.bound)<(n1.bound))
               return -1;

        return 0;
    }


}


class Solution {

    long weight;
    long value;

}

public class BranchAndBound {

static Solution branchAndBound2(LinkedList<Item> items, double W) {

    double timeStart = System.currentTimeMillis();

    int n = items.size();

    int [] p = new int [n];
    int [] w = new int [n];

     for (int i=0; i<n;i++){

        p [i]= (int)items.get(i).value;
        w [i]= (int)items.get(i).weight;

    }

    Node u;
    Node v = new Node(); // tree root

    int maxProfit=0;
    int usedWeight=0;

    NodeComparator nc = new NodeComparator();
    PriorityQueue<Node> PQ = new PriorityQueue<Node>(n,nc);

    v.level=-1;
    v.profit=0;
    v.weight=0; // v initialized to -1, dummy root
    v.bound = bound(v,W, n, w, p);
    PQ.add(v);

    while(!PQ.isEmpty()){

       v=PQ.poll();
       u = new Node();
       if(v.bound>maxProfit){ // check if node is still promising

           u.level = v.level+1; // set u to the child that includes the next item

           u.weight = v.weight + w[u.level];
           u.profit = v.profit + p[u.level];


           if (u.weight <=W && u.profit > maxProfit){
               maxProfit = u.profit;
               usedWeight = u.weight;
           }

           u.bound = bound(u, W, n, w, p);

           if(u.bound > maxProfit){
               PQ.add(u);
           }

           u = new Node();
           u.level = v.level+1;
           u.weight = v.weight; // set u to the child that does not include the next item
           u.profit = v.profit;
           u.bound = bound(u, W, n, w, p);

           if(u.bound>maxProfit)
               PQ.add(u);


       }


    }
    Solution solution = new Solution();
    solution.value = maxProfit;
    solution.weight = usedWeight;

    double timeStop = System.currentTimeMillis();
    double elapsedTime = timeStop - timeStart;
    System.out.println("* Time spent in branch and bound (milliseconds):" + elapsedTime);

    return solution;

}



static double bound(Node u, double W, int n, int [] w, int [] p){

    int j=0; int k=0;
    int totWeight=0;
    double result=0;

    if(u.weight>=W)
        return 0;

    else {

        result = u.profit;
        totWeight = u.weight; // por esto no hace

        if(u.level < w.length)
        {
          j= u.level +1;
        }



        int weightSum;

        while ((j < n) && ((weightSum=totWeight + w[j])<=W)){
            totWeight = weightSum; // grab as many items as possible
             result = result + p[j];
            j++;
        }
        k=j; // use k for consistency with formula in text

        if (k<n){
            result = result + ((W - totWeight) * p[k] / w[k]);// grab fraction of excluded kth item
        }
        return result;
    }

}



}

【问题讨论】:

  • 试着问一个更简洁的问题。真的很难理解这 100 多个 LOC 中的坏处。

标签: java optimization knapsack-problem


【解决方案1】:

我得到了一个稍微快一点的实现,它使用泛型删除了所有 Collection 实例,而是使用数组。

【讨论】:

    【解决方案2】:

    不确定您是否仍需要深入了解算法,或者您的调整是否已解决您的问题,但使用广度优先分支定界算法(如您已实现的算法),内存使用的可能性始终存在问题。当然,您希望能够排除足够数量的分支,以保持优先级队列中的节点数量相对较少,但在最坏的情况下,您最终可能会与内存中保存的背包中的项目选择的可能排列一样多的节点。当然,最坏的情况是极不可能的,但对于大型问题实例,即使是普通的树也可能最终会用数百万个节点填充您的优先级队列。

    如果您要在代码中抛出大量无法预料的大问题实例,并且需要知道无论算法必须考虑多少个分支,您都永远不会耗尽内存,我' d 考虑深度优先分支定界算法,如本书第 2.5.1 节中概述的 Horowitz-Sahni 算法:http://www.or.deis.unibo.it/knapsack.html。对于某些问题实例,这种方法在找到最佳解决方案之前必须考虑的可能解决方案的数量方面效率较低,但对于某些问题实例,它会更有效——它实际上取决于结构树。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-21
      • 1970-01-01
      • 2011-05-12
      • 1970-01-01
      • 2011-04-15
      • 2013-05-16
      • 1970-01-01
      相关资源
      最近更新 更多