Дроссель памяти при реализации ветвей и связанных ранцев - PullRequest
1 голос
/ 19 сентября 2011

Я написал эту реализацию алгоритма ветвления и связывания ранца на основе псевдо-Java-кода отсюда .К сожалению, в больших случаях проблемы задыхается память, вот так .Почему это?Как я могу сделать эту реализацию более эффективной с точки зрения памяти?

Входные данные в файле по ссылке отформатированы следующим образом:

 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;
    }

}



}

Ответы [ 2 ]

0 голосов
/ 19 октября 2011

Не уверен, что вам все еще нужно понимание алгоритма или ваши настройки решили вашу проблему, но с помощью алгоритма ветвления и привязки в ширину, подобного тому, который вы реализовали, всегда будет потенциал для использования памятипроблема.Вы, конечно, надеетесь, что вы сможете исключить достаточное количество ветвей, чтобы сохранить количество узлов в очереди приоритетов относительно небольшим, но в худшем случае вы можете оказаться в конечном итоге.с таким количеством узлов, сколько есть возможных вариантов выбора элементов в рюкзаке, хранящемся в памяти.Наихудший сценарий, конечно, крайне маловероятен, но для больших проблемных случаев даже среднее дерево может в конечном итоге заполнить вашу очередь приоритетов миллионами узлов.

Если вы собираетесь бросать многонепредвиденные большие проблемы в вашем коде, и вам нужно знать, что независимо от того, сколько ветвей нужно учесть в алгоритме, у вас никогда не будет нехватки памяти, я бы рассмотрел алгоритм ветвления и привязки с глубиной, такой какАлгоритм Горовица-Сахни, описанный в разделе 2.5.1 этой книги: http://www.or.deis.unibo.it/knapsack.html. В некоторых случаях такой подход будет менее эффективным с точки зрения количества возможных решений, которые необходимо рассмотреть, прежде чем будет найдено оптимальное,но опять же для некоторых проблемных случаев это будет более эффективно - это действительно зависит от структуры дерева.

0 голосов
/ 02 октября 2011

Я получил немного более быструю реализацию, убрав все экземпляры Collection с помощью шаблонов и вместо этого используя массивы.

...