如何更新节点的下限和上限

时间:2015-03-11 23:38:00

标签: scip

我正在尝试编写一个新的scip松弛处理程序。对于每个节点,我想用我提出的值更新其下限和上限。然后我想scip在解决过程中自然地使用这些更好的界限。但我得到了奇怪的结果。

我的问题是如何更新分支和绑定中当前节点的下限和上限?

在我的关系处理程序中,我有这个调试代码:

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;

输出

SCIP STAGE 9
1 min scip  -1e+14 <= -100000
1 min my b  -100 <= -15
1 min scip  1e+20 <= -10000

scip阶段9是SCIP_STAGE_SOLVING,看起来不错。

带有“scip”的行是节点的scip界限。 带有“我的b”的中间线指的是我的新界限。

我正在呼叫SCIPupdateLocalLowerbound(scip, -10),而当前的下限是-1e14,因此在该呼叫之后新的下限应为10。但是,下限变为1e20,这是一个巨大的错误。

我希望SCIPupdateLocalLowerbound(scip, -10);SCIPgetLocalLowerbound(scip)返回-10而不是1e20。我做错了什么?

另外,我没有看到名为SCIPupdateLocalUpperbound()的函数,那么如何更新节点的上限呢?

编辑2015/03/13 谢谢Gregor解释那部分scip。我还有一个小问题。

为了完整性,我通过

设置本地节点最小化问题的下限
SCIPupdateLocalLowerbound(scip, l)

我正在通过

设置最小化问题的全局上界
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的第二个参数采用

BMS_BLKMEM*           blkmem,             /**< block memory */

我正在通过我在scip-&gt; mem中找到的blkmem。这是正确的,还是应该通过其他一些干净的内存?我覆盖了一些重要的东西吗?

修改2015/03/19

现在我在设置目标函数时不理解输出。作为一个提醒(对我来说),原始的主要问题是最大化问题,而scip的转换问题是最小化。如果我看一下

的结果
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;

输出是:

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&lt; = 100000,这个节点的最小界限是-1.37597e + 08&lt; = 2.11197e + 08,这更糟糕了这个案例。

为什么SCIPgetObjlimit = -1.97183e + 08?为什么不是-100000?如果100000是变换空间中的当前上界(最小化),则-100000是我当前问题的全局下界。

1 个答案:

答案 0 :(得分:2)

虽然下界是每个节点特有的局部属性(因为它们通常是从该节点处的最佳LP弛豫目标推断出来的,或者是节点子节点已经被解决,因此上界来自原始节点解决您的问题,因此全球有效。

从SCIP的角度来看,每个节点的下限大于或等于全局上限都可以被修剪,并且此类节点获得+无穷大(即1e + 20,默认SCIP设置)为下限。仔细查看这些值会显示您强制修剪此节点,因为当您将本地绑定设置为 l = -100 时,全局绑定为-100000,因此SCIP的行为是打算在这里。

修改 关于你问题的第二部分:在某种意义上,实际上禁止使用这样的方法,例如SCIPprimalSetUpperBound(),它来自 primal.h ,从插件中,例如,你的放松器。原因正是你现在面临的问题,关于你不需要关心的SCIP内部问题。

我建议您通过SCIPsetObjlimit()设置一个客观限制。请注意,必须在原始空间中给出客观限制,即。如果您想先传递上限,请使用ub = SCIPretransformObj(scip, ub),然后使用SCIPsetObjlimit(scip, ub)

编辑原始问题和转化问题的原始界限:

  1. SCIPgetUpperBound(scip):转换问题空间中的当前上界,最小解最小解释目标和(转换)目标限制
  2. SCIPgetPrimalBound(scip):原始问题空间中SCIPgetUpperBound(scip)的值,即。在考虑最佳解决方案和用户目标限制的情况下,如果有的话。
  3. SCIPgetObjlimit(scip):用户设置的客观限制值,尊重原始解决方案目标。
  4. 我假设您设定了一个客观限制,但SCIP找到了一个更好的原始解决方案。