[ENH] set_cover Python: expose the lower bound accessors directly - #5277
Open
jg-codes wants to merge 1 commit into
Open
[ENH] set_cover Python: expose the lower bound accessors directly#5277jg-codes wants to merge 1 commit into
jg-codes wants to merge 1 commit into
Conversation
DualAscentOptimizer computes a dual lower bound and stores it via inv()->ReportLowerBound() (set_cover_heuristics.cc:1276, :1314). SetCoverInvariant exposes it in C++ as LowerBound() and CostOrLowerBound(), neither of which is bound in the pybind11 wrapper. The value is reachable from Python today, just indirectly: ExportSolutionAsProto() serializes it into SetCoverSolutionResponse.cost_lower_bound (set_cover_invariant.cc:536), and that binding exists. But reading a scalar today means serializing the whole solution proto, which is awkward when the caller wants an optimality gap next to inv.cost(). Binds LowerBound(), CostOrLowerBound() and is_cost_consistent(). The last one is needed because ReportLowerBound() is called with is_cost_consistent=false, so a caller has to be able to tell whether the invariant currently holds a feasible solution or a relaxation, which is exactly what CostOrLowerBound() switches on. Adds two tests. Built and tested on Linux (Bazel 8.7.0) against main at d9c0910: bazel test //ortools/set_cover/python:set_cover_test passes.
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
[ENH] set_cover Python: expose the lower bound accessors directly
Disclosure: drafted with AI assistance (Claude). See the verification section for exactly what was built and run.
What
DualAscentOptimizercomputes a dual lower bound and stores it on the invariant:SetCoverInvariantexposes it in C++ atset_cover_invariant.h:146(LowerBound()) and:131(CostOrLowerBound()). Neither is bound inortools/set_cover/python/set_cover.cc.The value is reachable from Python today, just indirectly:
ExportSolutionAsProto()writes it intoSetCoverSolutionResponse.cost_lower_boundatset_cover_invariant.cc:536, and that binding exists.That serializes the whole solution (selected subsets, cost, all of it) to read one scalar. This patch binds the accessor directly, next to the existing
costbinding:For applied work that gap is the difference between handing a planner a depot network and handing them a network with a statement about how much room is left. The number already exists; this is about it sitting next to
cost(), where a caller looking for it would expect to find it.Changes
ortools/set_cover/python/set_cover.cc: three.def()lines onSetCoverInvariant, next to the existingcostbinding:lower_bound(),cost_or_lower_bound(),is_cost_consistent().ortools/set_cover/python/set_cover_test.py: two tests.is_cost_consistent()is included deliberately.ReportLowerBound()is called withis_cost_consistent=false, andCostOrLowerBound()switches on that flag, so without it a caller cannot tell which of the two numbers they just received.No new dependency, no build change.
Verification
Built and tested on Linux (Bazel 8.7.0, x86_64) against
mainatd9c0910:clang-formatclean against the repo.clang-format; the Python isblackclean at the file's existing line width.I also exercised the end-to-end path this patch is meant to unblock, using a temporary local benchmark script against the same build:
DualAscentOptimizer.optimize()followed byinv.lower_bound()returns a non-trivial bound on real OR-Library SCP instances (see #5122 for the numbers). That path could not be checked before, sinceDualAscentOptimizeris not in the released PyPI wheel this PR was originally drafted against.Checklist
main