2011-09-19 19 views
1

我写了基于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; 
    } 

} 



} 
+0

试着问一个更简洁的问题。在这100多个LOC中,很难弄清楚什么是坏的。 – Roman

回答

0

我有一个稍微迅速地执行带走泛型所有的集合实例,而是使用数组。

0

不确定你是否仍然需要洞察算法,或者你的调整是否已经解决了你的问题,但是使用广度优先的分支和界限算法,就像你实现的那样,总会有潜在的内存使用问题。当然,当你希望排除足够数量的分支以保持优先级队列中的节点数量相对较小时,你希望能够保留足够数量的分支,但在最坏的情况下,最终可能会导致在存储器中保存的背包中的项目选择可能具有多达多个节点。当然,最糟糕的情况是极不可能的,但对于大型问题实例,即使是平均树也可能最终将数百万个节点填充到优先级队列中。

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