Skip to content

Commit e359b29

Browse files
authored
Allow using MiniZincSet from JuMP (#82)
1 parent 7484893 commit e359b29

File tree

4 files changed

+78
-7
lines changed

4 files changed

+78
-7
lines changed

Diff for: src/MiniZinc.jl

+9
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,20 @@ const ReifiedEqualTo{T} = MOI.Reified{MOI.EqualTo{T}}
1515
const ReifiedBinPacking{T} = MOI.Reified{MOI.BinPacking{T}}
1616
const ReifiedTable{T} = MOI.Reified{MOI.Table{T}}
1717

18+
struct MiniZincSet <: MOI.AbstractVectorSet
19+
name::String
20+
fields::Vector{Union{Int,UnitRange{Int}}}
21+
end
22+
23+
MOI.dimension(set::MiniZincSet) = maximum(maximum, set.fields)
24+
Base.copy(set::MiniZincSet) = set
25+
1826
MOI.Utilities.@model(
1927
Model,
2028
(MOI.ZeroOne, MOI.Integer, MOI.EqualTo{Bool}),
2129
(MOI.EqualTo, MOI.GreaterThan, MOI.LessThan, MOI.Interval),
2230
(
31+
MiniZincSet,
2332
MOI.AllDifferent,
2433
MOI.Circuit,
2534
MOI.CountAtLeast,

Diff for: src/write.jl

+12-7
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,17 @@ function _to_string(
149149
return ret
150150
end
151151

152-
struct MiniZincSet <: MOI.AbstractSet
153-
name::String
154-
fields::Vector{Union{Int,UnitRange{Int}}}
152+
function _write_constraint(
153+
io::IO,
154+
predicates::Set,
155+
variables::Dict,
156+
f::MOI.VectorOfVariables,
157+
mzn::MiniZincSet,
158+
)
159+
strs = [_to_string(variables, f.variables[field]) for field in mzn.fields]
160+
println(io, "constraint $(mzn.name)(", join(strs, ", "), ");")
161+
push!(predicates, mzn.name)
162+
return
155163
end
156164

157165
function _write_constraint(
@@ -167,10 +175,7 @@ function _write_constraint(
167175
MOI.Circuit,
168176
},
169177
)
170-
mzn = MiniZincSet(s)
171-
strs = [_to_string(variables, f.variables[field]) for field in mzn.fields]
172-
println(io, "constraint $(mzn.name)(", join(strs, ", "), ");")
173-
push!(predicates, mzn.name)
178+
_write_constraint(io, predicates, variables, f, MiniZincSet(s))
174179
return
175180
end
176181

Diff for: test/examples/packing.jl

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Copyright (c) 2022 MiniZinc.jl contributors
2+
#
3+
# Use of this source code is governed by an MIT-style license that can be found
4+
# in the LICENSE.md file or at https://opensource.org/licenses/MIT.
5+
6+
# Inspired from the square packing tutorial in https://www.minizinc.org/
7+
function test_packing()
8+
n = 6
9+
sizes = collect(1:n)
10+
upper_bound = sum(sizes)
11+
model = MOI.instantiate(
12+
() -> MiniZinc.Optimizer{Int}("chuffed");
13+
with_cache_type = Int,
14+
with_bridge_type = Int,
15+
)
16+
MOI.set(model, MOI.RawOptimizerAttribute("model_filename"), "test.mzn")
17+
# We need this `s` variable that is trivially equal to `sizes`
18+
# because `MiniZincSet` supports only VectorOfVariables
19+
s = [MOI.add_constrained_variable(model, MOI.Integer())[1] for i in 1:n]
20+
x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for i in 1:n]
21+
y = [MOI.add_constrained_variable(model, MOI.Integer())[1] for i in 1:n]
22+
max_x, _ = MOI.add_constrained_variable(model, MOI.Integer())
23+
max_y, _ = MOI.add_constrained_variable(model, MOI.Integer())
24+
MOI.add_constraint.(model, s, MOI.EqualTo.(sizes))
25+
MOI.add_constraint.(model, x, MOI.Interval(1, upper_bound))
26+
MOI.add_constraint.(model, y, MOI.Interval(1, upper_bound))
27+
MOI.add_constraint(model, max_x, MOI.Interval(1, upper_bound))
28+
MOI.add_constraint(model, max_y, MOI.Interval(1, upper_bound))
29+
MOI.add_constraint.(model, 1max_x .- 1x, MOI.GreaterThan.(sizes))
30+
MOI.add_constraint.(model, 1max_y .- 1y, MOI.GreaterThan.(sizes))
31+
MOI.add_constraint(
32+
model,
33+
MOI.VectorOfVariables([x; y; s; s]),
34+
MiniZinc.MiniZincSet(
35+
"diffn",
36+
[1:n, n .+ (1:n), 2n .+ (1:n), 3n .+ (1:n)],
37+
),
38+
)
39+
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
40+
obj = (1max_x) * max_y
41+
MOI.set(model, MOI.ObjectiveFunction{typeof(obj)}(), obj)
42+
MOI.optimize!(model)
43+
@test MOI.get(model, MOI.TerminationStatus()) === MOI.OPTIMAL
44+
@test MOI.get(model, MOI.PrimalStatus()) === MOI.FEASIBLE_POINT
45+
@test MOI.get(model, MOI.ResultCount()) == 1
46+
@test MOI.get(model, MOI.ObjectiveValue()) == 120
47+
rm("test.mzn")
48+
return
49+
end

Diff for: test/runtests.jl

+8
Original file line numberDiff line numberDiff line change
@@ -1696,6 +1696,14 @@ function test_integer_bounds_less_than_than()
16961696
index_map, _ = MOI.optimize!(mzn, model)
16971697
@test MOI.get(mzn, MOI.TerminationStatus()) == MOI.OPTIMAL
16981698
@test MOI.get(mzn, MOI.VariablePrimal(), index_map[x]) == 1
1699+
end
1700+
1701+
function test_minizincset()
1702+
set = MiniZinc.MiniZincSet("diffn", [1:2, 3:4, 5:6, 7:8])
1703+
@test MOI.dimension(set) == 8
1704+
model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())
1705+
x, _ = MOI.add_constrained_variables(model, set)
1706+
@test length(x) == 8
16991707
return
17001708
end
17011709

0 commit comments

Comments
 (0)