Skip to content
This repository was archived by the owner on Jun 14, 2020. It is now read-only.

Commit 6f0fdd6

Browse files
committed
Protect against weird bounds combinations
1 parent 11fb079 commit 6f0fdd6

File tree

1 file changed

+41
-10
lines changed

1 file changed

+41
-10
lines changed

src/constraints/singlevariable.jl

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,30 @@ function setvariablebound!(m::LinQuadOptimizer, v::SinVar, set::IV)
4040
setvariablebound!(m, getcol(m, v), set.lower, backend_type(m, Val{:Lowerbound}()))
4141
end
4242

43+
SVCI(v::SinVar, ::S) where S = SVCI{S}(v.variable.value)
44+
45+
function checkexisting(m::LinQuadOptimizer, v::SinVar, set::S) where S
46+
ref = SVCI(v, set)
47+
if haskey(constrdict(m, ref), ref)
48+
error("Adding the same constraint type: $(S) is not allowed for SingleVariable function")
49+
end
50+
end
51+
52+
function checkconflicting(m::LinQuadOptimizer, v::SinVar, set_to_add::S0, set_to_test::S) where S where S0
53+
ref = SVCI(v, set_to_test)
54+
if haskey(constrdict(m, ref), ref)
55+
error("Adding the same constraint type: $(S0) is not allowed for SingleVariable function because there is constraint of type $(S) tied to the respective variable")
56+
end
57+
end
58+
4359
# add constraint
4460
function MOI.addconstraint!(m::LinQuadOptimizer, v::SinVar, set::S) where S <: LinSets
61+
checkexisting(m, v, set)
62+
checkconflicting(m, v, set, MOI.Semicontinuous(0.0, 0.0))
63+
checkconflicting(m, v, set, MOI.Semiinteger(0.0, 0.0))
64+
checkconflicting(m, v, set, MOI.ZeroOne())
4565
setvariablebound!(m, v, set)
46-
m.last_constraint_reference += 1
47-
ref = SVCI{S}(m.last_constraint_reference)
66+
ref = SVCI(v, set)
4867
dict = constrdict(m, ref)
4968
dict[ref] = v.variable
5069
ref
@@ -105,8 +124,11 @@ we can revert to the old bounds
105124
Xpress is worse, once binary, the bounds are changed independently of what the user does
106125
=#
107126
function MOI.addconstraint!(m::LinQuadOptimizer, v::SinVar, set::MOI.ZeroOne)
108-
m.last_constraint_reference += 1
109-
ref = SVCI{MOI.ZeroOne}(m.last_constraint_reference)
127+
checkexisting(m, v, set)
128+
checkconflicting(m, v, set, MOI.Integer())
129+
checkconflicting(m, v, set, MOI.Semicontinuous(0.0, 0.0))
130+
checkconflicting(m, v, set, MOI.Semiinteger(0.0, 0.0))
131+
ref = SVCI(v, set)
110132
dict = constrdict(m, ref)
111133
ub = get_variable_upperbound(m, getcol(m, v))
112134
lb = get_variable_lowerbound(m, getcol(m, v))
@@ -143,9 +165,12 @@ MOI.get(m::LinQuadOptimizer, ::MOI.ConstraintFunction, c::SVCI{MOI.ZeroOne}) = S
143165
=#
144166

145167
function MOI.addconstraint!(m::LinQuadOptimizer, v::SinVar, set::MOI.Integer)
168+
checkexisting(m, v, set)
169+
checkconflicting(m, v, set, MOI.ZeroOne())
170+
checkconflicting(m, v, set, MOI.Semicontinuous(0.0, 0.0))
171+
checkconflicting(m, v, set, MOI.Semiinteger(0.0, 0.0))
146172
change_variable_types!(m, [getcol(m, v)], [backend_type(m, set)])
147-
m.last_constraint_reference += 1
148-
ref = SVCI{MOI.Integer}(m.last_constraint_reference)
173+
ref = SVCI(v, set)
149174
dict = constrdict(m, ref)
150175
dict[ref] = v.variable
151176
make_problem_type_integer(m)
@@ -174,13 +199,19 @@ MOI.get(m::LinQuadOptimizer, ::MOI.ConstraintFunction, c::SVCI{MOI.Integer}) = S
174199
Semicontinuous / Semiinteger constraints
175200
=#
176201
const SEMI_TYPES = Union{MOI.Semicontinuous{Float64}, MOI.Semiinteger{Float64}}
177-
function MOI.addconstraint!(m::LinQuadOptimizer, v::SinVar, set::SEMI_TYPES)
202+
function MOI.addconstraint!(m::LinQuadOptimizer, v::SinVar, set::S) where S <: SEMI_TYPES
203+
checkexisting(m, v, set)
204+
checkconflicting(m, v, set, MOI.ZeroOne())
205+
checkconflicting(m, v, set, MOI.Integer())
206+
if S == MOI.Semicontinuous{Float64}
207+
checkconflicting(m, v, set, MOI.Semiinteger(0.0, 0.0))
208+
else
209+
checkconflicting(m, v, set, MOI.Semicontinuous(0.0, 0.0))
210+
end
178211
change_variable_types!(m, [getcol(m, v)], [backend_type(m, set)])
179212
setvariablebound!(m, getcol(m, v), set.upper, backend_type(m, Val{:Upperbound}()))
180213
setvariablebound!(m, getcol(m, v), set.lower, backend_type(m, Val{:Lowerbound}()))
181-
182-
m.last_constraint_reference += 1
183-
ref = SVCI{typeof(set)}(m.last_constraint_reference)
214+
ref = SVCI(v, set)
184215
dict = constrdict(m, ref)
185216
dict[ref] = v.variable
186217
make_problem_type_integer(m)

0 commit comments

Comments
 (0)