@@ -21,8 +21,7 @@ constraint.
21
21
The penalty relaxation modifies constraints of the form ``f(x) \\ in S`` into
22
22
``f(x) + y - z \\ in S``, where ``y, z \\ ge 0``, and then it introduces a penalty
23
23
term into the objective of ``a \\ times (y + z)`` (if minimizing, else ``-a``),
24
- where `a` is the value in the `penalties` dictionary associated with the
25
- constraint that is being relaxed. If no value exists, the default is `default`.
24
+ where ``a`` is `penalty`
26
25
27
26
When `S` is [`MOI.LessThan`](@ref) or [`MOI.GreaterThan`](@ref), we omit `y` or
28
27
`z` respectively as a performance optimization.
@@ -60,26 +59,14 @@ julia> f isa MOI.ScalarAffineFunction{Float64}
60
59
true
61
60
```
62
61
"""
63
- struct ScalarPenaltyRelaxation{T}
62
+ struct ScalarPenaltyRelaxation{T} # <: MOI.AbstractFunctionModification
63
+ # We don't make this a subtype of AbstractFunctionModification to avoid some
64
+ # ambiguities with generic methods in Utilities and Bridges. The underlying
65
+ # reason is that these reformulations can be written using the high-level
66
+ # MOI API, so we don't need special handling for bridges and utilities.
64
67
penalty:: T
65
68
end
66
69
67
- function MOI. supports (
68
- :: MOI.ModelLike ,
69
- :: ScalarPenaltyRelaxation{T} ,
70
- :: Type{<:MOI.ConstraintIndex{F,<:MOI.AbstractScalarSet}} ,
71
- ) where {T,F<: Union{MOI.ScalarAffineFunction{T},MOI.ScalarQuadraticFunction{T}} }
72
- return true
73
- end
74
-
75
- function MOI. supports (
76
- :: MOI.ModelLike ,
77
- :: ScalarPenaltyRelaxation ,
78
- :: Type{<:MOI.ConstraintIndex} ,
79
- )
80
- return false
81
- end
82
-
83
70
function _change_set_to_min_if_necessary (
84
71
:: Type{T} ,
85
72
model:: MOI.ModelLike ,
@@ -94,6 +81,15 @@ function _change_set_to_min_if_necessary(
94
81
return MOI. MIN_SENSE
95
82
end
96
83
84
+ function MOI. modify (
85
+ :: MOI.ModelLike ,
86
+ :: MOI.ConstraintIndex ,
87
+ :: ScalarPenaltyRelaxation ,
88
+ )
89
+ # A generic fallback if modification is not supported.
90
+ return nothing
91
+ end
92
+
97
93
function MOI. modify (
98
94
model:: MOI.ModelLike ,
99
95
ci:: MOI.ConstraintIndex{F,<:MOI.AbstractScalarSet} ,
@@ -167,17 +163,13 @@ modifies the model in-place to create a penalized relaxation of the constraints.
167
163
168
164
## Reformulation
169
165
170
- The penalty relaxation modifies constraints of the form ``f(x) \\ in S`` into
171
- ``f(x) + y - z \\ in S``, where ``y, z \\ ge 0``, and then it introduces a penalty
172
- term into the objective of ``a \\ times (y + z)`` (if minimizing, else ``-a``),
173
- where `a` is the value in the `penalties` dictionary associated with the
174
- constraint that is being relaxed.
166
+ See [`Utilities.ScalarPenaltyRelaxation`](@ref) for details of the
167
+ reformulation.
175
168
176
- If no value exists for the constraint in `penalties`, the penalty is `default`.
177
- If `default` is also `nothing`, then the constraint is skipped.
178
-
179
- When `S` is [`MOI.LessThan`](@ref) or [`MOI.GreaterThan`](@ref), we omit `y` or
180
- `z` respectively as a performance optimization.
169
+ For each constraint `ci`, the penalty passed to [`Utilities.ScalarPenaltyRelaxation`](@ref)
170
+ is `get(penalties, ci, default)`. If the value is `nothing`, because `ci` does
171
+ not exist in `penalties` and `default = nothing`, then the constraint is
172
+ skipped.
181
173
182
174
## Return value
183
175
@@ -299,12 +291,12 @@ function _modify_penalty_relaxation(
299
291
if penalty === nothing
300
292
continue
301
293
end
302
- attr = ScalarPenaltyRelaxation (penalty)
303
- if ! MOI . supports (model, attr, MOI . ConstraintIndex{F,S})
304
- @warn (" Skipping PenaltyRelaxation of constraints of type $F -in-$S " )
294
+ delta = MOI . modify (model, ci, ScalarPenaltyRelaxation (penalty) )
295
+ if delta === nothing
296
+ @warn (" Skipping PenaltyRelaxation for constraints of type $F -in-$S " )
305
297
return
306
298
end
307
- map[ci] = MOI . modify (model, ci, attr)
299
+ map[ci] = delta
308
300
end
309
- return map
301
+ return
310
302
end
0 commit comments