Skip to content

Commit c1ce388

Browse files
committed
Fix FEASIBILITY_SENSE cases
1 parent a5bbee7 commit c1ce388

File tree

2 files changed

+39
-11
lines changed

2 files changed

+39
-11
lines changed

src/Utilities/penalty_relaxation.jl

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -80,18 +80,32 @@ function MOI.supports(
8080
return false
8181
end
8282

83+
function _change_set_to_min_if_necessary(
84+
::Type{T},
85+
model::MOI.ModelLike,
86+
) where {T}
87+
sense = MOI.get(model, MOI.ObjectiveSense())
88+
if sense != MOI.FEASIBILITY_SENSE
89+
return sense
90+
end
91+
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
92+
f = zero(MOI.ScalarAffineFunction{T})
93+
MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f)
94+
return MOI.MIN_SENSE
95+
end
96+
8397
function MOI.modify(
8498
model::MOI.ModelLike,
8599
ci::MOI.ConstraintIndex{F,<:MOI.AbstractScalarSet},
86100
relax::ScalarPenaltyRelaxation{T},
87101
) where {T,F<:Union{MOI.ScalarAffineFunction{T},MOI.ScalarQuadraticFunction{T}}}
102+
sense = _change_set_to_min_if_necessary(T, model)
88103
y = MOI.add_variable(model)
89104
z = MOI.add_variable(model)
90105
MOI.add_constraint(model, y, MOI.GreaterThan(zero(T)))
91106
MOI.add_constraint(model, z, MOI.GreaterThan(zero(T)))
92107
MOI.modify(model, ci, MOI.ScalarCoefficientChange(y, one(T)))
93108
MOI.modify(model, ci, MOI.ScalarCoefficientChange(z, -one(T)))
94-
sense = MOI.get(model, MOI.ObjectiveSense())
95109
scale = sense == MOI.MIN_SENSE ? one(T) : -one(T)
96110
a = scale * relax.penalty
97111
O = MOI.get(model, MOI.ObjectiveFunctionType())
@@ -106,11 +120,11 @@ function MOI.modify(
106120
ci::MOI.ConstraintIndex{F,MOI.GreaterThan{T}},
107121
relax::ScalarPenaltyRelaxation{T},
108122
) where {T,F<:Union{MOI.ScalarAffineFunction{T},MOI.ScalarQuadraticFunction{T}}}
123+
sense = _change_set_to_min_if_necessary(T, model)
109124
# Performance optimization: we don't need the z relaxation variable.
110125
y = MOI.add_variable(model)
111126
MOI.add_constraint(model, y, MOI.GreaterThan(zero(T)))
112127
MOI.modify(model, ci, MOI.ScalarCoefficientChange(y, one(T)))
113-
sense = MOI.get(model, MOI.ObjectiveSense())
114128
scale = sense == MOI.MIN_SENSE ? one(T) : -one(T)
115129
a = scale * relax.penalty
116130
O = MOI.get(model, MOI.ObjectiveFunctionType())
@@ -124,11 +138,11 @@ function MOI.modify(
124138
ci::MOI.ConstraintIndex{F,MOI.LessThan{T}},
125139
relax::ScalarPenaltyRelaxation{T},
126140
) where {T,F<:Union{MOI.ScalarAffineFunction{T},MOI.ScalarQuadraticFunction{T}}}
141+
sense = _change_set_to_min_if_necessary(T, model)
127142
# Performance optimization: we don't need the y relaxation variable.
128143
z = MOI.add_variable(model)
129144
MOI.add_constraint(model, z, MOI.GreaterThan(zero(T)))
130145
MOI.modify(model, ci, MOI.ScalarCoefficientChange(z, -one(T)))
131-
sense = MOI.get(model, MOI.ObjectiveSense())
132146
scale = sense == MOI.MIN_SENSE ? one(T) : -one(T)
133147
a = scale * relax.penalty
134148
O = MOI.get(model, MOI.ObjectiveFunctionType())
@@ -266,12 +280,6 @@ function PenaltyRelaxation(
266280
end
267281

268282
function MOI.modify(model::MOI.ModelLike, relax::PenaltyRelaxation{T}) where {T}
269-
sense = MOI.get(model, MOI.ObjectiveSense())
270-
if sense == MOI.FEASIBILITY_SENSE
271-
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
272-
f = zero(MOI.ScalarAffineFunction{T})
273-
MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f)
274-
end
275283
map = Dict{MOI.ConstraintIndex,MOI.ScalarAffineFunction{T}}()
276284
for (F, S) in MOI.get(model, MOI.ListOfConstraintTypesPresent())
277285
_modify_penalty_relaxation(map, model, relax, F, S)

test/Utilities/penalty_relaxation.jl

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,7 @@ function test_default_nothing()
272272
map = MOI.modify(model, MOI.Utilities.PenaltyRelaxation(default = nothing))
273273
@test !haskey(map, c)
274274
@test sprint(print, model) === """
275-
Minimize ScalarAffineFunction{Float64}:
276-
0.0
275+
Feasibility
277276
278277
Subject to:
279278
@@ -336,6 +335,27 @@ function test_caching_optimizer()
336335
return
337336
end
338337

338+
function test_scalar_penalty_relaxation()
339+
model = MOI.Utilities.Model{Float64}()
340+
x = MOI.add_variable(model)
341+
c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0))
342+
f = MOI.modify(model, c, MOI.Utilities.ScalarPenaltyRelaxation(2.0))
343+
@test f isa MOI.ScalarAffineFunction{Float64}
344+
@test sprint(print, model) === """
345+
Minimize ScalarAffineFunction{Float64}:
346+
0.0 + 2.0 v[2]
347+
348+
Subject to:
349+
350+
ScalarAffineFunction{Float64}-in-LessThan{Float64}
351+
0.0 + 1.0 v[1] - 1.0 v[2] <= 2.0
352+
353+
VariableIndex-in-GreaterThan{Float64}
354+
v[2] >= 0.0
355+
"""
356+
return
339357
end
340358

359+
end # module
360+
341361
TestPenaltyRelaxation.runtests()

0 commit comments

Comments
 (0)