Skip to content

Commit 6a536fd

Browse files
committed
Allow using MiniZincSet from JuMP
1 parent 7484893 commit 6a536fd

File tree

3 files changed

+105
-7
lines changed

3 files changed

+105
-7
lines changed

src/MiniZinc.jl

Lines changed: 9 additions & 0 deletions
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,

src/write.jl

Lines changed: 12 additions & 7 deletions
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

test/examples/packing.jl

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Inspired from the square packing tutorial in https://www.minizinc.org/
2+
function test_packing()
3+
# Number of squares
4+
n = 6
5+
# Size of each square
6+
sizes = collect(1:n)
7+
upper_bound = sum(sizes)
8+
9+
model = MOI.instantiate(
10+
() -> MiniZinc.Optimizer{Int}("chuffed");
11+
with_cache_type = Int,
12+
with_bridge_type = Int,
13+
)
14+
15+
# We need this `s` variable that is trivially equal to `sizes`
16+
# because `MiniZincSet` only does not take constants
17+
s = [MOI.add_constrained_variable(model, MOI.Integer())[1] for i in 1:n]
18+
x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for i in 1:n]
19+
y = [MOI.add_constrained_variable(model, MOI.Integer())[1] for i in 1:n]
20+
max_x, _ = MOI.add_constrained_variable(model, MOI.Integer())
21+
max_y, _ = MOI.add_constrained_variable(model, MOI.Integer())
22+
23+
for i in 1:n
24+
MOI.add_constraint(
25+
model,
26+
s[i],
27+
MOI.EqualTo(sizes[i]),
28+
)
29+
MOI.add_constraint(
30+
model,
31+
x[i],
32+
MOI.Interval(1, upper_bound),
33+
)
34+
MOI.add_constraint(
35+
model,
36+
y[i],
37+
MOI.Interval(1, upper_bound),
38+
)
39+
end
40+
MOI.add_constraint(
41+
model,
42+
max_x,
43+
MOI.Interval(1, upper_bound),
44+
)
45+
MOI.add_constraint(
46+
model,
47+
max_y,
48+
MOI.Interval(1, upper_bound),
49+
)
50+
51+
for i in 1:n
52+
MOI.add_constraint(
53+
model,
54+
1max_x - 1x[i],
55+
MOI.GreaterThan(sizes[i]),
56+
)
57+
MOI.add_constraint(
58+
model,
59+
1max_y - 1y[i],
60+
MOI.GreaterThan(sizes[i]),
61+
)
62+
end
63+
64+
MOI.add_constraint(
65+
model,
66+
[x; y; s; s],
67+
MiniZinc.MiniZincSet(
68+
"diffn",
69+
[1:n, n .+ (1:n), 2n .+ (1:n), 3n .+ (1:n)],
70+
),
71+
)
72+
73+
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
74+
obj = (1max_x) * max_y
75+
MOI.set(model, MOI.ObjectiveFunction{typeof(obj)}(), obj)
76+
77+
MOI.optimize!(model)
78+
79+
@test MOI.get(model, MOI.TerminationStatus()) === MOI.OPTIMAL
80+
@test MOI.get(model, MOI.PrimalStatus()) === MOI.FEASIBLE_POINT
81+
@test MOI.get(model, MOI.ResultCount()) == 1
82+
@test MOI.get(model, MOI.ObjectiveValue()) == 120
83+
return
84+
end

0 commit comments

Comments
 (0)