diff --git a/docs/src/reference/models.md b/docs/src/reference/models.md index 7efc192469..d6956536d9 100644 --- a/docs/src/reference/models.md +++ b/docs/src/reference/models.md @@ -31,6 +31,7 @@ write_to_file read_from_file supports_incremental_interface copy_to +IndexMap ``` ## Model attributes diff --git a/src/MathOptInterface.jl b/src/MathOptInterface.jl index ea672ed171..41226e38bf 100644 --- a/src/MathOptInterface.jl +++ b/src/MathOptInterface.jl @@ -124,23 +124,41 @@ This is used in two places to determine whether to add a cache: supports_incremental_interface(::ModelLike, ::Bool) = false """ - copy_to(dest::ModelLike, src::ModelLike; copy_names=true, warn_attributes=true) - -Copy the model from `src` into `dest`. The target `dest` is emptied, and all -previous indices to variables or constraints in `dest` are invalidated. Returns -a dictionary-like object that translates variable and constraint indices from -the `src` model to the corresponding indices in the `dest` model. - -If `copy_names` is `false`, the `Name`, `VariableName` and `ConstraintName` -attributes are not copied even if they are set in `src`. If a constraint that -is copied from `src` is not supported by `dest` then an -[`UnsupportedConstraint`](@ref) error is thrown. Similarly, if a model, variable -or constraint attribute that is copied from `src` is not supported by `dest` -then an [`UnsupportedAttribute`](@ref) error is thrown. Unsupported *optimizer* -attributes are treated differently: - -* If `warn_attributes` is `true`, a warning is displayed, otherwise, -* the attribute is silently ignored. + copy_to( + dest::ModelLike, + src::ModelLike; + copy_names::Bool = true, + warn_attributes::Bool = true, + )::IndexMap + +Copy the model from `src` into `dest`. + +The target `dest` is emptied, and all previous indices to variables and +constraints in `dest` are invalidated. + +Returns an [`IndexMap`](@ref) object that translates variable and constraint +indices from the `src` model to the corresponding indices in the `dest` model. + +## Notes + + * If `copy_names == false`, the [`Name`](@ref), [`VariableName`](@ref) and + [`ConstraintName`](@ref) attributes are not copied, even if they are set in + `src`. + * If a constraint that in `src` is not supported by `dest`, then an + [`UnsupportedConstraint`](@ref) error is thrown. + * If an [`AbstractModelAttribute`](@ref), [`AbstractVariableAttribute`](@ref), + or [`AbstractConstraintAttribute`](@ref) is set in `src` but not supported by + `dest`, then an [`UnsupportedAttribute`](@ref) error is thrown. + * Unsupported [`AbstractOptimizerAttribute`](@ref)s are treated differently: + * If `warn_attributes == true`, a warning is displayed, otherwise, the + attribute is silently ignored. + +## IndexMap + +Implementations of `copy_to` must return an [`IndexMap`](@ref). For technical +reasons, this type is defined in the Utilties submodule as +`MOI.Utilities.IndexMap`. However, since it is an integral part of the MOI API, +we provide `MOI.IndexMap` as an alias. ### Example @@ -160,16 +178,26 @@ is_valid(dest, index_map[x]) # true function copy_to end """ - copy_to_and_optimize!(dest::ModelLike, src::ModelLike; copy_names=true, warn_attributes=true) + copy_to_and_optimize!( + dest::AbstractOptimizer, + src::ModelLike; + kwargs... + )::IndexMap -Same as [`copy_to`](@ref) followed [`optimize!`](@ref). An optimizer -can decide to implement this function and not implement [`copy_to`](@ref) and -[`optimize!`](@ref). +A single call equivalent to calling [`copy_to`](@ref) followed by +[`optimize!`](@ref). Like [`copy_to`](@ref), it returns an [`IndexMap`]. -**WARNING** This is an experimental new feature of MOI v0.10 that may break in MOI v1.0. +Keyword arguments are passed to [`copy_to`](@ref). + +An optimizer can decide to implement this function instead of implementing +[`copy_to`](@ref) and [`optimize!`](@ref) individually. + +!!! warning + This is an experimental new feature of MOI v0.10 that may break in MOI v1.0. """ -function copy_to_and_optimize!(dest, src; kws...) - index_map = copy_to(dest, src; kws...) +function copy_to_and_optimize!(dest, src; kwargs...) + # The arguments above are untyped to avoid ambiguities. + index_map = copy_to(dest, src; kwargs...) optimize!(dest) return index_map end @@ -199,4 +227,21 @@ include("instantiate.jl") include("deprecate.jl") include("DeprecatedTest/DeprecatedTest.jl") +""" + IndexMap(number_of_variables::Int = 0) + +The dictionary-like object returned by [`copy_to`](@ref). + +If known in advance, pass `number_of_variables` to preallocate the necessary +space for the variables. + +## IndexMap + +Implementations of [`copy_to`](@ref) must return an [`IndexMap`](@ref). For +technical reasons, the `IndexMap` type is defined in the Utilties submodule as +`MOI.Utilities.IndexMap`. However, since it is an integral part of the MOI API, +we provide this `MOI.IndexMap` as an alias. +""" +const IndexMap = Utilities.IndexMap + end diff --git a/src/Utilities/copy/index_map.jl b/src/Utilities/copy/index_map.jl index a1cffa51ec..c1a6a57ca2 100644 --- a/src/Utilities/copy/index_map.jl +++ b/src/Utilities/copy/index_map.jl @@ -1,3 +1,11 @@ +# IndexMap is defined here because there is a boostrapping problem. +# * IndexMap requires `Utilities.CleverDicts` and `Utilities.DoubleDicts`, so +# if it were to be defined in MOI proper, it must be included after +# Utilities. +# * However, Utilities requires IndexMap, so it must be defined before +# Utilities.jl is included. +# To work around this issue, we define `IndexMap` here. + struct IndexMap <: AbstractDict{MOI.Index,MOI.Index} var_map::CleverDicts.CleverDict{ MOI.VariableIndex, @@ -9,17 +17,18 @@ struct IndexMap <: AbstractDict{MOI.Index,MOI.Index} end """ - IndexMap(n::Int = 0) + IndexMap(number_of_variables::Int = 0) + +The dictionary-like object returned by [`MathOptInterface.copy_to`](@ref). -Dictionary-like object returned by [`MathOptInterface.copy_to`](@ref) that -contains the mapping between variable indices in `.var_map` and between -constraint indices in `.con_map`. +If known in advance, pass `number_of_variables` to preallocate the necessary +space for the variables. """ -function IndexMap(n::Int = 0) +function IndexMap(number_of_variables::Int = 0) var_map = CleverDicts.CleverDict{MOI.VariableIndex,MOI.VariableIndex}( CleverDicts.key_to_index, CleverDicts.index_to_key, - n, + number_of_variables, ) con_map = DoubleDicts.IndexDoubleDict() return IndexMap(var_map, con_map)