Strange values for GRB_CB_MIP_OBJBST and GRB_CB_MIP_OBJBND at root node
AnsweredI am trying to get primal and dual bounds at the root node. I use the following code:
struct RootNodeInfoCB : public GRBCallback {
void callback() override {
if(where == GRB_CB_MIPNODE) {
const auto node = (size_t) getDoubleInfo(GRB_CB_MIPSOL_NODCNT);
if(node == 0u) { // Root node
std::cout << getDoubleInfo(GRB_CB_MIP_OBJBST) << ","
<< getDoubleInfo(GRB_CB_MIP_OBJBND) << "\n";
}
}
}
};
However, it always print values 6.95292e-310, 6.95292e-310; in the log, instead, I see the primal/dual bound evolving normally. Here is the log without the callback prints:
Gurobi Optimizer version 9.0.1 build v9.0.1rc0 (linux64)
Optimize a model with 4896 rows, 4412 columns and 26153 nonzeros
Model fingerprint: 0x48c5a908
Variable types: 0 continuous, 4412 integer (4321 binary)
Coefficient statistics:
Matrix range [1e+00, 1e+03]
Objective range [1e+00, 2e+01]
Bounds range [1e+00, 3e+02]
RHS range [1e+00, 1e+03]
Presolve removed 4327 rows and 753 columns
Presolve time: 0.06s
Presolved: 569 rows, 3659 columns, 8245 nonzeros
Variable types: 0 continuous, 3659 integer (3584 binary)
Root relaxation: objective 3.920359e+02, 620 iterations, 0.01 seconds
Nodes | Current Node | Objective Bounds | Work
Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time
0 0 392.03590 0 96 - 392.03590 - - 0s
0 0 402.11640 0 144 - 402.11640 - - 0s
0 0 402.20370 0 133 - 402.20370 - - 0s
0 0 402.20370 0 137 - 402.20370 - - 0s
0 0 405.38889 0 109 - 405.38889 - - 0s
0 0 405.45174 0 97 - 405.45174 - - 0s
0 0 405.57778 0 98 - 405.57778 - - 0s
0 0 405.71477 0 104 - 405.71477 - - 0s
0 0 405.76641 0 105 - 405.76641 - - 0s
0 0 405.77091 0 105 - 405.77091 - - 0s
0 0 407.12088 0 103 - 407.12088 - - 0s
0 0 407.76378 0 106 - 407.76378 - - 0s
0 0 407.78641 0 103 - 407.78641 - - 0s
0 0 407.78641 0 106 - 407.78641 - - 0s
0 0 408.84211 0 108 - 408.84211 - - 0s
0 0 409.00000 0 92 - 409.00000 - - 0s
0 0 409.00000 0 100 - 409.00000 - - 0s
0 0 409.00000 0 110 - 409.00000 - - 0s
0 0 409.00000 0 105 - 409.00000 - - 0s
0 0 409.00000 0 99 - 409.00000 - - 0s
0 0 409.00000 0 100 - 409.00000 - - 0s
0 0 409.00000 0 72 - 409.00000 - - 0s
0 0 409.00000 0 85 - 409.00000 - - 0s
0 0 409.00000 0 77 - 409.00000 - - 0s
0 0 409.00000 0 55 - 409.00000 - - 0s
0 0 410.00000 0 49 - 410.00000 - - 0s
0 0 410.00000 0 28 - 410.00000 - - 0s
H 0 0 422.0000000 410.00000 2.84% - 0s
0 0 410.00000 0 58 422.00000 410.00000 2.84% - 0s
0 0 410.00000 0 98 422.00000 410.00000 2.84% - 0s
0 0 410.00000 0 64 422.00000 410.00000 2.84% - 0s
0 0 410.00000 0 86 422.00000 410.00000 2.84% - 0s
0 0 410.00000 0 86 422.00000 410.00000 2.84% - 0s
0 0 410.00000 0 60 422.00000 410.00000 2.84% - 0s
0 0 410.09804 0 99 422.00000 410.09804 2.82% - 0s
0 0 410.15385 0 101 422.00000 410.15385 2.81% - 0s
0 0 410.20000 0 98 422.00000 410.20000 2.80% - 0s
0 0 410.20000 0 91 422.00000 410.20000 2.80% - 0s
0 0 410.80000 0 87 422.00000 410.80000 2.65% - 0s
0 0 410.83333 0 84 422.00000 410.83333 2.65% - 0s
0 0 410.93333 0 81 422.00000 410.93333 2.62% - 0s
0 0 410.93333 0 81 422.00000 410.93333 2.62% - 0s
0 0 411.50000 0 77 422.00000 411.50000 2.49% - 0s
0 0 411.50000 0 81 422.00000 411.50000 2.49% - 0s
0 0 411.50000 0 81 422.00000 411.50000 2.49% - 0s
0 0 411.50000 0 80 422.00000 411.50000 2.49% - 0s
0 0 411.50000 0 78 422.00000 411.50000 2.49% - 0s
0 0 411.50000 0 69 422.00000 411.50000 2.49% - 0s
0 0 413.25000 0 53 422.00000 413.25000 2.07% - 0s
0 0 413.25000 0 84 422.00000 413.25000 2.07% - 0s
0 0 413.25000 0 64 422.00000 413.25000 2.07% - 0s
0 0 413.25000 0 87 422.00000 413.25000 2.07% - 0s
0 0 413.25000 0 78 422.00000 413.25000 2.07% - 0s
0 0 413.25000 0 77 422.00000 413.25000 2.07% - 0s
0 0 413.25000 0 76 422.00000 413.25000 2.07% - 0s
0 0 413.25000 0 83 422.00000 413.25000 2.07% - 0s
0 0 413.25000 0 74 422.00000 413.25000 2.07% - 0s
0 0 413.25000 0 9 422.00000 413.25000 2.07% - 0s
0 0 413.25000 0 79 422.00000 413.25000 2.07% - 0s
0 0 413.25000 0 67 422.00000 413.25000 2.07% - 0s
0 0 413.25000 0 48 422.00000 413.25000 2.07% - 0s
0 0 413.25000 0 44 422.00000 413.25000 2.07% - 0s
0 2 413.25000 0 44 422.00000 413.25000 2.07% - 0s
Cutting planes:
Learned: 5
Gomory: 2
Cover: 5
Implied bound: 10
Clique: 13
MIR: 21
StrongCG: 2
GUB cover: 1
Zero half: 4
RLT: 11
Relax-and-lift: 5
Explored 104 nodes (5596 simplex iterations) in 0.97 seconds
Thread count was 4 (of 4 available processors)
Solution count 2: 422 422
Optimal solution found (tolerance 1.00e-04)
Best objective 4.220000000000e+02, best bound 4.220000000000e+02, gap 0.0000%
User-callback calls 984, time in user-callback 0.00 sec
In general, there are a few things which I don't understand:
- GRB_CB_MIP_OBJBST and GRB_CB_MIP_OBJBND always print what I imagine is some kind of default value. Are these not the right info to query to get the primal/dual bounds at the root node?
- The log says it explores 104 nodes. However, I noticed that in my callback when where == GRB_CB_MIPNODE, the value of GRB_CB_MIPSOL_NODCNT is always 0. Is this a wrong value (again, some kind of default), or are the other 103 nodes after the root node not triggering GRB_CB_MIPNODE?
- I want a callback to be called at the root node only. My callback, however, if I get it working, will be called at each node and must check every time if it is at the root node. If I explore 1'000'000 nodes, would this result in >= 1'000'000 calls to my callback? I guess my cpu's branch predictor will do a good job at guessing the check is always false after the first few calls, but still... isn't there a way do "disable" a callback?
Thanks!
-
Official comment
This post is more than three years old. Some information may not be up to date. For current information, please check the Gurobi Documentation or Knowledge Base. If you need more help, please create a new post in the community forum. Or why not try our AI Gurobot?. -
\( \texttt{GRB_CB_MIP_OBJBST} \) and \( \texttt{GRB_CB_MIP_OBJBND} \) are specifically meant to be used when \( \texttt{where == GRB_CB_MIP} \). Similarly, \( \texttt{GRB_CB_MIPSOL_NODCNT} \) is meant to be used when \( \texttt{where == GRB_CB_MIPSOL} \).
When \( \texttt{where == GRB_CB_MIPNODE} \), use:
- \( \texttt{GRB_CB_MIPNODE_OBJBST} \) for the best objective value
- \( \texttt{GRB_CB_MIPNODE_OBJBND} \) for the best objective bound
- \( \texttt{GRB_CB_MIPNODE_NODCNT} \) for the explored node count.
See the Callback Codes section of the documentation for more details.
You can wrap the code in the callback function with a conditional statement to avoid running the entire code every time the callback is triggered (not unlike what you already do). This should have a low overhead.
1 -
Thanks Eli. It completely escaped me that I was using a where == GRB_CB_MIPNODE but then I was using the MIPSOL and MIP codes. Changing that fixed this problem.
It's still not clear to me what happens with the number of nodes, though. My callback is called 100% of the time with GRB_CB_MIPNODE_NODCNT == 0, the primal and dual bound are equal at the end of the exploration of the root node, so I would assume Gurobi should only explore one node. However, the log still says 104 nodes were explored, and GRB_DoubleAttr_NodeCount also says it's 104. Am I missing something here?
P.S. How do you format in-line code nicely with fixed-width font?
0 -
Could you post your revised callback code, along with the log output (including values printed in the callback function)?
To write \(\texttt{inline code}\), you can use:
\(\texttt{inline code}\)
For more information, see the Posting to the Community Forum article.
0 -
Sorry Eli, it was my mistake. Indeed everything works as it's supposed to, including bounds and number of nodes explored. Thanks a lot for your help.
0
Post is closed for comments.
Comments
5 comments