Skip to content

Conversation

nguidotti
Copy link
Contributor

@nguidotti nguidotti commented Oct 9, 2025

With this PR, the solver propagates the bounds from the parent to the child nodes. If the solver reaches the end of a branch (i.e., when the node becomes infeasible or an integer feasible solution is found), the bounds are recomputed from scratch.

Average (Primal) Gap over the MIPLIB2017 dataset:
main (91a19f8): 15.917959 with 224 feasible solutions
This PR: 15.519858 with 224 feasible solutions

Checklist

  • I am familiar with the Contributing Guidelines.
  • Testing
    • New or existing tests cover these changes
    • Added tests
    • Created an issue to follow-up
    • NA
  • Documentation
    • The documentation is up to date with these changes
    • Added new documentation
    • NA

@nguidotti nguidotti added this to the 25.12 milestone Oct 9, 2025
@nguidotti nguidotti self-assigned this Oct 9, 2025
@nguidotti nguidotti added non-breaking Introduces a non-breaking change improvement Improves an existing functionality labels Oct 9, 2025
Copy link

copy-pr-bot bot commented Oct 9, 2025

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@nguidotti
Copy link
Contributor Author

/ok to test f44b134

@nguidotti nguidotti marked this pull request as ready for review October 14, 2025 13:06
@nguidotti nguidotti requested a review from a team as a code owner October 14, 2025 13:06
@nguidotti nguidotti requested review from aliceb-nv and rg20 October 14, 2025 13:06
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile Overview

Greptile Summary

This PR implements bounds propagation optimization in the branch-and-bound solver for mixed-integer programming (MIP). The key change is that bounds (variable upper/lower limits) are now efficiently propagated from parent nodes to child nodes during tree traversal, rather than being recomputed from scratch at every node. The implementation tracks which bounds have changed using a bounds_changed vector and selectively triggers full recomputation only when necessary (when nodes become infeasible or integer feasible solutions are found). The changes span three core files: branch_and_bound.hpp updates the method signature, mip_node.hpp refactors bounds update logic into separate methods, and branch_and_bound.cpp implements the conditional bounds update mechanism with performance optimizations for the dual simplex solver.

Important Files Changed

Changed Files
Filename Score Overview
cpp/src/dual_simplex/branch_and_bound.hpp 5/5 Updated solve_node method signature to support bounds propagation tracking
cpp/src/dual_simplex/mip_node.hpp 4/5 Refactored bounds update logic with new update_variable_bound method and optimized traversal
cpp/src/dual_simplex/branch_and_bound.cpp 4/5 Implemented conditional bounds recomputation logic with performance optimizations

Confidence score: 4/5

  • This PR implements a well-understood optimization for branch-and-bound algorithms with clear performance benefits
  • Score reflects solid implementation but complexity in bounds management logic could introduce subtle bugs if bounds tracking becomes inconsistent
  • Pay close attention to the bounds update logic in mip_node.hpp to ensure tighter bounds are never overwritten by looser ones

Sequence Diagram

sequenceDiagram
    participant User
    participant BranchAndBound as "Branch & Bound Solver"
    participant Node as "MIP Node"
    participant LP as "LP Solver"
    
    User->>BranchAndBound: "solve(solution)"
    
    BranchAndBound->>BranchAndBound: "solve_node()"
    
    Note over BranchAndBound: Bounds propagation logic
    BranchAndBound->>Node: "get_variable_bounds(lower, upper, bounds_changed)"
    Node->>Node: "update_variable_bound() for current node"
    
    loop For each parent node up to root
        Node->>Node: "update_variable_bound() from parent"
        Note over Node: Propagates bounds from parent to child
    end
    
    Node-->>BranchAndBound: "Updated bounds with bounds_changed flags"
    
    BranchAndBound->>LP: "bound_strengthening()"
    LP-->>BranchAndBound: "feasible status"
    
    alt Node is feasible
        BranchAndBound->>LP: "dual_phase2() with updated bounds"
        LP-->>BranchAndBound: "LP solution"
        
        alt Solution is integer feasible
            BranchAndBound->>BranchAndBound: "add_feasible_solution()"
        else Solution is fractional
            BranchAndBound->>Node: "branch() - create child nodes"
            Note over Node: Children inherit parent bounds
            Node->>Node: "add_children(down_child, up_child)"
        end
    else Node is infeasible
        BranchAndBound->>Node: "set_status(INFEASIBLE)"
    end
    
    BranchAndBound-->>User: "Final solution with bounds propagation"
Loading

3 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

@nguidotti nguidotti changed the base branch from branch-25.10 to branch-25.12 October 14, 2025 13:39
@nguidotti nguidotti requested review from a team as code owners October 14, 2025 13:39
@nguidotti nguidotti requested review from jakirkham and rgsl888prabhu and removed request for a team October 14, 2025 13:39
@rg20 rg20 changed the base branch from branch-25.12 to branch-25.10 October 14, 2025 13:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

improvement Improves an existing functionality non-breaking Introduces a non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant