Skip to content

Commit 4c0b43b

Browse files
guilhermebodinodow
andauthored
MOI.modify version for multiple changes at once (#1800)
* MOI.modify version for multiple changes at once * fall back to scalar modify * fix modifications.jl * add docs and tests * Update modifications.jl * fix docstrings Co-authored-by: Oscar Dowson <odow@users.noreply.github.com>
1 parent 010559a commit 4c0b43b

File tree

2 files changed

+127
-0
lines changed

2 files changed

+127
-0
lines changed

src/modifications.jl

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,58 @@ objectives is not supported by the model `model`.
9595
```julia
9696
modify(model, ObjectiveFunction{ScalarAffineFunction{Float64}}(), ScalarConstantChange(10.0))
9797
```
98+
99+
## Multiple modifications in Constraint Functions
100+
101+
modify(
102+
model::ModelLike,
103+
cis::AbstractVector{<:ConstraintIndex},
104+
changes::AbstractVector{<:AbstractFunctionModification},
105+
)
106+
107+
Apply multiple modifications specified by `changes` to the functions of constraints `cis`.
108+
109+
A [`ModifyConstraintNotAllowed`](@ref) error is thrown if modifying
110+
constraints is not supported by `model`.
111+
112+
### Examples
113+
114+
```julia
115+
modify(
116+
model,
117+
[ci, ci],
118+
[
119+
ScalarCoefficientChange{Float64}(VariableIndex(1), 1.0),
120+
ScalarCoefficientChange{Float64}(VariableIndex(2), 0.5),
121+
],
122+
)
123+
```
124+
125+
## Multiple modifications in the Objective Function
126+
127+
modify(
128+
model::ModelLike,
129+
attr::ObjectiveFunction,
130+
changes::AbstractVector{<:AbstractFunctionModification},
131+
)
132+
133+
Apply multiple modifications specified by `changes` to the functions of constraints `cis`.
134+
135+
A [`ModifyObjectiveNotAllowed`](@ref) error is thrown if modifying
136+
objective coefficients is not supported by `model`.
137+
138+
### Examples
139+
140+
```julia
141+
modify(
142+
model,
143+
ObjectiveFunction{ScalarAffineFunction{Float64}}(),
144+
[
145+
ScalarCoefficientChange{Float64}(VariableIndex(1), 1.0),
146+
ScalarCoefficientChange{Float64}(VariableIndex(2), 0.5),
147+
],
148+
)
149+
```
98150
"""
99151
function modify end
100152

@@ -106,10 +158,33 @@ function modify(
106158
return throw_modify_not_allowed(ci, change)
107159
end
108160

161+
function modify(
162+
model::ModelLike,
163+
cis::AbstractVector{<:ConstraintIndex},
164+
changes::AbstractVector{<:AbstractFunctionModification},
165+
)
166+
@assert length(cis) == length(changes)
167+
for (ci, change) in zip(cis, changes)
168+
modify(model, ci, change)
169+
end
170+
return
171+
end
172+
109173
function modify(
110174
model::ModelLike,
111175
attr::ObjectiveFunction,
112176
change::AbstractFunctionModification,
113177
)
114178
return throw_modify_not_allowed(attr, change)
115179
end
180+
181+
function modify(
182+
model::ModelLike,
183+
attr::ObjectiveFunction,
184+
changes::AbstractVector{<:AbstractFunctionModification},
185+
)
186+
for change in changes
187+
modify(model, attr, change)
188+
end
189+
return
190+
end

test/Utilities/cachingoptimizer.jl

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,58 @@ function test_final_touch_optimize()
952952
@test model.model_cache.index_map === nothing
953953
end
954954

955+
function test_multiple_modifications()
956+
m = MOIU.CachingOptimizer(MOIU.Model{Float64}(), MOIU.AUTOMATIC)
957+
958+
x = MOI.add_variables(m, 3)
959+
960+
saf = MOI.ScalarAffineFunction(
961+
[
962+
MOI.ScalarAffineTerm(1.0, x[1]),
963+
MOI.ScalarAffineTerm(1.0, x[2]),
964+
MOI.ScalarAffineTerm(1.0, x[3]),
965+
],
966+
0.0,
967+
)
968+
ci1 = MOI.add_constraint(m, saf, MOI.LessThan(1.0))
969+
ci2 = MOI.add_constraint(m, saf, MOI.LessThan(2.0))
970+
971+
MOI.set(m, MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(), saf)
972+
973+
fc1 = MOI.get(m, MOI.ConstraintFunction(), ci1)
974+
@test MOI.coefficient.(fc1.terms) == [1.0, 1.0, 1.0]
975+
fc2 = MOI.get(m, MOI.ConstraintFunction(), ci2)
976+
@test MOI.coefficient.(fc2.terms) == [1.0, 1.0, 1.0]
977+
obj = MOI.get(m, MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}())
978+
@test MOI.coefficient.(obj.terms) == [1.0, 1.0, 1.0]
979+
980+
changes_cis = [
981+
MOI.ScalarCoefficientChange(MOI.VariableIndex(1), 4.0)
982+
MOI.ScalarCoefficientChange(MOI.VariableIndex(1), 0.5)
983+
MOI.ScalarCoefficientChange(MOI.VariableIndex(3), 2.0)
984+
]
985+
MOI.modify(m, [ci1, ci2, ci2], changes_cis)
986+
987+
fc1 = MOI.get(m, MOI.ConstraintFunction(), ci1)
988+
@test MOI.coefficient.(fc1.terms) == [4.0, 1.0, 1.0]
989+
fc2 = MOI.get(m, MOI.ConstraintFunction(), ci2)
990+
@test MOI.coefficient.(fc2.terms) == [0.5, 1.0, 2.0]
991+
992+
changes_obj = [
993+
MOI.ScalarCoefficientChange(MOI.VariableIndex(1), 4.0)
994+
MOI.ScalarCoefficientChange(MOI.VariableIndex(2), 10.0)
995+
MOI.ScalarCoefficientChange(MOI.VariableIndex(3), 2.0)
996+
]
997+
MOI.modify(
998+
m,
999+
MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
1000+
changes_obj,
1001+
)
1002+
1003+
obj = MOI.get(m, MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}())
1004+
@test MOI.coefficient.(obj.terms) == [4.0, 10.0, 2.0]
1005+
end
1006+
9551007
end # module
9561008

9571009
TestCachingOptimizer.runtests()

0 commit comments

Comments
 (0)