-
Notifications
You must be signed in to change notification settings - Fork 92
Fix explored nodes counter #570
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: release/25.12
Are you sure you want to change the base?
Conversation
WalkthroughThe branch-and-bound algorithm's node counting and progress logging flow has been refactored. Node counter updates (nodes_explored, nodes_unexplored, nodes_since_last_log) are repositioned to occur around cutoff handling rather than per-step. A new should_report_ coordination flag gates logging behavior, with logging state reset after each report emission. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
/ok to test bd697c9 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
cpp/src/dual_simplex/branch_and_bound.cpp (1)
723-737: Use the current lower bound when loggingHere we print progress using
user_lower = compute_user_objective(original_lp_, root_objective_). That root objective is the initial LP bound, so after the tree tightens the lower bound the reported gap never reflects it and the metric stays artificially wide. Please baseuser_lower(and the gap) on the current lower bound you already computed for this node.diff --git a/cpp/src/dual_simplex/branch_and_bound.cpp b/cpp/src/dual_simplex/branch_and_bound.cpp @@ - f_t obj = compute_user_objective(original_lp_, upper_bound); - f_t user_lower = compute_user_objective(original_lp_, root_objective_); + f_t obj = compute_user_objective(original_lp_, upper_bound); + f_t user_lower = compute_user_objective(original_lp_, lower_bound);
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
cpp/src/dual_simplex/branch_and_bound.cpp(8 hunks)cpp/src/dual_simplex/branch_and_bound.hpp(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
cpp/src/dual_simplex/branch_and_bound.cpp (2)
cpp/src/dual_simplex/branch_and_bound.hpp (6)
node(89-94)node(89-89)node(96-103)node(96-98)search_tree(233-237)search_tree(258-264)cpp/src/dual_simplex/solve.cpp (6)
compute_user_objective(98-103)compute_user_objective(98-98)compute_user_objective(106-110)compute_user_objective(106-106)compute_user_objective(650-651)compute_user_objective(653-653)
| if (lower_bound > upper_bound || rel_gap < settings_.relative_mip_gap_tol) { | ||
| search_tree->graphviz_node(settings_.log, node, "cutoff", node->lower_bound); | ||
| search_tree->update_tree(node, node_status_t::FATHOMED); | ||
| ++stats_.nodes_explored; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit strange. I think of nodes explored as the number of nodes we have solved, or perhaps proved infeasible through node presolve. If we are fathoming the node here I would not count it as explored.
| search_tree->update_tree(node, node_status_t::FATHOMED); | ||
| ++stats_.nodes_explored; | ||
| --stats_.nodes_unexplored; | ||
| ++stats_.nodes_since_last_log; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. The purpose of nodes since last log is for us to print every so often in a deterministic way. Here we did no work, so I don't think we want to increase this counter.
| if (stats_.nodes_explored.load() == nodes_explored) { | ||
| stats_.nodes_since_last_log = 0; | ||
| stats_.last_log = tic(); | ||
| bool should_report = should_report_.exchange(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to have member variable to decide if we should log? I think this is increasing the complexity of the code for little return.
| } | ||
| } | ||
|
|
||
| ++stats_.nodes_explored; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: is there a reason why all of these are ++x instead x++?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we incrementing the nodes explored here at all?
chris-maes
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's not count a node as explored if we trivially fathom it.
Let's talk offline about why you increment the nodes explored at the end of explore_subtree.
|
🔔 Hi @anandhkb, this pull request has had no activity for 7 days. Please update or let us know if it can be closed. Thank you! If this is an "epic" issue, then please add the "epic" label to this issue. |
This PR changes how the explored node counter is updated, such that it is only incremented after solving a node in the B&B.
Checklist
Summary by CodeRabbit