2011-09-19 3 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)과 같이 깊이 우선 분기와 바운드 알고리즘을 고려해야합니다. 일부 문제의 경우이 접근법은 최적의 솔루션이 발견되기 전에 고려해야 할 가능한 솔루션 수의 측면에서 효율성이 떨어지지만 일부 문제 인스턴스의 경우 다시 효율적입니다. 이는 실제로 구조에 따라 달라집니다 나무의.