Skip to content

[Bridges] fix bridges before final_touch and after bound changes - #3108

Merged
odow merged 5 commits into
jump-dev:masterfrom
chriscoey:cc/indicator-milp-before-final-touch
Oct 18, 2026
Merged

odow merged 5 commits into
jump-dev:masterfrom
chriscoey:cc/indicator-milp-before-final-touch

Conversation

@chriscoey

@chriscoey chriscoey commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Before final_touch runs, SOS1ToMILPBridge, SOS2ToMILPBridge and IntegerToZeroOneBridge each report a ScalarAffineFunction-in-EqualTo constraint that they have not created yet. The bridged model then under-counts its equality constraints, and since ListOfConstraintTypesPresent skips any type whose count is 0, copy_to can silently drop a user's equality:

import MathOptInterface as MOI
model = MOI.Bridges.Constraint.SOS1ToMILP{Float64}(MOI.Utilities.Model{Float64}())
x = MOI.add_variables(model, 3)
MOI.add_constraint.(model, x, MOI.Interval(0.0, 2.0))
MOI.add_constraint(model, 1.0 * x[1] + 1.0 * x[2], MOI.EqualTo(1.0))
MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.SOS1([1.0, 2.0, 3.0]))
F, S = MOI.ScalarAffineFunction{Float64}, MOI.EqualTo{Float64}
MOI.get(model, MOI.NumberOfConstraints{F,S}())  # 0
dest = MOI.Utilities.Model{Float64}()
MOI.copy_to(dest, model)
MOI.get(dest, MOI.NumberOfConstraints{F,S}())   # 0

IndicatorToMILPBridge has a similar problem, and its ListOfVariableIndices also throws TypeError: in typeassert, expected MathOptInterface.VariableIndex, got a value of type Nothing, so copy_to fails. With MOI.instantiate(HiGHS.Optimizer; with_cache_type = Float64, with_bridge_type = Float64), writing the model to an LP file before optimize! drops the equality in the SOS case and throws in the indicator case.

These bridges now report no variables or constraints until final_touch has created them.

While here, I fixed the ZeroOne count of ReifiedCountDistinctToMILPBridge, which was -2 before final_touch, and IndicatorToMILPBridge keeping a deleted constraint index after a bound change (empty instead of empty!). IntegerToZeroOneBridge also kept its old expansion after a bound change between final_touch calls: widening an integer x from [0, 3] to [0, 7] left x - y1 - 2 y2 == 0 in the model, so x still could not exceed 3.

@chriscoey chriscoey changed the title [Bridges] fix variable and constraint counts and lists before final_touch [Bridges] fix bridges before final_touch and after bound changes Oct 17, 2026
@odow
odow merged commit 98579e8 into jump-dev:master Oct 18, 2026
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants