2011-09-19 1 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。いくつかの問題インスタンスでは、このアプローチは、最適なものが見つかる前に考えなければならない解決策の数の点で効率が悪くなりますが、いくつかの問題インスタンスについては、より効率的になります。木の

関連する問題