@@ -81,6 +81,43 @@ function _change_sense_to_min_if_necessary(
8181 return MOI. MIN_SENSE
8282end
8383
84+ function _add_penalty_to_objective (
85+ model:: MOI.ModelLike ,
86+ :: Type{F} ,
87+ penalty:: T ,
88+ x:: Vector{MOI.VariableIndex} ,
89+ ) where {T,F<: MOI.VariableIndex }
90+ g = MOI. ScalarAffineFunction (MOI. ScalarAffineTerm .(penalty, x), zero (T))
91+ f = MOI. get (model, MOI. ObjectiveFunction {F} ())
92+ push! (g. terms, MOI. ScalarAffineTerm (one (T), f))
93+ MOI. set (model, MOI. ObjectiveFunction {typeof(g)} (), g)
94+ return MOI. ScalarAffineFunction (MOI. ScalarAffineTerm .(one (T), x), zero (T))
95+ end
96+
97+ function _add_penalty_to_objective (
98+ model:: MOI.ModelLike ,
99+ :: Type{F} ,
100+ penalty:: T ,
101+ x:: Vector{MOI.VariableIndex} ,
102+ ) where {T,F<: Union{MOI.ScalarAffineFunction{T},MOI.ScalarQuadraticFunction{T}} }
103+ obj = MOI. ObjectiveFunction {F} ()
104+ for xi in x
105+ MOI. modify (model, obj, MOI. ScalarCoefficientChange (xi, penalty))
106+ end
107+ return MOI. ScalarAffineFunction (MOI. ScalarAffineTerm .(one (T), x), zero (T))
108+ end
109+
110+ function _add_penalty_to_objective (
111+ :: MOI.ModelLike ,
112+ :: Type{F} ,
113+ :: T ,
114+ :: Vector{MOI.VariableIndex} ,
115+ ) where {T,F}
116+ return error (
117+ " Cannot perform `ScalarPenaltyRelaxation` with an objective function of type `$F `" ,
118+ )
119+ end
120+
84121function MOI. modify (
85122 model:: MOI.ModelLike ,
86123 ci:: MOI.ConstraintIndex{F,<:MOI.AbstractScalarSet} ,
@@ -93,13 +130,9 @@ function MOI.modify(
93130 MOI. add_constraint (model, z, MOI. GreaterThan (zero (T)))
94131 MOI. modify (model, ci, MOI. ScalarCoefficientChange (y, one (T)))
95132 MOI. modify (model, ci, MOI. ScalarCoefficientChange (z, - one (T)))
96- scale = sense == MOI. MIN_SENSE ? one (T) : - one (T)
97- a = scale * relax. penalty
133+ penalty = sense == MOI. MIN_SENSE ? relax. penalty : - relax. penalty
98134 O = MOI. get (model, MOI. ObjectiveFunctionType ())
99- obj = MOI. ObjectiveFunction {O} ()
100- MOI. modify (model, obj, MOI. ScalarCoefficientChange (y, a))
101- MOI. modify (model, obj, MOI. ScalarCoefficientChange (z, a))
102- return one (T) * y + one (T) * z
135+ return _add_penalty_to_objective (model, O, penalty, [y, z])
103136end
104137
105138function MOI. modify (
@@ -112,12 +145,9 @@ function MOI.modify(
112145 y = MOI. add_variable (model)
113146 MOI. add_constraint (model, y, MOI. GreaterThan (zero (T)))
114147 MOI. modify (model, ci, MOI. ScalarCoefficientChange (y, one (T)))
115- scale = sense == MOI. MIN_SENSE ? one (T) : - one (T)
116- a = scale * relax. penalty
148+ penalty = sense == MOI. MIN_SENSE ? relax. penalty : - relax. penalty
117149 O = MOI. get (model, MOI. ObjectiveFunctionType ())
118- obj = MOI. ObjectiveFunction {O} ()
119- MOI. modify (model, obj, MOI. ScalarCoefficientChange (y, a))
120- return one (T) * y
150+ return _add_penalty_to_objective (model, O, penalty, [y])
121151end
122152
123153function MOI. modify (
@@ -130,42 +160,28 @@ function MOI.modify(
130160 z = MOI. add_variable (model)
131161 MOI. add_constraint (model, z, MOI. GreaterThan (zero (T)))
132162 MOI. modify (model, ci, MOI. ScalarCoefficientChange (z, - one (T)))
133- scale = sense == MOI. MIN_SENSE ? one (T) : - one (T)
134- a = scale * relax. penalty
163+ penalty = sense == MOI. MIN_SENSE ? relax. penalty : - relax. penalty
135164 O = MOI. get (model, MOI. ObjectiveFunctionType ())
136- obj = MOI. ObjectiveFunction {O} ()
137- MOI. modify (model, obj, MOI. ScalarCoefficientChange (z, a))
138- return one (T) * z
165+ return _add_penalty_to_objective (model, O, penalty, [z])
139166end
140167
141168function MOI. modify (
142169 model:: MOI.ModelLike ,
143- ci:: MOI.ConstraintIndex{MOI.ScalarNonlinearFunction,<:MOI.AbstractScalarSet } ,
170+ ci:: MOI.ConstraintIndex{MOI.ScalarNonlinearFunction,S } ,
144171 relax:: ScalarPenaltyRelaxation{T} ,
145- ) where {T}
172+ ) where {T,S <: MOI.AbstractScalarSet }
146173 sense = _change_sense_to_min_if_necessary (T, model)
147- y = MOI. add_variable (model)
148- z = MOI. add_variable (model)
149- MOI. add_constraint (model, y, MOI. GreaterThan ( zero (T)) )
150- MOI . add_constraint (model, z, MOI. GreaterThan ( zero (T)))
151- func = MOI . get (model, MOI . ConstraintFunction (), ci)
152- newfunc = MOI . ScalarNonlinearFunction (: + , [func, ( one (T) * y - one (T) * z)])
153- MOI . set (model, MOI . ConstraintFunction (), ci, newfunc )
154- scale = sense == MOI. MIN_SENSE ? one (T) : - one (T )
155- a = scale * relax. penalty
174+ y, _ = MOI. add_constrained_variable (model, MOI . GreaterThan ( zero (T)) )
175+ z, _ = MOI. add_constrained_variable (model, MOI . GreaterThan ( zero (T)) )
176+ f = MOI. get (model, MOI. ConstraintFunction (), ci )
177+ f = MOI. ScalarNonlinearFunction (
178+ : + ,
179+ Any[f, y, MOI . ScalarNonlinearFunction (: - , Any[z])],
180+ )
181+ MOI. set (model, MOI . ConstraintFunction (), ci, f )
182+ penalty = sense == MOI . MIN_SENSE ? relax . penalty : - relax. penalty
156183 O = MOI. get (model, MOI. ObjectiveFunctionType ())
157- obj = MOI. ObjectiveFunction {O} ()
158- # This breaks if the objective is a VariableIndex or ScalarNonlinearFunction
159- MOI. modify (model, obj, MOI. ScalarCoefficientChange (y, a))
160- MOI. modify (model, obj, MOI. ScalarCoefficientChange (z, a))
161- # The following causes problems with other methods trying to modify the objective
162- # function. We would have to branch/dispatch on objective type
163- # To support existing nonlinear objectives as well as linear/quadratic objectives,
164- # we just turn any objective into a ScalarNonlinearFunction
165- # obj = MOI.get(model, MOI.ObjectiveFunction{O}())
166- # newobj = MOI.ScalarNonlinearFunction(:+, [obj, a * y + a * z])
167- # MOI.set(model, MOI.ObjectiveFunction{MOI.ScalarNonlinearFunction}(), newobj)
168- return one (T) * y + one (T) * z
184+ return _add_penalty_to_objective (model, O, penalty, [y, z])
169185end
170186
171187function MOI. modify (
@@ -179,12 +195,9 @@ function MOI.modify(
179195 func = MOI. get (model, MOI. ConstraintFunction (), ci)
180196 newfunc = MOI. ScalarNonlinearFunction (:+ , [func, y])
181197 MOI. set (model, MOI. ConstraintFunction (), ci, newfunc)
182- scale = sense == MOI. MIN_SENSE ? one (T) : - one (T)
183- a = scale * relax. penalty
198+ penalty = sense == MOI. MIN_SENSE ? relax. penalty : - relax. penalty
184199 O = MOI. get (model, MOI. ObjectiveFunctionType ())
185- obj = MOI. ObjectiveFunction {O} ()
186- MOI. modify (model, obj, MOI. ScalarCoefficientChange (y, a))
187- return one (T) * y
200+ return _add_penalty_to_objective (model, O, penalty, [y])
188201end
189202
190203function MOI. modify (
@@ -198,12 +211,9 @@ function MOI.modify(
198211 func = MOI. get (model, MOI. ConstraintFunction (), ci)
199212 newfunc = MOI. ScalarNonlinearFunction (:- , [func, z])
200213 MOI. set (model, MOI. ConstraintFunction (), ci, newfunc)
201- scale = sense == MOI. MIN_SENSE ? one (T) : - one (T)
202- a = scale * relax. penalty
214+ penalty = sense == MOI. MIN_SENSE ? relax. penalty : - relax. penalty
203215 O = MOI. get (model, MOI. ObjectiveFunctionType ())
204- obj = MOI. ObjectiveFunction {O} ()
205- MOI. modify (model, obj, MOI. ScalarCoefficientChange (z, a))
206- return one (T) * z
216+ return _add_penalty_to_objective (model, O, penalty, [z])
207217end
208218
209219"""
0 commit comments