Java 实现背包的分枝定界

Java 实现背包的分枝定界,java,mathematical-optimization,branch-and-bound,Java,Mathematical Optimization,Branch And Bound,对于b&b背包的问题,我很头疼(我想知道:人们为什么要这么做?)。这是到目前为止我的实现,它最多输出80个(当它应该打印90个时,对于教科书样本上的项目)。在将元素传递给算法之前,我创建了一个比较器(在LinkedList上)来按Pi/Wi对元素进行排序,但在此输入上已经进行了预排序。我现在正在调试(并更新发布的代码),因为我猜这是一个数组索引问题。。。还是边界函数有错误 输入: 4 16 //# items maxWeight 40 2 // profit weight 30 5 50 10

对于b&b背包的问题,我很头疼(我想知道:人们为什么要这么做?)。这是到目前为止我的实现,它最多输出80个(当它应该打印90个时,对于教科书样本上的项目)。在将元素传递给算法之前,我创建了一个比较器(在LinkedList上)来按Pi/Wi对元素进行排序,但在此输入上已经进行了预排序。我现在正在调试(并更新发布的代码),因为我猜这是一个数组索引问题。。。还是边界函数有错误

输入:

4 16 //# items maxWeight
40 2 // profit weight
30 5
50 10
10 5


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

}

public class BranchAndBound {
    static int branchAndBound (LinkedList<Item> items, int W) {
        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 = new Node();
        Node v = new Node(); // tree root

        int maxProfit=0;

        LinkedList <Node> Q = new LinkedList<Node>();

        v.level=-1;
        v.profit=0;
        v.weight=0; // v initialized to -1, dummy root

        Q.offer(v); // place the dummy at the root

        while(!Q.isEmpty()){
            v = Q.poll();

            if (v.level==-1){
              u.level=0;
            }
            else if(v.level != (n - 1))
            {
               u.level = v.level+1; // set u to be a child of v
            }

            u = new Node();
            u.weight = v.weight + w[u.level];// set u to the child
            u.profit = v.profit + p[u.level]; // that includes the
                                             //next item
            double bound = bound(u, W, n, w, p);
            u.bound=bound;

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

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

            u = new Node();
            u.weight = v.weight; // set u to the child that
            u.profit = v.profit;// does NOT include the next item

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

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

        return maxProfit;
    }

    public static float bound(Node u, int W, int n, int [] w, int [] p){
        int j=0; int k=0;
        int totWeight=0;
        float result=0;

        if(u.weight>=W)
            return 0;
        else {
            result = u.profit;
            j= u.level +1;
            totWeight = u.weight;

            while ((j < n) && (totWeight + w[j]<=W)){
                totWeight = totWeight + w[j]; // 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 kth item

            return result;
        }
    }
}
4 16/#项目最大重量
40 2//利润权重
30 5
50 10
10 5
类节点
{
智力水平;
国际利润;
整数权重;
双重约束;
}
公务舱{
静态int branchHandbound(LinkedList项,int W){
int n=items.size();
int[]p=新的int[n];
int[]w=新的int[n];
对于(int i=0;imaxProfit){
Q.添加(u);
}
u=新节点();
u、 weight=v.weight;//将u设置为
u、 profit=v.profit;//不包括下一项
束缚=束缚(u,W,n,W,p);
u、 束缚=束缚;
如果(绑定>最大利润){
Q.添加(u);
}
}
回报最大利润;
}
公共静态浮点绑定(节点u,int W,int n,int[]W,int[]p){
int j=0;int k=0;
int-totwweight=0;
浮动结果=0;
如果(u.重量>=W)
返回0;
否则{
结果=美国利润;
j=u级+1;
总重量=单位重量;

虽然((j
enqueue(Q, u)
您应该将
u
副本添加到链接列表中,而不是传递对
u
的引用并继续操作它

换句话说,为类
节点定义一个复制构造函数并执行

Q.offer(new Node(u));
而不是

Q.offer(u);

事实上,您上面给出的代码只为
branchAndBound(..)的每个调用分配类
节点的两个实例

您是否尝试过在调试器中单步执行代码?我正在这样做,代码更新/更改一直是我单步执行的。我猜您的意思是
它应该打印90
而不是
98
是的,我已经更改了创建新节点的步骤。代码仍然有问题,现在它打印320作为最佳值。它打印90是为了me(在我写答案之前的版本)在新版本的代码中,在执行
u=new Node();
之后,您不会复制
u.level
。这就是为什么我建议在调用
Q.offer(…)时使用复制构造函数的原因
而不是将
u
分配给
节点的新实例
。按照您修改它的方式,您必须移动
if(v.level=-1){..}else{..}
u=new Node()之后块;
并在第二个
u=new Node()之后重复相同的块
。然后我也得到了90而不是320。你能在pastebin上发布你所做的吗?我发现三个节点上的边界函数有一个错误,我根据你的建议在节点分配部分更改了一点代码。修复了,我刚刚看到一个遗漏。感谢所有的帮助。