Skip to content

Commit 9ba623e

Browse files
authored
Add Reified set and MILP bridges (#1955)
1 parent fd8ca78 commit 9ba623e

File tree

10 files changed

+943
-0
lines changed

10 files changed

+943
-0
lines changed

docs/src/reference/standard_form.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ CountDistinct
109109
CountGreaterThan
110110
Cumulative
111111
Path
112+
Reified
112113
Table
113114
```
114115

docs/src/submodules/Bridges/list_of_bridges.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,13 @@ Bridges.Constraint.IndicatorSOS1Bridge
5959
Bridges.Constraint.SemiToBinaryBridge
6060
Bridges.Constraint.ZeroOneBridge
6161
Bridges.Constraint.AllDifferentToCountDistinctBridge
62+
Bridges.Constraint.ReifiedAllDifferentToCountDistinctBridge
6263
Bridges.Constraint.BinPackingToMILPBridge
6364
Bridges.Constraint.CircuitToMILPBridge
6465
Bridges.Constraint.CountAtLeastToCountBelongsBridge
6566
Bridges.Constraint.CountBelongsToMILPBridge
6667
Bridges.Constraint.CountDistinctToMILPBridge
68+
Bridges.Constraint.ReifiedCountDistinctToMILPBridge
6769
Bridges.Constraint.CountGreaterThanToMILPBridge
6870
Bridges.Constraint.TableToMILPBridge
6971
```

src/Bridges/Constraint/Constraint.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ include("set_map.jl")
2020
include("single_bridge_optimizer.jl")
2121

2222
include("bridges/all_different.jl")
23+
include("bridges/all_different_reif.jl")
2324
include("bridges/bin_packing.jl")
2425
include("bridges/circuit.jl")
2526
include("bridges/count_at_least.jl")
2627
include("bridges/count_belongs.jl")
2728
include("bridges/count_distinct.jl")
29+
include("bridges/count_distinct_reif.jl")
2830
include("bridges/count_greater_than.jl")
2931
include("bridges/det.jl")
3032
include("bridges/flip_sign.jl")
@@ -112,11 +114,16 @@ function add_all_bridges(bridged_model, ::Type{T}) where {T}
112114
MOI.Bridges.add_bridge(bridged_model, ZeroOneBridge{T})
113115
# Constraint programming bridges
114116
MOI.Bridges.add_bridge(bridged_model, AllDifferentToCountDistinctBridge{T})
117+
MOI.Bridges.add_bridge(
118+
bridged_model,
119+
ReifiedAllDifferentToCountDistinctBridge{T},
120+
)
115121
MOI.Bridges.add_bridge(bridged_model, BinPackingToMILPBridge{T})
116122
MOI.Bridges.add_bridge(bridged_model, CircuitToMILPBridge{T})
117123
MOI.Bridges.add_bridge(bridged_model, CountAtLeastToCountBelongsBridge{T})
118124
MOI.Bridges.add_bridge(bridged_model, CountBelongsToMILPBridge{T})
119125
MOI.Bridges.add_bridge(bridged_model, CountDistinctToMILPBridge{T})
126+
MOI.Bridges.add_bridge(bridged_model, ReifiedCountDistinctToMILPBridge{T})
120127
MOI.Bridges.add_bridge(bridged_model, CountGreaterThanToMILPBridge{T})
121128
MOI.Bridges.add_bridge(bridged_model, TableToMILPBridge{T})
122129
return
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
# Copyright (c) 2017: Miles Lubin and contributors
2+
# Copyright (c) 2017: Google Inc.
3+
#
4+
# Use of this source code is governed by an MIT-style license that can be found
5+
# in the LICENSE.md file or at https://opensource.org/licenses/MIT.
6+
7+
"""
8+
ReifiedAllDifferentToCountDistinctBridge{T,F} <:
9+
Bridges.Constraint.AbstractBridge
10+
11+
`ReifiedAllDifferentToCountDistinctBridge` implements the following
12+
reformulations:
13+
14+
* ``r \\iff x \\in \\textsf{AllDifferent}(d)`` to
15+
``r \\iff (n, x) \\in \\textsf{CountDistinct}(1+d)`` and ``n = d``
16+
* ``r \\iff f(x) \\in \\textsf{AllDifferent}(d)`` to
17+
``r \\iff (d, f(x)) \\in \\textsf{CountDistinct}(1+d)``
18+
19+
## Source node
20+
21+
`ReifiedAllDifferentToCountDistinctBridge` supports:
22+
23+
* `F` in [`MOI.Reified{MOI.AllDifferent}`](@ref)
24+
25+
where `F` is [`MOI.VectorOfVariables`](@ref) or
26+
[`MOI.VectorAffineFunction{T}`](@ref).
27+
28+
## Target nodes
29+
30+
`ReifiedAllDifferentToCountDistinctBridge` creates:
31+
32+
* `F` in [`MOI.Reified{MOI.CountDistinct}`](@ref)
33+
* [`MOI.VariableIndex`](@ref) in [`MOI.EqualTo{T}`](@ref)
34+
"""
35+
mutable struct ReifiedAllDifferentToCountDistinctBridge{
36+
T,
37+
F<:Union{MOI.VectorOfVariables,MOI.VectorAffineFunction{T}},
38+
} <: AbstractBridge
39+
f::F
40+
y::Union{Nothing,MOI.VariableIndex}
41+
ci::MOI.ConstraintIndex{F,MOI.Reified{MOI.CountDistinct}}
42+
43+
function ReifiedAllDifferentToCountDistinctBridge{T}(
44+
f::MOI.VectorOfVariables,
45+
y::MOI.VariableIndex,
46+
ci::MOI.ConstraintIndex{
47+
MOI.VectorOfVariables,
48+
MOI.Reified{MOI.CountDistinct},
49+
},
50+
) where {T}
51+
return new{T,MOI.VectorOfVariables}(f, y, ci)
52+
end
53+
54+
function ReifiedAllDifferentToCountDistinctBridge{T}(
55+
f::MOI.VectorAffineFunction{T},
56+
ci::MOI.ConstraintIndex{
57+
MOI.VectorAffineFunction{T},
58+
MOI.Reified{MOI.CountDistinct},
59+
},
60+
) where {T}
61+
return new{T,MOI.VectorAffineFunction{T}}(f, nothing, ci)
62+
end
63+
end
64+
65+
const ReifiedAllDifferentToCountDistinct{T,OT<:MOI.ModelLike} =
66+
SingleBridgeOptimizer{ReifiedAllDifferentToCountDistinctBridge{T},OT}
67+
68+
function bridge_constraint(
69+
::Type{ReifiedAllDifferentToCountDistinctBridge{T,F}},
70+
model::MOI.ModelLike,
71+
f::F,
72+
s::MOI.Reified{MOI.AllDifferent},
73+
) where {T,F<:MOI.VectorOfVariables}
74+
d = MOI.output_dimension(f)
75+
y, _ = MOI.add_constrained_variable(model, MOI.EqualTo(T(d - 1)))
76+
scalars = MOI.Utilities.eachscalar(f)
77+
ci = MOI.add_constraint(
78+
model,
79+
MOI.Utilities.operate(vcat, T, scalars[1], y, scalars[2:end]),
80+
MOI.Reified(MOI.CountDistinct(d)),
81+
)
82+
return ReifiedAllDifferentToCountDistinctBridge{T}(f, y, ci)
83+
end
84+
85+
function bridge_constraint(
86+
::Type{ReifiedAllDifferentToCountDistinctBridge{T,F}},
87+
model::MOI.ModelLike,
88+
f::F,
89+
s::MOI.Reified{MOI.AllDifferent},
90+
) where {T,F<:MOI.VectorAffineFunction{T}}
91+
d = MOI.output_dimension(f)
92+
scalars = MOI.Utilities.eachscalar(f)
93+
ci = MOI.add_constraint(
94+
model,
95+
MOI.Utilities.operate(vcat, T, scalars[1], T(d - 1), scalars[2:end]),
96+
MOI.Reified(MOI.CountDistinct(d)),
97+
)
98+
return ReifiedAllDifferentToCountDistinctBridge{T}(f, ci)
99+
end
100+
101+
function MOI.supports_constraint(
102+
::Type{<:ReifiedAllDifferentToCountDistinctBridge{T}},
103+
::Type{<:Union{MOI.VectorOfVariables,MOI.VectorAffineFunction{T}}},
104+
::Type{MOI.Reified{MOI.AllDifferent}},
105+
) where {T}
106+
return true
107+
end
108+
109+
function MOI.Bridges.added_constrained_variable_types(
110+
::Type{ReifiedAllDifferentToCountDistinctBridge{T,MOI.VectorOfVariables}},
111+
) where {T}
112+
return Tuple{Type}[(MOI.EqualTo{T},)]
113+
end
114+
115+
function MOI.Bridges.added_constrained_variable_types(
116+
::Type{
117+
ReifiedAllDifferentToCountDistinctBridge{T,MOI.VectorAffineFunction{T}},
118+
},
119+
) where {T}
120+
return Tuple{Type}[]
121+
end
122+
123+
function MOI.Bridges.added_constraint_types(
124+
::Type{ReifiedAllDifferentToCountDistinctBridge{T,F}},
125+
) where {T,F}
126+
return Tuple{Type,Type}[(F, MOI.Reified{MOI.CountDistinct}),]
127+
end
128+
129+
function concrete_bridge_type(
130+
::Type{<:ReifiedAllDifferentToCountDistinctBridge{T}},
131+
::Type{F},
132+
::Type{MOI.Reified{MOI.AllDifferent}},
133+
) where {T,F<:Union{MOI.VectorOfVariables,MOI.VectorAffineFunction{T}}}
134+
return ReifiedAllDifferentToCountDistinctBridge{T,F}
135+
end
136+
137+
function MOI.get(
138+
::MOI.ModelLike,
139+
::MOI.ConstraintFunction,
140+
bridge::ReifiedAllDifferentToCountDistinctBridge,
141+
)
142+
return bridge.f
143+
end
144+
145+
function MOI.get(
146+
::MOI.ModelLike,
147+
::MOI.ConstraintSet,
148+
bridge::ReifiedAllDifferentToCountDistinctBridge,
149+
)
150+
return MOI.Reified(MOI.AllDifferent(MOI.output_dimension(bridge.f) - 1))
151+
end
152+
153+
function MOI.delete(
154+
model::MOI.ModelLike,
155+
bridge::ReifiedAllDifferentToCountDistinctBridge,
156+
)
157+
MOI.delete(model, bridge.ci)
158+
if bridge.y !== nothing
159+
MOI.delete(model, bridge.y)
160+
end
161+
return
162+
end
163+
164+
function MOI.get(
165+
bridge::ReifiedAllDifferentToCountDistinctBridge,
166+
::MOI.NumberOfVariables,
167+
)::Int64
168+
if bridge.y === nothing
169+
return 0
170+
end
171+
return 1
172+
end
173+
174+
function MOI.get(
175+
bridge::ReifiedAllDifferentToCountDistinctBridge,
176+
::MOI.ListOfVariableIndices,
177+
)::Vector{MOI.VariableIndex}
178+
if bridge.y === nothing
179+
return MOI.VariableIndex[]
180+
end
181+
return [bridge.y]
182+
end
183+
184+
function MOI.get(
185+
bridge::ReifiedAllDifferentToCountDistinctBridge{T},
186+
::MOI.NumberOfConstraints{MOI.VariableIndex,MOI.EqualTo{T}},
187+
)::Int64 where {T}
188+
if bridge.y === nothing
189+
return 0
190+
end
191+
return 1
192+
end
193+
194+
function MOI.get(
195+
bridge::ReifiedAllDifferentToCountDistinctBridge{T},
196+
::MOI.ListOfConstraintIndices{MOI.VariableIndex,MOI.EqualTo{T}},
197+
) where {T}
198+
if bridge.y === nothing
199+
return MOI.ConstraintIndex{MOI.VariableIndex,MOI.EqualTo{T}}[]
200+
end
201+
ci = MOI.ConstraintIndex{MOI.VariableIndex,MOI.EqualTo{T}}(bridge.y.value)
202+
return [ci]
203+
end
204+
205+
function MOI.get(
206+
::ReifiedAllDifferentToCountDistinctBridge{T,F},
207+
::MOI.NumberOfConstraints{F,MOI.Reified{MOI.CountDistinct}},
208+
)::Int64 where {T,F}
209+
return 1
210+
end
211+
212+
function MOI.get(
213+
bridge::ReifiedAllDifferentToCountDistinctBridge{T,F},
214+
::MOI.ListOfConstraintIndices{F,MOI.Reified{MOI.CountDistinct}},
215+
) where {T,F}
216+
return [bridge.ci]
217+
end

0 commit comments

Comments
 (0)