how to update a node's lower and upper bound
我正在尝试编写一个新的 scip 松弛处理程序。对于每个节点,我想用我想出的值来更新它的下限和上限。然后我希望 scip 在其求解过程中自然地使用这些更好的界限。但我得到了奇怪的结果。
我的问题是如何更新分支和边界中当前节点的下限和上限?
在我的关系处理程序中,我有以下调试代码:
1 2 3 4 5 6 7 8 9 | double l = -100; double u = -15; cout <<"SCIP STAGE" << (scip->set->stage) << std::endl; cout << SCIPgetNNodes(scip) <<" min scip " << SCIPgetLocalLowerbound(scip) <<" <=" << SCIPgetUpperbound(scip) << endl; cout << SCIPgetNNodes(scip) <<" min my b " << l <<" <=" << u << endl; SCIPupdateLocalLowerbound(scip, l); cout << SCIPgetNNodes(scip) <<" min scip " << SCIPgetLocalLowerbound(scip) <<" <=" << SCIPgetUpperbound(scip) << endl; |
输出是
1 2 3 4 | SCIP STAGE 9 1 min scip -1e+14 <= -100000 1 min my b -100 <= -15 1 min scip 1e+20 <= -10000 |
scip stage 9 是 SCIP_STAGE_SOLVING,看起来不错。
带有"scip"的行是节点的scip 边界。
带有"my b"的中间线是指我的新界限。
我正在调用
我希望
另外,我没有看到一个名为
编辑 2015/03/13
感谢 Gregor 解释了 scip 的那部分。我还有一个小问题。
为了完整起见,我将本地节点的最小化问题的下限设置为
1 | SCIPupdateLocalLowerbound(scip, l) |
我正在通过
设置最小化问题的全局上限
1 2 3 4 | if ( newUpperBound < scip->primal->upperbound) { SCIPprimalSetUpperbound(scip->primal, scip->mem->probmem, scip->set, scip->stat, scip->eventqueue, scip->transprob, scip->tree, scip->lp, newUpperBound); } |
SCIPprimalSetUpperbound 的第二个参数采用
1 | BMS_BLKMEM* blkmem, /**< block memory */ |
我正在传递一个我在 scip->mem 中找到的 blkmem。这是正确的,还是我应该传递一些其他干净的块内存?我是否覆盖了一些重要的东西?
编辑 2015/03/19
现在我不明白设置目标函数时的输出。提醒一下(对我来说),原来的主问题是最大化问题,而 scip 的转换问题是最小化问题。如果我查看
的结果
1 2 3 4 5 6 | cout << SCIPgetNNodes(scip) <<" min scip " << SCIPgetLocalLowerbound(scip) <<" <=" << SCIPgetUpperbound(scip) << endl; cout << SCIPgetNNodes(scip) <<" min my b " << newLowerBound <<" <=" << newUpperBound << endl; cout <<"SCIPgetObjlimit" << SCIPgetObjlimit(scip) << endl; cout <<"SCIPretransformObj" << SCIPretransformObj(scip,newUpperBound) << endl; |
输出为:
1 2 3 4 | 7 min scip -1.10142e+08 <= 100000 7 min my b -1.37597e+08 <= 2.11197e+08 SCIPgetObjlimit -1.97183e+08 SCIPretransformObj -2.11197e+08 |
所以 scip 的这个节点的最小值的界限是 -1.10142e 08 <= 100000,我这个节点的最小值的界限是 -1.37597e 08 <= 2.11197e 08,在这种情况下更糟。
为什么 SCIPgetObjlimit = -1.97183e 08?为什么不是-100000?如果 100000 是转换空间中的当前上限(最小化),那么 -100000 是我原始问题的当前全局下限。
虽然下界是每个节点特有的局部属性(因为它们通常是从该节点处的最佳 LP 松弛目标推断出来的,或者如果它们已经被求解,则上界来自原始的针对您的问题的解决方案,因此在全球范围内有效。
从 SCIP 的angular来看,下限大于或等于全局上限的每个节点都可以被修剪,并且这些节点得到无穷大(即默认 SCIP 设置的 1e 20)作为下限。仔细查看这些值会发现您强制修剪此节点,因为当您将本地边界设置为 l=-100 时,全局边界为 -100000,因此 SCIP 的行为在这里是有意的。
编辑
关于您问题的第二部分:实际上,从某种意义上说,从 primal.h 中使用诸如
我建议通过
编辑原始问题和转换问题中的原始边界:
我假设您设置了一个客观的限制,但 SCIP 找到了一个更好的原始解决方案。