Skip to content

Commit af426f0

Browse files
authored
Merge pull request #827 from JuliaOpt/bl/map_indices
Replace mapvariables by map_indices
2 parents 2aee608 + 8b601e3 commit af426f0

File tree

8 files changed

+189
-112
lines changed

8 files changed

+189
-112
lines changed

docs/src/apireference.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,7 @@ Utilities.mode
662662
The following utilities are available for functions:
663663
```@docs
664664
Utilities.eval_variables
665+
Utilities.map_indices
665666
Utilities.substitute_variables
666667
Utilities.remove_variable
667668
Utilities.all_coefficients

src/Bridges/bridge_optimizer.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,7 @@ function bridged_function(b::AbstractBridgeOptimizer,
933933
end
934934
# Shortcut to avoid `Variable.throw_if_cannot_unbridge(Variable.bridges(b))`
935935
function bridge_function(
936-
::AbstractBridgeOptimizer, value::MOIU.ObjectOrArrayWithoutIndex)
936+
::AbstractBridgeOptimizer, value::MOIU.ObjectOrTupleOrArrayWithoutIndex)
937937
return value
938938
end
939939

@@ -983,7 +983,7 @@ function unbridged_function(bridge::AbstractBridgeOptimizer,
983983
end
984984
# Shortcut to avoid `Variable.throw_if_cannot_unbridge(Variable.bridges(b))`
985985
function unbridged_function(
986-
::AbstractBridgeOptimizer, value::MOIU.ObjectOrArrayWithoutIndex)
986+
::AbstractBridgeOptimizer, value::MOIU.ObjectOrTupleOrArrayWithoutIndex)
987987
return value
988988
end
989989

src/Utilities/cachingoptimizer.jl

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ function reset_optimizer(m::CachingOptimizer, optimizer::MOI.AbstractOptimizer)
9090
m.state = EMPTY_OPTIMIZER
9191
for attr in MOI.get(m.model_cache, MOI.ListOfOptimizerAttributesSet())
9292
value = MOI.get(m.model_cache, attr)
93-
optimizer_value = attribute_value_map(m.model_to_optimizer_map, value)
93+
optimizer_value = map_indices(m.model_to_optimizer_map, value)
9494
MOI.set(m.optimizer, attr, optimizer_value)
9595
end
9696
return
@@ -236,7 +236,7 @@ function MOI.add_constraint(m::CachingOptimizer, func::MOI.AbstractFunction, set
236236
if m.state == ATTACHED_OPTIMIZER
237237
if m.mode == AUTOMATIC
238238
try
239-
cindex_optimizer = MOI.add_constraint(m.optimizer, mapvariables(m.model_to_optimizer_map, func), set)
239+
cindex_optimizer = MOI.add_constraint(m.optimizer, map_indices(m.model_to_optimizer_map, func), set)
240240
catch err
241241
if err isa MOI.NotAllowedError
242242
# It could be MOI.AddConstraintNotAllowed{F', S'} with F' != F
@@ -248,7 +248,7 @@ function MOI.add_constraint(m::CachingOptimizer, func::MOI.AbstractFunction, set
248248
end
249249
end
250250
else
251-
cindex_optimizer = MOI.add_constraint(m.optimizer, mapvariables(m.model_to_optimizer_map, func), set)
251+
cindex_optimizer = MOI.add_constraint(m.optimizer, map_indices(m.model_to_optimizer_map, func), set)
252252
end
253253
end
254254
cindex = MOI.add_constraint(m.model_cache, func, set)
@@ -262,7 +262,7 @@ end
262262
function MOI.modify(m::CachingOptimizer, cindex::CI, change::MOI.AbstractFunctionModification)
263263
if m.state == ATTACHED_OPTIMIZER
264264
cindex_optimizer = m.model_to_optimizer_map[cindex]
265-
change_optimizer = mapvariables(m.model_to_optimizer_map, change)
265+
change_optimizer = map_indices(m.model_to_optimizer_map, change)
266266
if m.mode == AUTOMATIC
267267
try
268268
MOI.modify(m.optimizer, cindex_optimizer, change_optimizer)
@@ -285,10 +285,11 @@ end
285285
# the third and fourth arguments of the set methods so that we only support
286286
# setting the same type of set or function.
287287
function replace_constraint_function_or_set(m::CachingOptimizer, attr, cindex, replacement)
288+
replacement_optimizer = map_indices(m.model_to_optimizer_map, replacement)
288289
if m.state == ATTACHED_OPTIMIZER
289290
if m.mode == AUTOMATIC
290291
try
291-
MOI.set(m.optimizer, attr, m.model_to_optimizer_map[cindex], replacement)
292+
MOI.set(m.optimizer, attr, m.model_to_optimizer_map[cindex], replacement_optimizer)
292293
catch err
293294
if err isa MOI.NotAllowedError
294295
reset_optimizer(m)
@@ -297,7 +298,7 @@ function replace_constraint_function_or_set(m::CachingOptimizer, attr, cindex, r
297298
end
298299
end
299300
else
300-
MOI.set(m.optimizer, attr, m.model_to_optimizer_map[cindex], replacement)
301+
MOI.set(m.optimizer, attr, m.model_to_optimizer_map[cindex], replacement_optimizer)
301302
end
302303
end
303304
MOI.set(m.model_cache, attr, cindex, replacement)
@@ -307,13 +308,13 @@ function MOI.set(m::CachingOptimizer, ::MOI.ConstraintSet, cindex::CI{F,S}, set:
307308
replace_constraint_function_or_set(m, MOI.ConstraintSet(), cindex, set)
308309
end
309310

310-
function MOI.set(m::CachingOptimizer, ::MOI.ConstraintFunction, cindex::CI{F,S}, func::F) where {F,S}
311+
function MOI.set(m::CachingOptimizer, ::MOI.ConstraintFunction, cindex::CI{F}, func::F) where F
311312
replace_constraint_function_or_set(m, MOI.ConstraintFunction(), cindex, func)
312313
end
313314

314315
function MOI.modify(m::CachingOptimizer, obj::MOI.ObjectiveFunction, change::MOI.AbstractFunctionModification)
315316
if m.state == ATTACHED_OPTIMIZER
316-
change_optimizer = mapvariables(m.model_to_optimizer_map, change)
317+
change_optimizer = map_indices(m.model_to_optimizer_map, change)
317318
if m.mode == AUTOMATIC
318319
try
319320
MOI.modify(m.optimizer, obj, change_optimizer)
@@ -368,16 +369,13 @@ end
368369

369370
## CachingOptimizer get and set attributes
370371

371-
# Attributes are mapped through attribute_value_map (defined in copy.jl) before
372+
# Attributes are mapped through `map_indices` (defined in functions.jl) before
372373
# they are sent to the optimizer and when they are returned from the optimizer.
373-
# This map currently only translates indices on MOI.AbstractFunction objects
374-
# between the optimizer indices and the (user-facing) model_cache indices. As a result,
375-
# all MOI.AbstractFunctions must implement mapvariables. Other attributes that
376-
# store indices need to be handled with care.
374+
# As a result, values of attributes must implement `map_indices`.
377375

378376
function MOI.set(m::CachingOptimizer, attr::MOI.AbstractModelAttribute, value)
379377
if m.state == ATTACHED_OPTIMIZER
380-
optimizer_value = attribute_value_map(m.model_to_optimizer_map, value)
378+
optimizer_value = map_indices(m.model_to_optimizer_map, value)
381379
if m.mode == AUTOMATIC
382380
try
383381
MOI.set(m.optimizer, attr, optimizer_value)
@@ -401,7 +399,7 @@ function MOI.set(m::CachingOptimizer,
401399
index::MOI.Index, value)
402400
if m.state == ATTACHED_OPTIMIZER
403401
optimizer_index = m.model_to_optimizer_map[index]
404-
optimizer_value = attribute_value_map(m.model_to_optimizer_map, value)
402+
optimizer_value = map_indices(m.model_to_optimizer_map, value)
405403
if m.mode == AUTOMATIC
406404
try
407405
MOI.set(m.optimizer, attr, optimizer_index, optimizer_value)
@@ -448,8 +446,8 @@ function MOI.get(model::CachingOptimizer, attr::MOI.AbstractModelAttribute)
448446
" optimizer is attached.")
449447
end
450448
end
451-
return attribute_value_map(model.optimizer_to_model_map,
452-
MOI.get(model.optimizer, attr))
449+
return map_indices(model.optimizer_to_model_map,
450+
MOI.get(model.optimizer, attr))
453451
else
454452
return MOI.get(model.model_cache, attr)
455453
end
@@ -463,9 +461,9 @@ function MOI.get(model::CachingOptimizer,
463461
error("Cannot query $(attr) from caching optimizer because no " *
464462
"optimizer is attached.")
465463
end
466-
return attribute_value_map(model.optimizer_to_model_map,
467-
MOI.get(model.optimizer, attr,
468-
model.model_to_optimizer_map[index]))
464+
return map_indices(model.optimizer_to_model_map,
465+
MOI.get(model.optimizer, attr,
466+
model.model_to_optimizer_map[index]))
469467
else
470468
return MOI.get(model.model_cache, attr, index)
471469
end
@@ -479,10 +477,10 @@ function MOI.get(model::CachingOptimizer,
479477
error("Cannot query $(attr) from caching optimizer because no " *
480478
"optimizer is attached.")
481479
end
482-
return attribute_value_map(model.optimizer_to_model_map,
483-
MOI.get(model.optimizer, attr,
484-
map(index -> model.model_to_optimizer_map[index],
485-
indices)))
480+
return map_indices(model.optimizer_to_model_map,
481+
MOI.get(model.optimizer, attr,
482+
map(index -> model.model_to_optimizer_map[index],
483+
indices)))
486484
else
487485
return MOI.get(model.model_cache, attr, indices)
488486
end
@@ -521,7 +519,7 @@ end
521519

522520
function MOI.set(model::CachingOptimizer, attr::MOI.AbstractOptimizerAttribute,
523521
value)
524-
optimizer_value = attribute_value_map(model.model_to_optimizer_map, value)
522+
optimizer_value = map_indices(model.model_to_optimizer_map, value)
525523
if model.optimizer !== nothing
526524
MOI.set(model.optimizer, attr, optimizer_value)
527525
end
@@ -537,8 +535,8 @@ function MOI.get(model::CachingOptimizer, attr::MOI.AbstractOptimizerAttribute)
537535
error("Cannot query $(attr) from caching optimizer because no " *
538536
"optimizer is attached.")
539537
end
540-
return attribute_value_map(model.optimizer_to_model_map,
541-
MOI.get(model.optimizer, attr))
538+
return map_indices(model.optimizer_to_model_map,
539+
MOI.get(model.optimizer, attr))
542540
end
543541

544542
# Force users to specify whether the attribute should be queried from the
@@ -566,17 +564,17 @@ end
566564

567565
function MOI.get(m::CachingOptimizer, attr::AttributeFromOptimizer{T}) where {T <: MOI.AbstractModelAttribute}
568566
@assert m.state == ATTACHED_OPTIMIZER
569-
return attribute_value_map(m.optimizer_to_model_map,MOI.get(m.optimizer, attr.attr))
567+
return map_indices(m.optimizer_to_model_map,MOI.get(m.optimizer, attr.attr))
570568
end
571569

572570
function MOI.get(m::CachingOptimizer, attr::AttributeFromOptimizer{T}, idx::MOI.Index) where {T <: Union{MOI.AbstractVariableAttribute,MOI.AbstractConstraintAttribute}}
573571
@assert m.state == ATTACHED_OPTIMIZER
574-
return attribute_value_map(m.optimizer_to_model_map,MOI.get(m.optimizer, attr.attr, m.model_to_optimizer_map[idx]))
572+
return map_indices(m.optimizer_to_model_map,MOI.get(m.optimizer, attr.attr, m.model_to_optimizer_map[idx]))
575573
end
576574

577575
function MOI.get(m::CachingOptimizer, attr::AttributeFromOptimizer{T}, idx::Vector{<:MOI.Index}) where {T <: Union{MOI.AbstractVariableAttribute,MOI.AbstractConstraintAttribute}}
578576
@assert m.state == ATTACHED_OPTIMIZER
579-
return attribute_value_map(m.optimizer_to_model_map,MOI.get(m.optimizer, attr.attr, getindex.(m.model_to_optimizer_map,idx)))
577+
return map_indices(m.optimizer_to_model_map,MOI.get(m.optimizer, attr.attr, getindex.(m.model_to_optimizer_map,idx)))
580578
end
581579

582580
function MOI.set(m::CachingOptimizer, attr::AttributeFromModelCache{T}, v) where {T <: MOI.AbstractModelAttribute}
@@ -589,15 +587,15 @@ end
589587

590588
function MOI.set(m::CachingOptimizer, attr::AttributeFromOptimizer{T}, v) where {T <: MOI.AbstractModelAttribute}
591589
@assert m.state == ATTACHED_OPTIMIZER
592-
return MOI.set(m.optimizer, attr.attr, attribute_value_map(m.model_to_optimizer_map,v))
590+
return MOI.set(m.optimizer, attr.attr, map_indices(m.model_to_optimizer_map, v))
593591
end
594592

595593
# Map vector of indices into vector of indices or one index into one index
596594
map_indices_to_optimizer(m::CachingOptimizer, idx::MOI.Index) = m.model_to_optimizer_map[idx]
597595
map_indices_to_optimizer(m::CachingOptimizer, indices::Vector{<:MOI.Index}) = getindex.(Ref(m.model_to_optimizer_map), indices)
598596
function MOI.set(m::CachingOptimizer, attr::AttributeFromOptimizer{T}, idx, v) where {T <: Union{MOI.AbstractVariableAttribute,MOI.AbstractConstraintAttribute}}
599597
@assert m.state == ATTACHED_OPTIMIZER
600-
return MOI.set(m.optimizer, attr.attr, map_indices_to_optimizer(m, idx), attribute_value_map(m.model_to_optimizer_map,v))
598+
return MOI.set(m.optimizer, attr.attr, map_indices_to_optimizer(m, idx), map_indices(m.model_to_optimizer_map, v))
601599
end
602600

603601
function MOI.supports(m::CachingOptimizer, attr::AttributeFromModelCache{T}) where {T <: MOI.AbstractModelAttribute}

src/Utilities/copy.jl

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ error in case `copy_to` is called with `copy_names` equal to `true`.
6363
"""
6464
supports_default_copy_to(model::MOI.ModelLike, copy_names::Bool) = false
6565

66-
struct IndexMap
66+
struct IndexMap <: AbstractDict{MOI.Index, MOI.Index}
6767
varmap::Dict{MOI.VariableIndex, MOI.VariableIndex}
6868
conmap::Dict{MOI.ConstraintIndex, MOI.ConstraintIndex}
6969
end
@@ -141,7 +141,7 @@ function _pass_attributes(dest::MOI.ModelLike, src::MOI.ModelLike,
141141
end
142142
value = MOI.get(src, attr, get_args...)
143143
if value !== nothing
144-
mapped_value = attribute_value_map(idxmap, value)
144+
mapped_value = map_indices(idxmap, value)
145145
pass_attr!(dest, attr, set_args..., mapped_value)
146146
end
147147
end
@@ -220,7 +220,7 @@ function copy_constraints(dest::MOI.ModelLike, src::MOI.ModelLike,
220220
idxmap::IndexMap,
221221
cis_src::Vector{<:MOI.ConstraintIndex})
222222
f_src = MOI.get(src, MOI.ConstraintFunction(), cis_src)
223-
f_dest = mapvariables.(Ref(idxmap), f_src)
223+
f_dest = map_indices.(Ref(idxmap), f_src)
224224
s = MOI.get(src, MOI.ConstraintSet(), cis_src)
225225
cis_dest = MOI.add_constraints(dest, f_dest, s)
226226
for (ci_src, ci_dest) in zip(cis_src, cis_dest)
@@ -264,8 +264,6 @@ function pass_constraints(
264264
end
265265
end
266266

267-
attribute_value_map(idxmap, f::MOI.AbstractFunction) = mapvariables(idxmap, f)
268-
attribute_value_map(idxmap, attribute_value) = attribute_value
269267
function default_copy_to(dest::MOI.ModelLike, src::MOI.ModelLike)
270268
Base.depwarn("default_copy_to(dest, src) is deprecated, use default_copy_to(dest, src, true) instead or default_copy_to(dest, src, false) if you do not want to copy names.", :default_copy_to)
271269
default_copy_to(dest, src, true)
@@ -600,7 +598,7 @@ function allocate_constraints(dest::MOI.ModelLike, src::MOI.ModelLike,
600598
for ci_src in cis_src
601599
f_src = MOI.get(src, MOI.ConstraintFunction(), ci_src)
602600
s = MOI.get(src, MOI.ConstraintSet(), ci_src)
603-
f_dest = mapvariables(idxmap, f_src)
601+
f_dest = map_indices(idxmap, f_src)
604602
ci_dest = allocate_constraint(dest, f_dest, s)
605603
idxmap.conmap[ci_src] = ci_dest
606604
end
@@ -611,7 +609,7 @@ function load_constraints(dest::MOI.ModelLike, src::MOI.ModelLike,
611609
for ci_src in cis_src
612610
ci_dest = idxmap[ci_src]
613611
f_src = MOI.get(src, MOI.ConstraintFunction(), ci_src)
614-
f_dest = mapvariables(idxmap, f_src)
612+
f_dest = map_indices(idxmap, f_src)
615613
s = MOI.get(src, MOI.ConstraintSet(), ci_src)
616614
load_constraint(dest, ci_dest, f_dest, s)
617615
end

0 commit comments

Comments
 (0)