MiniZinc.jl is a wrapper for the MiniZinc constraint modeling language.
It provides a way to write MathOptInterface models to .mzn files, and a way to
interact with libminizinc.
This wrapper is maintained by the JuMP community and is not part of the MiniZinc project.
If you need help, please ask a question on the JuMP community forum.
If you have a reproducible example of a bug, please open a GitHub issue.
MiniZinc.jl is licensed under the MIT License.
The underlying project, MiniZinc/libminizinc, is licensed under the MPL 2.0 license.
Install MiniZinc.jl using the Julia package manager:
import Pkg
Pkg.add("MiniZinc")Windows
On Linux and macOS, this package automatically installs libminizinc. However,
we're still working out problems with the install on Windows. To use
MiniZinc.jl, you'll need to manually install a copy of libminizinc from
minizinc.org or compile one yourself from
MiniZinc/libminizinc.
To teach MiniZinc.jl where to look for libminizinc, set the
JULIA_LIBMINIZINC_DIR environment variable. For example:
ENV["JULIA_LIBMINIZINC_DIR"] = "C:\\Program Files\\MiniZinc"MiniZinc.jl supports the constraint programming sets defined in MathOptInterface, as well as (in)equality constraints.
The following example solves the following constraint program:
xᵢ ∈ {1, 2, 3} ∀i=1,2,3
zⱼ ∈ {0, 1} ∀j=1,2
z₁ <-> x₁ != x₂
z₂ <-> x₂ != x₃
z₁ + z₂ = 1
julia> import MiniZinc
julia> import MathOptInterface as MOI
julia> function main()
model = MOI.Utilities.CachingOptimizer(
MiniZinc.Model{Int}(),
MiniZinc.Optimizer{Int}("chuffed"),
)
# xᵢ ∈ {1, 2, 3} ∀i=1,2,3
x = MOI.add_variables(model, 3)
MOI.add_constraint.(model, x, MOI.Interval(1, 3))
MOI.add_constraint.(model, x, MOI.Integer())
# zⱼ ∈ {0, 1} ∀j=1,2
z = MOI.add_variables(model, 2)
MOI.add_constraint.(model, z, MOI.ZeroOne())
# z₁ <-> x₁ != x₂
MOI.add_constraint(
model,
MOI.VectorOfVariables([z[1], x[1], x[2]]),
MOI.Reified(MOI.AllDifferent(2)),
)
# z₂ <-> x₂ != x₃
MOI.add_constraint(
model,
MOI.VectorOfVariables([z[2], x[2], x[3]]),
MOI.Reified(MOI.AllDifferent(2)),
)
# z₁ + z₂ = 1
MOI.add_constraint(model, 1 * z[1] + x[2], MOI.EqualTo(1))
MOI.optimize!(model)
x_star = MOI.get(model, MOI.VariablePrimal(), x)
z_star = MOI.get(model, MOI.VariablePrimal(), z)
return x_star, z_star
end
main (generic function with 1 method)
julia> main()
([1, 1, 3], [0, 1])You can also call MiniZinc from JuMP, using any solver that libminizinc
supports. By default, MiniZinc.jl is compiled with the
HiGHS MILP solver,
which can be selected by passing the "highs" parameter to MiniZinc.Optimizer:
using JuMP
import MiniZinc
model = Model(() -> MiniZinc.Optimizer{Float64}("highs"))
@variable(model, 1 <= x[1:3] <= 3, Int)
@constraint(model, x in MOI.AllDifferent(3))
@objective(model, Max, sum(i * x[i] for i in 1:3))
optimize!(model)
@show value.(x)ORTools_jll currently requires Linux
In order to use the CP-SAT solver from ORTools, use:
import ORTools_jll
path = joinpath(ORTools_jll.artifact_dir, "share", "minizinc", "solvers", "cp-sat.msc")
model = Model(() -> MiniZinc.Optimizer{Float64}(path))The MiniZinc Optimizer{T} supports the following constraints and attributes.
List of supported objective functions:
MOI.ObjectiveFunction{MOI.ScalarAffineFunction{T}}MOI.ObjectiveFunction{MOI.ScalarQuadraticFunction{T}}MOI.ObjectiveFunction{MOI.VariableIndex}
List of supported variable types:
List of supported constraint types:
MOI.ScalarAffineFunction{T}inMOI.EqualTo{T}MOI.ScalarAffineFunction{T}inMOI.GreaterThan{T}MOI.ScalarAffineFunction{T}inMOI.IntegerMOI.ScalarAffineFunction{T}inMOI.Interval{T}MOI.ScalarAffineFunction{T}inMOI.LessThan{T}MOI.ScalarAffineFunction{T}inMOI.ZeroOneMOI.VariableIndexinMOI.EqualTo{T}MOI.VariableIndexinMOI.GreaterThan{T}MOI.VariableIndexinMOI.IntegerMOI.VariableIndexinMOI.Interval{T}MOI.VariableIndexinMOI.LessThan{T}MOI.VariableIndexinMOI.Parameter{T}MOI.VariableIndexinMOI.Semicontinuous{T}MOI.VariableIndexinMOI.Semiinteger{T}MOI.VariableIndexinMOI.ZeroOneMOI.VectorOfVariablesinMOI.AllDifferentMOI.VectorOfVariablesinMOI.BinPacking{T}MOI.VectorOfVariablesinMOI.CircuitMOI.VectorOfVariablesinMOI.CountAtLeastMOI.VectorOfVariablesinMOI.CountBelongsMOI.VectorOfVariablesinMOI.CountDistinctMOI.VectorOfVariablesinMOI.CountGreaterThanMOI.VectorOfVariablesinMOI.CumulativeMOI.VectorOfVariablesinMOI.PathMOI.VectorOfVariablesinMOI.Table{T}
List of supported model attributes:
List of supported constraint attributes:
For an infeasible model, MOI.compute_conflict! finds a minimal
conflicting subset of constraints (an Irreducible Inconsistent Subsystem),
after which MOI.ConstraintConflictStatus reports which constraints
participate. For example, this model is infeasible because x[1] + x[2] cannot
be both >= 18 and <= 5:
model = MOI.Utilities.CachingOptimizer(
MiniZinc.Model{Int}(),
MiniZinc.Optimizer{Int}("chuffed"),
)
x = MOI.add_variables(model, 2)
MOI.add_constraint.(model, x, MOI.Interval(1, 10))
f = 1 * x[1] + 1 * x[2]
MOI.add_constraint(model, f, MOI.GreaterThan(18)) # x[1] + x[2] >= 18
MOI.add_constraint(model, f, MOI.LessThan(5)) # x[1] + x[2] <= 5
MOI.optimize!(model)
if MOI.get(model, MOI.TerminationStatus()) == MOI.INFEASIBLE
MOI.compute_conflict!(model)
if MOI.get(model, MOI.ConflictStatus()) == MOI.CONFLICT_FOUND
# Query each constraint you added to `model` for its participation.
# Variable bounds always read NOT_IN_CONFLICT (see below).
for (F, S) in MOI.get(model, MOI.ListOfConstraintTypesPresent())
for ci in MOI.get(model, MOI.ListOfConstraintIndices{F,S}())
status = MOI.get(model, MOI.ConstraintConflictStatus(), ci)
# status is MOI.IN_CONFLICT or MOI.NOT_IN_CONFLICT
end
end
end
endThis uses findMUS, which is not part of
the standard MiniZinc distribution; it is supplied by the FindMUS_jll
dependency, so no extra setup is required.
Conflicts cover modeling constraints only; variable bounds are folded into the variable declarations and never appear in a conflict.
Conflict analysis always uses the Chuffed subsolver, regardless of the solver
passed to MiniZinc.Optimizer, so a model outside Chuffed's support (for
example, one with floating-point variables) reports NO_CONFLICT_FOUND.
Set options using MOI.RawOptimizerAttribute in MOI or
set_attribute in JuMP.
MiniZinc.jl supports the following options:
-
model_filename::String = "": the location at which to write out the.mznfile during optimization. This option can be helpful during debugging. If left empty, a temporary file will be used instead. -
MOI.SolutionLimit: set this option to a positive integer to return up to thelimitnumber of solutions.