Skip to content

Commit e73ab19

Browse files
committed
penalty relaxation for nonlinear constraints
1 parent 1f5671e commit e73ab19

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

src/Utilities/penalty_relaxation.jl

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,86 @@ function MOI.modify(
138138
return one(T) * z
139139
end
140140

141+
function MOI.modify(
142+
model::MOI.ModelLike,
143+
ci::MOI.ConstraintIndex{MOI.ScalarNonlinearFunction,<:MOI.AbstractScalarSet},
144+
relax::ScalarPenaltyRelaxation{T},
145+
) where {T}
146+
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+
set = MOI.get(model, MOI.ConstraintSet(), ci)
153+
newfunc = MOI.ScalarNonlinearFunction(:+, [func, (one(T) * y - one(T) * z)])
154+
MOI.set(model, MOI.ConstraintFunction(), ci, newfunc)
155+
scale = sense == MOI.MIN_SENSE ? one(T) : -one(T)
156+
a = scale * relax.penalty
157+
O = MOI.get(model, MOI.ObjectiveFunctionType())
158+
obj = MOI.get(model, MOI.ObjectiveFunction{O}())
159+
obj = MOI.ObjectiveFunction{O}()
160+
MOI.modify(model, obj, MOI.ScalarCoefficientChange(y, a))
161+
MOI.modify(model, obj, MOI.ScalarCoefficientChange(z, a))
162+
# This causes problems with other methods trying to modify the objective
163+
# function.
164+
# To support existing nonlinear objectives as well as linear/quadratic objectives,
165+
# we just turn any objective into a ScalarNonlinearFunction
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
169+
end
170+
171+
function MOI.modify(
172+
model::MOI.ModelLike,
173+
ci::MOI.ConstraintIndex{MOI.ScalarNonlinearFunction,MOI.GreaterThan{T}},
174+
relax::ScalarPenaltyRelaxation{T},
175+
) where {T}
176+
sense = _change_sense_to_min_if_necessary(T, model)
177+
y = MOI.add_variable(model)
178+
MOI.add_constraint(model, y, MOI.GreaterThan(zero(T)))
179+
func = MOI.get(model, MOI.ConstraintFunction(), ci)
180+
set = MOI.get(model, MOI.ConstraintSet(), ci)
181+
newfunc = MOI.ScalarNonlinearFunction(:+, [func, y])
182+
MOI.set(model, MOI.ConstraintFunction(), ci, newfunc)
183+
scale = sense == MOI.MIN_SENSE ? one(T) : -one(T)
184+
a = scale * relax.penalty
185+
O = MOI.get(model, MOI.ObjectiveFunctionType())
186+
obj = MOI.get(model, MOI.ObjectiveFunction{O}())
187+
MOI.modify(model, obj, MOI.ScalarCoefficientChange(y, a))
188+
# This causes problems. TODO: Revisit.
189+
# To support existing nonlinear objectives as well as linear/quadratic objectives,
190+
# we just turn any objective into a ScalarNonlinearFunction
191+
#newobj = MOI.ScalarNonlinearFunction(:+, [obj, a * y])
192+
#MOI.set(model, MOI.ObjectiveFunction{MOI.ScalarNonlinearFunction}(), newobj)
193+
return one(T) * y
194+
end
195+
196+
function MOI.modify(
197+
model::MOI.ModelLike,
198+
ci::MOI.ConstraintIndex{MOI.ScalarNonlinearFunction,MOI.LessThan{T}},
199+
relax::ScalarPenaltyRelaxation{T},
200+
) where {T}
201+
sense = _change_sense_to_min_if_necessary(T, model)
202+
z = MOI.add_variable(model)
203+
MOI.add_constraint(model, z, MOI.GreaterThan(zero(T)))
204+
func = MOI.get(model, MOI.ConstraintFunction(), ci)
205+
set = MOI.get(model, MOI.ConstraintSet(), ci)
206+
newfunc = MOI.ScalarNonlinearFunction(:-, [func, z])
207+
MOI.set(model, MOI.ConstraintFunction(), ci, newfunc)
208+
scale = sense == MOI.MIN_SENSE ? one(T) : -one(T)
209+
a = scale * relax.penalty
210+
O = MOI.get(model, MOI.ObjectiveFunctionType())
211+
obj = MOI.get(model, MOI.ObjectiveFunction{O}())
212+
MOI.modify(model, obj, MOI.ScalarCoefficientChange(z, a))
213+
# This causes problems. TODO: Revisit.
214+
# To support existing nonlinear objectives as well as linear/quadratic objectives,
215+
# we just turn any objective into a ScalarNonlinearFunction
216+
#newobj = MOI.ScalarNonlinearFunction(:+, [obj, a * z])
217+
#MOI.set(model, MOI.ObjectiveFunction{MOI.ScalarNonlinearFunction}(), newobj)
218+
return one(T) * z
219+
end
220+
141221
"""
142222
PenaltyRelaxation(
143223
penalties = Dict{MOI.ConstraintIndex,Float64}();

0 commit comments

Comments
 (0)