diff --git a/src/Utilities/copy.jl b/src/Utilities/copy.jl index 76a34dc75f..644552bd78 100644 --- a/src/Utilities/copy.jl +++ b/src/Utilities/copy.jl @@ -40,6 +40,32 @@ function pass_attributes(dest::MOI.ModelLike, src::MOI.ModelLike, index_map) return end +struct UnsafeObjectiveFunction{F<:MOI.AbstractFunction} <: + MOI.AbstractModelAttribute end + +function MOI.get(model::MOI.ModelLike, ::UnsafeObjectiveFunction{F}) where {F} + return MOI.get(model, MOI.ObjectiveFunction{F}()) +end + +struct UnsafeConstraintFunction <: MOI.AbstractConstraintAttribute end + +function MOI.get_fallback( + model::MOI.ModelLike, + ::UnsafeConstraintFunction, + ci::MOI.ConstraintIndex, +) + return MOI.get(model, MOI.ConstraintFunction(), ci) +end + +function _pass_attribute( + dest::MOI.ModelLike, + src::MOI.ModelLike, + index_map, + ::MOI.ConstraintFunction, +) + return _pass_attribute(dest, src, index_map, UnsafeConstraintFunction()) +end + function _pass_attribute( dest::MOI.ModelLike, src::MOI.ModelLike, @@ -175,7 +201,10 @@ function _copy_constraints( cis_src::Vector{<:MOI.ConstraintIndex}, ) for ci in cis_src - f = MOI.get(src, MOI.ConstraintFunction(), ci) + # MOI does not allows the implementation of `MOI.constraint` + # to modify it or hold a copy of it. + # `map_indices` is also often going to copy it anyway + f = MOI.get(src, UnsafeConstraintFunction(), ci) s = MOI.get(src, MOI.ConstraintSet(), ci) index_map_FS[ci] = MOI.add_constraint(dest, map_indices(index_map, f), s) diff --git a/src/Utilities/model.jl b/src/Utilities/model.jl index fe06b53763..e0022104c2 100644 --- a/src/Utilities/model.jl +++ b/src/Utilities/model.jl @@ -402,7 +402,11 @@ end function MOI.get( model::AbstractModel, - attr::Union{MOI.ConstraintFunction,MOI.ConstraintSet}, + attr::Union{ + UnsafeConstraintFunction, + MOI.ConstraintFunction, + MOI.ConstraintSet, + }, ci::MOI.ConstraintIndex, ) return MOI.get(constraints(model, ci), attr, ci) @@ -530,7 +534,10 @@ function MOI.supports(model::AbstractModel, attr::MOI.ObjectiveFunction) return MOI.supports(model.objective, attr) end -function MOI.get(model::AbstractModel, attr::MOI.ObjectiveFunction) +function MOI.get( + model::AbstractModel, + attr::Union{UnsafeObjectiveFunction,MOI.ObjectiveFunction}, +) return MOI.get(model.objective, attr) end diff --git a/src/Utilities/objective_container.jl b/src/Utilities/objective_container.jl index 5ebce67930..b7103196e2 100644 --- a/src/Utilities/objective_container.jl +++ b/src/Utilities/objective_container.jl @@ -153,6 +153,10 @@ function MOI.get( return convert(F, zero(MOI.ScalarAffineFunction{T})) end +function MOI.get(o::ObjectiveContainer, ::MOI.ObjectiveFunction{F}) where {F} + return copy(MOI.get(o, UnsafeObjectiveFunction{F}())) +end + function _empty_keeping_sense(o::ObjectiveContainer) sense, is_sense_set = o.sense, o.is_sense_set MOI.empty!(o) diff --git a/src/Utilities/universalfallback.jl b/src/Utilities/universalfallback.jl index 8a6f9aa063..972c060f5a 100644 --- a/src/Utilities/universalfallback.jl +++ b/src/Utilities/universalfallback.jl @@ -534,7 +534,7 @@ end function MOI.get( uf::UniversalFallback, - attr::MOI.ObjectiveFunction{F}, + attr::Union{UnsafeObjectiveFunction{F},MOI.ObjectiveFunction{F}}, )::F where {F} if uf.objective === nothing return MOI.get(uf.model, attr) @@ -866,7 +866,11 @@ end function MOI.get( uf::UniversalFallback, - attr::Union{MOI.ConstraintFunction,MOI.ConstraintSet}, + attr::Union{ + UnsafeConstraintFunction, + MOI.ConstraintFunction, + MOI.ConstraintSet, + }, ci::MOI.ConstraintIndex, ) return MOI.get(constraints(uf, ci), attr, ci) diff --git a/src/Utilities/variables_container.jl b/src/Utilities/variables_container.jl index 23f60c71f9..da8f2ef6e9 100644 --- a/src/Utilities/variables_container.jl +++ b/src/Utilities/variables_container.jl @@ -310,7 +310,7 @@ MOI.is_valid(::VariablesContainer, ::MOI.ConstraintIndex) = false function MOI.get( model::VariablesContainer, - ::MOI.ConstraintFunction, + ::Union{UnsafeConstraintFunction,MOI.ConstraintFunction}, ci::MOI.ConstraintIndex{MOI.VariableIndex}, ) MOI.throw_if_not_valid(model, ci) diff --git a/src/Utilities/vector_of_constraints.jl b/src/Utilities/vector_of_constraints.jl index b12b97bd85..7ca1d18d1c 100644 --- a/src/Utilities/vector_of_constraints.jl +++ b/src/Utilities/vector_of_constraints.jl @@ -98,12 +98,20 @@ end function MOI.get( v::VectorOfConstraints{F,S}, - ::MOI.ConstraintFunction, + ::UnsafeConstraintFunction, ci::MOI.ConstraintIndex{F,S}, ) where {F,S} MOI.throw_if_not_valid(v, ci) f, _ = v.constraints[ci]::Tuple{F,S} - return copy(f) + return f +end + +function MOI.get( + v::VectorOfConstraints{F,S}, + ::MOI.ConstraintFunction, + ci::MOI.ConstraintIndex{F,S}, +) where {F,S} + return copy(MOI.get(v, UnsafeConstraintFunction(), ci)) end function MOI.get(