sat: do not remove an enforcement literal from incomplete activity bounds - #5294
Open
jipjan wants to merge 1 commit into
Open
sat: do not remove an enforcement literal from incomplete activity bounds#5294jipjan wants to merge 1 commit into
jipjan wants to merge 1 commit into
Conversation
…unds RemoveEnforcementThatMakesConstraintTrivial() computes min/max activity of the boolean terms under the assumption that one enforcement literal is false, then removes that literal when the resulting activity is included in the rhs. Two guards inside that loop say they abort -- "This is not supposed to happen after PresolveEnforcement(), so we just abort in this case" -- but they only break out of the inner loop. Control still reaches the IsIncludedIn(rhs) test with min/max_activity missing every remaining term, so the interval is too narrow (and can even be empty, which is included in any domain). The literal is then removed and a conditional constraint silently becomes unconditional, losing every solution that had the enforcement false. Skip the test when either guard fired, which is what "abort" appears to mean.
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
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.
ActivityBoundHelper::RemoveEnforcementThatMakesConstraintTrivial()computes the min/max activity of a row's boolean terms under the assumption that one enforcement literal is false, and removes that literal when the resulting activity is included in the rhs — i.e. when the constraint holds anyway.Two guards inside that loop announce that they abort:
but
breakonly leaves the inner loop. Control still falls intowith
min_activity/max_activitymissing the contribution of every term after the break. Those bounds are not valid: the interval is too narrow, and if the accumulatedmax_activityis belowmin_activitythe domain is empty, whichIsIncludedIn()reports as included in anything. The enforcement literal is then removed, soenf => rowsilently becomes an unconditionalrowand every solution withenffalse that did not satisfy the row is lost — a wrong optimum, or an infeasible answer on a satisfiable model.This PR skips the test when either guard fired, which is what "abort" appears to have been intended to mean. No other behaviour changes.
Context
Found while root-causing #5293 (a certified-optimal answer 51 % above a verified feasible solution, on an all-linear 90'770-variable model). The actual cause of that issue is a different defect in the same function, which
mainhas already fixed:non_amo_min_activity/non_amo_max_activitywereintaccumulatingint64_tcoefficients, so a boolean term above 2³¹ wrapped them. That is stillintin the current release (v9.15) andint64_tonmain.So this PR is the remaining half. I have no model that triggers it — instrumenting
v9.15on my reproducer showsbroke=0on every removal, the overflow being the culprit there — so it is offered as a soundness fix for a path whose own comments say it should not be reached, rather than as a fix for an observed failure.Testing
Compiled and run as part of a two-hunk patch on
v9.15(the function is otherwise identical there), against both the original 86'541-constraint model from #5293 and a 192-constraint delta-debugged version of it. Both give the correct optimum with default parameters, and the answers are unchanged by this hunk alone since it never fires on them.