Skip to content

Fix constraints that MiniZinc.Model supported but could not write - #123

Merged
odow merged 1 commit into
jump-dev:masterfrom
chriscoey:coey/unsupported-constraints
Oct 26, 2026
Merged

odow merged 1 commit into
jump-dev:masterfrom
chriscoey:coey/unsupported-constraints

Conversation

@chriscoey

Copy link
Copy Markdown
Contributor

MiniZinc.Model reported support for some constraints that write cannot handle.

VariableIndex in Semicontinuous, Semiinteger and Parameter were ignored when writing the model, so the solve returned a wrong answer:

using JuMP, MiniZinc
model = GenericModel{Int}(() -> MiniZinc.Optimizer{Int}("chuffed"))
@variable(model, x in Semiinteger(2, 3))
@constraint(model, x <= 1)
@objective(model, Max, x)
optimize!(model)
value(x)  # 1, but x must be 0, 2 or 3, so the answer is 0

Similarly, @variable(model, p in Parameter(2)) was written as var int: p;, with no value.

These threw a MethodError when writing the model:

  • ScalarAffineFunction, ScalarQuadraticFunction and ScalarNonlinearFunction in Interval, ZeroOne and Integer
  • VectorOfVariables in Reified{LessThan}, Reified{GreaterThan} and Reified{EqualTo}
using JuMP, MiniZinc
model = GenericModel{Int}(() -> MiniZinc.Optimizer{Int}("chuffed"))
@variable(model, 0 <= x <= 1, Int)
@variable(model, 0 <= y <= 1, Int)
@constraint(model, 1 <= x + y <= 2)
optimize!(model)
# ERROR: MethodError: no method matching _write_constraint(::IOStream, ::Set{String}, ::Dict{...}, ::MathOptInterface.ScalarAffineFunction{Int64}, ::MathOptInterface.Interval{Int64})

supports_constraint now returns false for all of these, like the existing VectorAffineFunction override, so the bridges can reformulate them into constraints that write handles. Both examples now return the right answer.

For the interval example, the bridge adds a slack variable: constraint 1*x + 1*y + -1*x3 = 0; with x3 in 1..2. Writing constraint x + y in 1..2; directly would avoid that. I went with the bridges to match the existing override, but I can switch to writing Interval directly if you prefer.

Without bridges, the Interval, ZeroOne and Integer cases still throw the MethodError, because MOI.copy_to doesn't check supports_constraint for them.

Please merge #122 first: with only this PR, p * y * y <= 18 with p in Parameter(2) is written as ((1*p*y + 0 * y) - 18) <= 0.

@codecov

codecov Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.39%. Comparing base (61a1207) to head (07e55a1).

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #123      +/-   ##
==========================================
+ Coverage   98.38%   98.39%   +0.01%     
==========================================
  Files           5        5              
  Lines         681      687       +6     
==========================================
+ Hits          670      676       +6     
  Misses         11       11              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

MiniZinc.Model reported support for VariableIndex in Semicontinuous,
Semiinteger and Parameter, but `write` ignored those constraints, so
the solve returned a wrong answer. For example, `x in Semiinteger(2, 3)`
with `x <= 1`, maximizing x, returned x = 1 instead of 0.

It also reported support for scalar affine, quadratic and nonlinear
functions in Interval, ZeroOne and Integer, and for VectorOfVariables in
Reified LessThan, GreaterThan and EqualTo, but `write` could not handle
them, so optimize! threw a MethodError. In JuMP this includes
`@constraint(model, 1 <= x + y <= 2)` and
`@constraint(model, [z, x] in MOI.Reified(MOI.LessThan(1)))`.

Returning false from supports_constraint lets the bridges reformulate
them into constraints that `write` supports.
@odow
odow force-pushed the coey/unsupported-constraints branch from a63c645 to 07e55a1 Compare October 26, 2026 22:51
@odow
odow merged commit 5db1128 into jump-dev:master Oct 26, 2026
9 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