From 15b74839a4f876db64567c5d3d4894747cd9ff4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Sun, 14 Mar 2021 00:13:35 +0100 Subject: [PATCH 1/2] Pass copy operation for non-variable constraints --- src/Bridges/bridge_optimizer.jl | 41 +++++++++++++++ src/Utilities/cachingoptimizer.jl | 3 +- src/Utilities/copy.jl | 84 ++++++++++++++++++++++++++---- src/Utilities/model.jl | 22 ++++++++ src/Utilities/universalfallback.jl | 83 +++++++++++++++++++++++++++++ test/Utilities/copy.jl | 74 ++++++++++++++++++++++++++ 6 files changed, 297 insertions(+), 10 deletions(-) diff --git a/src/Bridges/bridge_optimizer.jl b/src/Bridges/bridge_optimizer.jl index 7599be8b02..bc23d87ab6 100644 --- a/src/Bridges/bridge_optimizer.jl +++ b/src/Bridges/bridge_optimizer.jl @@ -320,6 +320,47 @@ function MOI.supports( return MOI.supports(b.model, attr) end +function MOIU.pass_nonvariable_constraints( + dest::AbstractBridgeOptimizer, + src::MOI.ModelLike, + copy_names::Bool, + idxmap::MOIU.IndexMap, + constraint_types, + pass_cons, + pass_attr; + filter_constraints::Union{Nothing,Function} = nothing, +) + not_bridged_types = eltype(constraint_types)[] + bridged_types = eltype(constraint_types)[] + for (F, S) in constraint_types + if is_bridged(dest, F, S) + push!(bridged_types, (F, S)) + else + push!(not_bridged_types, (F, S)) + end + end + MOIU.pass_nonvariable_constraints( + dest.model, + src, + copy_names, + idxmap, + not_bridged_types, + pass_cons, + pass_attr; + filter_constraints = filter_constraints, + ) + MOIU.pass_nonvariable_constraints_fallback( + dest, + src, + copy_names, + idxmap, + bridged_types, + pass_cons, + pass_attr; + filter_constraints = filter_constraints, + ) +end + function MOI.copy_to(mock::AbstractBridgeOptimizer, src::MOI.ModelLike; kws...) return MOIU.automatic_copy_to(mock, src; kws...) end diff --git a/src/Utilities/cachingoptimizer.jl b/src/Utilities/cachingoptimizer.jl index 58c2b4b4a0..4c721ddebc 100644 --- a/src/Utilities/cachingoptimizer.jl +++ b/src/Utilities/cachingoptimizer.jl @@ -207,7 +207,8 @@ function _standardize(d::IndexMap) end function MOI.copy_to(m::CachingOptimizer, src::MOI.ModelLike; kws...) - return automatic_copy_to(m, src; kws...) + m.state == ATTACHED_OPTIMIZER && reset_optimizer(m) + return MOI.copy_to(m.model_cache, src; kws...) end function supports_default_copy_to(model::CachingOptimizer, copy_names::Bool) return supports_default_copy_to(model.model_cache, copy_names) diff --git a/src/Utilities/copy.jl b/src/Utilities/copy.jl index 8b73d4cd40..198cd3c55b 100644 --- a/src/Utilities/copy.jl +++ b/src/Utilities/copy.jl @@ -422,6 +422,71 @@ function copy_constraints( end end +function pass_nonvariable_constraints_fallback( + dest::MOI.ModelLike, + src::MOI.ModelLike, + copy_names::Bool, + idxmap::IndexMap, + constraint_types, + pass_cons = copy_constraints, + pass_attr = MOI.set; + filter_constraints::Union{Nothing,Function} = nothing, +) + for (F, S) in constraint_types + cis_src = MOI.get(src, MOI.ListOfConstraintIndices{F,S}()) + if filter_constraints !== nothing + filter!(filter_constraints, cis_src) + end + # do the rest in `pass_cons` which is type stable + pass_cons(dest, src, idxmap, cis_src) + pass_attributes(dest, src, copy_names, idxmap, cis_src, pass_attr) + end +end + +""" + pass_nonvariable_constraints( + dest::MOI.ModelLike, + src::MOI.ModelLike, + copy_names::Bool, + idxmap::IndexMap, + constraint_types, + pass_cons = copy_constraints, + pass_attr = MOI.set; + filter_constraints::Union{Nothing,Function} = nothing, + ) + +For all tuples `(F, S)` in `constraint_types`, copy all constraints of type +`F`-in-`S` from `src` to `dest` mapping the variables indices with `idxmap`. +If `filter_constraints` is not nothing, only indices `ci` such that +`filter_constraints(ci)` is true are copied. + +The default implementation calls `pass_nonvariable_constraints_fallback` which +copies the constraints with `pass_cons` and their attributes with `pass_attr`. +A method can be implemented to use a specialized copy for a given type of +`dest`. +""" +function pass_nonvariable_constraints( + dest::MOI.ModelLike, + src::MOI.ModelLike, + copy_names::Bool, + idxmap::IndexMap, + constraint_types, + pass_cons = copy_constraints, + pass_attr = MOI.set; + filter_constraints::Union{Nothing,Function} = nothing, +) + pass_nonvariable_constraints_fallback( + dest, + src, + copy_names, + idxmap, + constraint_types, + pass_cons, + pass_attr; + filter_constraints = filter_constraints, + ) +end + function pass_constraints( dest::MOI.ModelLike, src::MOI.ModelLike, @@ -473,15 +538,16 @@ function pass_constraints( (F, S) for (F, S) in MOI.get(src, MOI.ListOfConstraints()) if F != MOI.SingleVariable && F != MOI.VectorOfVariables ] - for (F, S) in nonvariable_constraint_types - cis_src = MOI.get(src, MOI.ListOfConstraintIndices{F,S}()) - if filter_constraints !== nothing - filter!(filter_constraints, cis_src) - end - # do the rest in `pass_cons` which is type stable - pass_cons(dest, src, idxmap, cis_src) - pass_attributes(dest, src, copy_names, idxmap, cis_src, pass_attr) - end + pass_nonvariable_constraints( + dest, + src, + copy_names, + idxmap, + nonvariable_constraint_types, + pass_cons, + pass_attr; + filter_constraints = filter_constraints, + ) end function copy_free_variables( diff --git a/src/Utilities/model.jl b/src/Utilities/model.jl index 8b8c6e859e..198851acb7 100644 --- a/src/Utilities/model.jl +++ b/src/Utilities/model.jl @@ -752,6 +752,28 @@ function MOI.empty!(model::AbstractModel{T}) where {T} return end +function pass_nonvariable_constraints( + dest::AbstractModel, + src::MOI.ModelLike, + copy_names::Bool, + idxmap::IndexMap, + constraint_types, + pass_cons, + pass_attr; + filter_constraints::Union{Nothing,Function} = nothing, +) + pass_nonvariable_constraints( + dest.constraints, + src, + copy_names, + idxmap, + constraint_types, + pass_cons, + pass_attr; + filter_constraints = filter_constraints, + ) +end + function MOI.copy_to(dest::AbstractModel, src::MOI.ModelLike; kws...) return automatic_copy_to(dest, src; kws...) end diff --git a/src/Utilities/universalfallback.jl b/src/Utilities/universalfallback.jl index 892e6bfc17..7cbebd0af9 100644 --- a/src/Utilities/universalfallback.jl +++ b/src/Utilities/universalfallback.jl @@ -86,6 +86,89 @@ function MOI.empty!(uf::UniversalFallback) return end +function _pass_unsupported_attributes( + dest::UniversalFallback, + src::MOI.ModelLike, + copy_names::Bool, + idxmap::IndexMap, + pass_attr::Function, + ::Type{F}, + ::Type{S}, +) where {F,S} + # Copy constraint attributes + attrs = MOI.get(src, MOI.ListOfConstraintAttributesSet{F,S}()) + attrs = filter(attrs) do attr + return !MOI.supports(dest.model, attr, MOI.ConstraintIndex{F,S}) && + (copy_names || !(attr isa MOI.ConstraintName)) + end + if !isempty(attrs) # If `attrs` is empty, we can spare the computation of `cis_dest` + cis_src = MOI.get(src, MOI.ListOfConstraintIndices{F,S}()) + cis_dest = map(ci -> idxmap[ci], cis_src) + _pass_attributes( + dest, + src, + idxmap, + attrs, + (MOI.ConstraintIndex{F,S},), + (cis_src,), + (cis_dest,), + pass_attr, + ) + end +end + +function pass_nonvariable_constraints( + dest::UniversalFallback, + src::MOI.ModelLike, + copy_names::Bool, + idxmap::IndexMap, + constraint_types, + pass_cons, + pass_attr; + filter_constraints::Union{Nothing,Function} = nothing, +) + supported_types = eltype(constraint_types)[] + unsupported_types = eltype(constraint_types)[] + for (F, S) in constraint_types + if MOI.supports_constraint(dest.model, F, S) + push!(supported_types, (F, S)) + else + push!(unsupported_types, (F, S)) + end + end + pass_nonvariable_constraints( + dest.model, + src, + copy_names, + idxmap, + supported_types, + pass_cons, + pass_attr; + filter_constraints = filter_constraints, + ) + for (F, S) in supported_types + _pass_unsupported_attributes( + dest, + src, + copy_names, + idxmap, + pass_attr, + F, + S, + ) + end + pass_nonvariable_constraints_fallback( + dest, + src, + copy_names, + idxmap, + unsupported_types, + pass_cons, + pass_attr; + filter_constraints = filter_constraints, + ) +end + function MOI.copy_to(uf::UniversalFallback, src::MOI.ModelLike; kws...) return MOIU.automatic_copy_to(uf, src; kws...) end diff --git a/test/Utilities/copy.jl b/test/Utilities/copy.jl index 5ac74e9afb..ff09c53edb 100644 --- a/test/Utilities/copy.jl +++ b/test/Utilities/copy.jl @@ -620,3 +620,77 @@ end MOI.NumberOfConstraints{MOI.SingleVariable,MOI.Integer}(), ) == 0 end + +# We create a `OnlyCopyConstraints` that don't implement `add_constraint` but +# implements `pass_nonvariable_constraints` to check that this is passed accross +# all layers without falling back to `pass_nonvariable_constraints_fallback` +# which calls `add_constraint`. + +struct OnlyCopyConstraints{F,S} <: MOI.ModelLike + constraints::MOIU.VectorOfConstraints{F,S} + function OnlyCopyConstraints{F,S}() where {F,S} + return new{F,S}(MOIU.VectorOfConstraints{F,S}()) + end +end +MOI.empty!(model::OnlyCopyConstraints) = MOI.empty!(model.constraints) +function MOI.supports_constraint( + model::OnlyCopyConstraints, + F::Type{<:MOI.AbstractFunction}, + S::Type{<:MOI.AbstractSet}, +) + return MOI.supports_constraint(model.constraints, F, S) +end +function MOIU.pass_nonvariable_constraints( + dest::OnlyCopyConstraints, + src::MOI.ModelLike, + copy_names::Bool, + idxmap::MOIU.IndexMap, + constraint_types, + pass_cons, + pass_attr; + filter_constraints::Union{Nothing,Function} = nothing, +) + MOIU.pass_nonvariable_constraints( + dest.constraints, + src, + copy_names, + idxmap, + constraint_types, + pass_cons, + pass_attr; + filter_constraints = filter_constraints, + ) +end + +function test_pass_copy(::Type{T}) where {T} + F = MOI.ScalarAffineFunction{T} + S = MOI.EqualTo{T} + S2 = MOI.GreaterThan{T} + src = MOIU.Model{T}() + x = MOI.add_variable(src) + fx = MOI.SingleVariable(x) + MOI.add_constraint(src, T(1) * fx, MOI.EqualTo(T(1))) + MOI.add_constraint(src, T(2) * fx, MOI.EqualTo(T(2))) + MOI.add_constraint(src, T(3) * fx, MOI.GreaterThan(T(3))) + MOI.add_constraint(src, T(4) * fx, MOI.GreaterThan(T(4))) + dest = MOIU.CachingOptimizer( + MOI.Bridges.full_bridge_optimizer( + MOIU.UniversalFallback( + MOIU.GenericOptimizer{T,OnlyCopyConstraints{F,S}}() + ), + T, + ), + MOIU.AUTOMATIC, + ) + MOI.copy_to(dest, src) + voc = dest.model_cache.model.model.constraints.constraints + @test MOI.get(voc, MOI.NumberOfConstraints{F,S}()) == 2 + @test !haskey(dest.model_cache.model.constraints, (F,S)) + @test MOI.get(dest, MOI.NumberOfConstraints{F,S2}()) == 2 + @test haskey(dest.model_cache.model.constraints, (F,S2)) +end + +@testset "copy of constraints passed as copy accross layers" begin + test_pass_copy(Int) + test_pass_copy(Float64) +end From 62064273dc06b5701117c4525361b26bd209b8e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Sun, 21 Mar 2021 17:24:46 +0100 Subject: [PATCH 2/2] Pass attributes separately --- src/Bridges/bridge_optimizer.jl | 14 +++----- src/Test/modellike.jl | 20 ++++++----- src/Utilities/copy.jl | 31 ++++++++--------- src/Utilities/model.jl | 10 ++---- src/Utilities/universalfallback.jl | 56 +++--------------------------- test/Utilities/copy.jl | 22 ++++++------ 6 files changed, 46 insertions(+), 107 deletions(-) diff --git a/src/Bridges/bridge_optimizer.jl b/src/Bridges/bridge_optimizer.jl index bc23d87ab6..3949f148e4 100644 --- a/src/Bridges/bridge_optimizer.jl +++ b/src/Bridges/bridge_optimizer.jl @@ -323,11 +323,9 @@ end function MOIU.pass_nonvariable_constraints( dest::AbstractBridgeOptimizer, src::MOI.ModelLike, - copy_names::Bool, idxmap::MOIU.IndexMap, constraint_types, - pass_cons, - pass_attr; + pass_cons; filter_constraints::Union{Nothing,Function} = nothing, ) not_bridged_types = eltype(constraint_types)[] @@ -342,21 +340,17 @@ function MOIU.pass_nonvariable_constraints( MOIU.pass_nonvariable_constraints( dest.model, src, - copy_names, idxmap, not_bridged_types, - pass_cons, - pass_attr; + pass_cons; filter_constraints = filter_constraints, ) - MOIU.pass_nonvariable_constraints_fallback( + return MOIU.pass_nonvariable_constraints_fallback( dest, src, - copy_names, idxmap, bridged_types, - pass_cons, - pass_attr; + pass_cons; filter_constraints = filter_constraints, ) end diff --git a/src/Test/modellike.jl b/src/Test/modellike.jl index b1bc9e82d8..9d51eda101 100644 --- a/src/Test/modellike.jl +++ b/src/Test/modellike.jl @@ -783,7 +783,7 @@ function start_values_test(dest::MOI.ModelLike, src::MOI.ModelLike) end end -function copytest(dest::MOI.ModelLike, src::MOI.ModelLike) +function copytest(dest::MOI.ModelLike, src::MOI.ModelLike; copy_names = false) @test MOIU.supports_default_copy_to(src, true) #=copy_names=# MOI.empty!(src) MOI.empty!(dest) @@ -850,13 +850,15 @@ function copytest(dest::MOI.ModelLike, src::MOI.ModelLike) MOI.Zeros, ) - dict = MOI.copy_to(dest, src, copy_names = false) + dict = MOI.copy_to(dest, src, copy_names = copy_names) - @test !MOI.supports(dest, MOI.Name()) || MOI.get(dest, MOI.Name()) == "" + dest_name(src_name) = copy_names ? src_name : "" + @test !MOI.supports(dest, MOI.Name()) || + MOI.get(dest, MOI.Name()) == dest_name("ModelName") @test MOI.get(dest, MOI.NumberOfVariables()) == 4 if MOI.supports(dest, MOI.VariableName(), MOI.VariableIndex) - for vi in v - MOI.get(dest, MOI.VariableName(), dict[vi]) == "" + for i in eachindex(v) + MOI.get(dest, MOI.VariableName(), dict[v[i]]) == dest_name("var$i") end end @test MOI.get( @@ -908,17 +910,17 @@ function copytest(dest::MOI.ModelLike, src::MOI.ModelLike) @test (MOI.VectorAffineFunction{Float64}, MOI.Zeros) in loc @test !MOI.supports(dest, MOI.ConstraintName(), typeof(csv)) || - MOI.get(dest, MOI.ConstraintName(), dict[csv]) == "" + MOI.get(dest, MOI.ConstraintName(), dict[csv]) == dest_name("csv") @test MOI.get(dest, MOI.ConstraintFunction(), dict[csv]) == MOI.SingleVariable(dict[w]) @test MOI.get(dest, MOI.ConstraintSet(), dict[csv]) == MOI.EqualTo(2.0) @test !MOI.supports(dest, MOI.ConstraintName(), typeof(cvv)) || - MOI.get(dest, MOI.ConstraintName(), dict[cvv]) == "" + MOI.get(dest, MOI.ConstraintName(), dict[cvv]) == dest_name("cvv") @test MOI.get(dest, MOI.ConstraintFunction(), dict[cvv]) == MOI.VectorOfVariables(getindex.(Ref(dict), v)) @test MOI.get(dest, MOI.ConstraintSet(), dict[cvv]) == MOI.Nonnegatives(3) @test !MOI.supports(dest, MOI.ConstraintName(), typeof(csa)) || - MOI.get(dest, MOI.ConstraintName(), dict[csa]) == "" + MOI.get(dest, MOI.ConstraintName(), dict[csa]) == dest_name("csa") @test MOI.get(dest, MOI.ConstraintFunction(), dict[csa]) ≈ MOI.ScalarAffineFunction( MOI.ScalarAffineTerm.([1.0, 3.0], [dict[v[3]], dict[v[1]]]), @@ -926,7 +928,7 @@ function copytest(dest::MOI.ModelLike, src::MOI.ModelLike) ) @test MOI.get(dest, MOI.ConstraintSet(), dict[csa]) == MOI.LessThan(2.0) @test !MOI.supports(dest, MOI.ConstraintName(), typeof(cva)) || - MOI.get(dest, MOI.ConstraintName(), dict[cva]) == "" + MOI.get(dest, MOI.ConstraintName(), dict[cva]) == dest_name("cva") @test MOI.get(dest, MOI.ConstraintFunction(), dict[cva]) ≈ MOI.VectorAffineFunction( MOI.VectorAffineTerm.( diff --git a/src/Utilities/copy.jl b/src/Utilities/copy.jl index 198cd3c55b..74995ac7af 100644 --- a/src/Utilities/copy.jl +++ b/src/Utilities/copy.jl @@ -425,11 +425,9 @@ end function pass_nonvariable_constraints_fallback( dest::MOI.ModelLike, src::MOI.ModelLike, - copy_names::Bool, idxmap::IndexMap, constraint_types, - pass_cons = copy_constraints, - pass_attr = MOI.set; + pass_cons = copy_constraints; filter_constraints::Union{Nothing,Function} = nothing, ) for (F, S) in constraint_types @@ -439,7 +437,6 @@ function pass_nonvariable_constraints_fallback( end # do the rest in `pass_cons` which is type stable pass_cons(dest, src, idxmap, cis_src) - pass_attributes(dest, src, copy_names, idxmap, cis_src, pass_attr) end end @@ -447,11 +444,9 @@ end pass_nonvariable_constraints( dest::MOI.ModelLike, src::MOI.ModelLike, - copy_names::Bool, idxmap::IndexMap, constraint_types, - pass_cons = copy_constraints, - pass_attr = MOI.set; + pass_cons = copy_constraints; filter_constraints::Union{Nothing,Function} = nothing, ) @@ -468,21 +463,17 @@ A method can be implemented to use a specialized copy for a given type of function pass_nonvariable_constraints( dest::MOI.ModelLike, src::MOI.ModelLike, - copy_names::Bool, idxmap::IndexMap, constraint_types, - pass_cons = copy_constraints, - pass_attr = MOI.set; + pass_cons = copy_constraints; filter_constraints::Union{Nothing,Function} = nothing, ) - pass_nonvariable_constraints_fallback( + return pass_nonvariable_constraints_fallback( dest, src, - copy_names, idxmap, constraint_types, - pass_cons, - pass_attr; + pass_cons; filter_constraints = filter_constraints, ) end @@ -541,13 +532,19 @@ function pass_constraints( pass_nonvariable_constraints( dest, src, - copy_names, idxmap, nonvariable_constraint_types, - pass_cons, - pass_attr; + pass_cons; filter_constraints = filter_constraints, ) + for (F, S) in nonvariable_constraint_types + cis_src = MOI.get(src, MOI.ListOfConstraintIndices{F,S}()) + if filter_constraints !== nothing + filter!(filter_constraints, cis_src) + end + # do the rest in `pass_cons` which is type stable + pass_attributes(dest, src, copy_names, idxmap, cis_src, pass_attr) + end end function copy_free_variables( diff --git a/src/Utilities/model.jl b/src/Utilities/model.jl index 198851acb7..f9c7aaa0dc 100644 --- a/src/Utilities/model.jl +++ b/src/Utilities/model.jl @@ -755,21 +755,17 @@ end function pass_nonvariable_constraints( dest::AbstractModel, src::MOI.ModelLike, - copy_names::Bool, idxmap::IndexMap, constraint_types, - pass_cons, - pass_attr; + pass_cons; filter_constraints::Union{Nothing,Function} = nothing, ) - pass_nonvariable_constraints( + return pass_nonvariable_constraints( dest.constraints, src, - copy_names, idxmap, constraint_types, - pass_cons, - pass_attr; + pass_cons; filter_constraints = filter_constraints, ) end diff --git a/src/Utilities/universalfallback.jl b/src/Utilities/universalfallback.jl index 7cbebd0af9..e23bfcf611 100644 --- a/src/Utilities/universalfallback.jl +++ b/src/Utilities/universalfallback.jl @@ -86,45 +86,12 @@ function MOI.empty!(uf::UniversalFallback) return end -function _pass_unsupported_attributes( - dest::UniversalFallback, - src::MOI.ModelLike, - copy_names::Bool, - idxmap::IndexMap, - pass_attr::Function, - ::Type{F}, - ::Type{S}, -) where {F,S} - # Copy constraint attributes - attrs = MOI.get(src, MOI.ListOfConstraintAttributesSet{F,S}()) - attrs = filter(attrs) do attr - return !MOI.supports(dest.model, attr, MOI.ConstraintIndex{F,S}) && - (copy_names || !(attr isa MOI.ConstraintName)) - end - if !isempty(attrs) # If `attrs` is empty, we can spare the computation of `cis_dest` - cis_src = MOI.get(src, MOI.ListOfConstraintIndices{F,S}()) - cis_dest = map(ci -> idxmap[ci], cis_src) - _pass_attributes( - dest, - src, - idxmap, - attrs, - (MOI.ConstraintIndex{F,S},), - (cis_src,), - (cis_dest,), - pass_attr, - ) - end -end - function pass_nonvariable_constraints( dest::UniversalFallback, src::MOI.ModelLike, - copy_names::Bool, idxmap::IndexMap, constraint_types, - pass_cons, - pass_attr; + pass_cons; filter_constraints::Union{Nothing,Function} = nothing, ) supported_types = eltype(constraint_types)[] @@ -139,32 +106,17 @@ function pass_nonvariable_constraints( pass_nonvariable_constraints( dest.model, src, - copy_names, idxmap, supported_types, - pass_cons, - pass_attr; + pass_cons; filter_constraints = filter_constraints, ) - for (F, S) in supported_types - _pass_unsupported_attributes( - dest, - src, - copy_names, - idxmap, - pass_attr, - F, - S, - ) - end - pass_nonvariable_constraints_fallback( + return pass_nonvariable_constraints_fallback( dest, src, - copy_names, idxmap, unsupported_types, - pass_cons, - pass_attr; + pass_cons; filter_constraints = filter_constraints, ) end diff --git a/test/Utilities/copy.jl b/test/Utilities/copy.jl index ff09c53edb..4e45549330 100644 --- a/test/Utilities/copy.jl +++ b/test/Utilities/copy.jl @@ -45,7 +45,8 @@ end MOIT.failcopytestia(model) MOIT.failcopytestva(model) MOIT.failcopytestca(model) - MOIT.copytest(model, MOIU.Model{Float64}()) + MOIT.copytest(model, MOIU.Model{Float64}(), copy_names = false) + MOIT.copytest(model, MOIU.Model{Float64}(), copy_names = true) end @testset "Allocate-Load" begin @test !MOIU.supports_allocate_load(DummyModel(), false) @@ -55,7 +56,8 @@ end MOIT.failcopytestia(mock) MOIT.failcopytestva(mock) MOIT.failcopytestca(mock) - MOIT.copytest(mock, MOIU.Model{Float64}()) + MOIT.copytest(mock, MOIU.Model{Float64}(), copy_names = false) + MOIT.copytest(mock, MOIU.Model{Float64}(), copy_names = true) end struct DummyEvaluator <: MOI.AbstractNLPEvaluator end @@ -643,21 +645,17 @@ end function MOIU.pass_nonvariable_constraints( dest::OnlyCopyConstraints, src::MOI.ModelLike, - copy_names::Bool, idxmap::MOIU.IndexMap, constraint_types, - pass_cons, - pass_attr; + pass_cons; filter_constraints::Union{Nothing,Function} = nothing, ) - MOIU.pass_nonvariable_constraints( + return MOIU.pass_nonvariable_constraints( dest.constraints, src, - copy_names, idxmap, constraint_types, - pass_cons, - pass_attr; + pass_cons; filter_constraints = filter_constraints, ) end @@ -676,7 +674,7 @@ function test_pass_copy(::Type{T}) where {T} dest = MOIU.CachingOptimizer( MOI.Bridges.full_bridge_optimizer( MOIU.UniversalFallback( - MOIU.GenericOptimizer{T,OnlyCopyConstraints{F,S}}() + MOIU.GenericOptimizer{T,OnlyCopyConstraints{F,S}}(), ), T, ), @@ -685,9 +683,9 @@ function test_pass_copy(::Type{T}) where {T} MOI.copy_to(dest, src) voc = dest.model_cache.model.model.constraints.constraints @test MOI.get(voc, MOI.NumberOfConstraints{F,S}()) == 2 - @test !haskey(dest.model_cache.model.constraints, (F,S)) + @test !haskey(dest.model_cache.model.constraints, (F, S)) @test MOI.get(dest, MOI.NumberOfConstraints{F,S2}()) == 2 - @test haskey(dest.model_cache.model.constraints, (F,S2)) + @test haskey(dest.model_cache.model.constraints, (F, S2)) end @testset "copy of constraints passed as copy accross layers" begin