From 82dacaa11a1b0c16cfbc7afdfac12e91ec5933e2 Mon Sep 17 00:00:00 2001 From: odow Date: Thu, 21 Dec 2023 11:07:49 +1300 Subject: [PATCH 1/3] Add Utilities.SortedListOfModelAttributesSet --- docs/src/submodules/Utilities/reference.md | 2 + src/Utilities/copy.jl | 49 ++++++++++++++++++---- src/Utilities/universalfallback.jl | 4 ++ 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/docs/src/submodules/Utilities/reference.md b/docs/src/submodules/Utilities/reference.md index 9fd6a1af7f..17183601e8 100644 --- a/docs/src/submodules/Utilities/reference.md +++ b/docs/src/submodules/Utilities/reference.md @@ -80,6 +80,8 @@ Utilities.IndexMap Utilities.identity_index_map Utilities.ModelFilter Utilities.loadfromstring! +Utilities.SortedListOfModelAttributesSet +Utilities.sort_by_weight ``` ## Penalty relaxation diff --git a/src/Utilities/copy.jl b/src/Utilities/copy.jl index 11a76c3ba9..050c76e10c 100644 --- a/src/Utilities/copy.jl +++ b/src/Utilities/copy.jl @@ -9,9 +9,44 @@ include("copy/index_map.jl") -_sort_priority(::Any) = 2 -_sort_priority(::MOI.UserDefinedFunction) = 0 -_sort_priority(::MOI.ObjectiveSense) = 1 +""" + SortedListOfModelAttributesSet() + +Return the vector of [`MOI.ListOfModelAttributesSet`](@ref), except that the +elements are sorted according to [`sort_by_weight`]. + +During [`MOI.copy_to`](@ref), we need to copy [`MOI.UserDefinedFunction`](@ref)s +first, so that they are in the model before we deal with the objective function +or the constraints. Similarly, we need to [`MOI.ObjectiveSense`](@ref) to be set +before [`MOI.ObjectiveFunction`](@ref) so that bridges which depend on the sense +can be used. +""" +struct SortedListOfModelAttributesSet <: MOI.AbstractModelAttribute end + +function MOI.get_fallback( + model::MOI.ModelLike, + ::SortedListOfModelAttributesSet, +) + attrs = MOI.get(model, MOI.ListOfModelAttributesSet()) + return sort(attrs; by = sort_by_weight) +end + +""" + sort_by_weight(::MOI.AbstractModelAttribute) --> Float64 + +The weights used to sort elements in [`SortedListOfModelAttributesSet`](@ref). + +The default weights are: + + * `sort_by_weight(::MOI.UserDefinedFunction) = 0.0` + * `sort_by_weight(::MOI.ObjectiveSense) = 10.0` + * `sort_by_weight(::MOI.ObjectiveFunction) = 20.0` + * `sort_by_weight(::MOI.AbstractModelAttribute) = 30.0` +""" +sort_by_weight(::MOI.UserDefinedFunction) = 0.0 +sort_by_weight(::MOI.ObjectiveSense) = 10.0 +sort_by_weight(::MOI.ObjectiveFunction) = 20.0 +sort_by_weight(::MOI.AbstractModelAttribute) = 30.0 """ pass_attributes( @@ -27,12 +62,7 @@ function pass_attributes( src::MOI.ModelLike, index_map::IndexMap, ) - attrs = MOI.get(src, MOI.ListOfModelAttributesSet()) - # We need to deal with the UserDefinedFunctions first, so that they are in - # the model before we deal with the objective function or the constraints. - # We also need `ObjectiveSense` to be set before `ObjectiveFunction`. - sort!(attrs; by = _sort_priority) - for attr in attrs + for attr in MOI.get(src, SortedListOfModelAttributesSet()) if !MOI.supports(dest, attr) if attr == MOI.Name() continue # Skipping names is okay. @@ -591,6 +621,7 @@ function MOI.get( MOI.ListOfConstraintTypesPresent, MOI.ListOfModelAttributesSet, MOI.ListOfVariableAttributesSet, + SortedListOfModelAttributesSet, }, ) return filter(model.filter, MOI.get(model.inner, attr)) diff --git a/src/Utilities/universalfallback.jl b/src/Utilities/universalfallback.jl index e167fcd184..218bc3c5cd 100644 --- a/src/Utilities/universalfallback.jl +++ b/src/Utilities/universalfallback.jl @@ -503,6 +503,10 @@ function MOI.get(uf::UniversalFallback, listattr::MOI.ListOfModelAttributesSet) return list end +function MOI.get(uf::UniversalFallback, attr::SortedListOfModelAttributesSet) + return MOI.get_fallback(uf, attr) +end + function MOI.get( uf::UniversalFallback, listattr::MOI.ListOfVariableAttributesSet, From 3359e5641bd432b101fedcca73bd9d04f080759b Mon Sep 17 00:00:00 2001 From: odow Date: Thu, 21 Dec 2023 13:15:51 +1300 Subject: [PATCH 2/3] Add tests --- test/Utilities/copy.jl | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/Utilities/copy.jl b/test/Utilities/copy.jl index c102f99194..f1b2a45346 100644 --- a/test/Utilities/copy.jl +++ b/test/Utilities/copy.jl @@ -935,6 +935,30 @@ function test_sorted_variable_sets_by_cost_2() return end +function test_sorted_copy_to() + src = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()) + x = MOI.add_variable(src) + f = MOI.ScalarNonlinearFunction(:sqr, Any[x]) + attr_1 = MOI.UserDefinedFunction(:sqr, 1) + attr_2 = MOI.ObjectiveSense() + attr_3 = MOI.ObjectiveFunction{typeof(f)}() + attr_4 = MOI.Name() + MOI.set(src, attr_4, "abc") + MOI.set(src, attr_1, (sqrt,)) + MOI.set(src, attr_3, f) + MOI.set(src, attr_2, MOI.MAX_SENSE) + @test MOI.get(src, MOI.Utilities.SortedListOfModelAttributesSet()) == + [attr_1, attr_2, attr_3, attr_4] + dest = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()) + index_map = MOI.copy_to(dest, src) + @test MOI.get(dest, attr_1) == (sqrt,) + @test MOI.get(dest, attr_2) == MOI.MAX_SENSE + g = MOI.ScalarNonlinearFunction(:sqr, Any[index_map[x]]) + @test ≈(g, MOI.get(dest, attr_3)) + @test MOI.get(dest, attr_4) == "abc" + return +end + end # module TestCopy.runtests() From eced03d50ac0208dcc1e95e923c7888b1cb7cb37 Mon Sep 17 00:00:00 2001 From: odow Date: Thu, 21 Dec 2023 14:09:17 +1300 Subject: [PATCH 3/3] Update --- docs/src/submodules/Utilities/reference.md | 4 +-- src/Utilities/copy.jl | 36 +++++++++------------- src/Utilities/universalfallback.jl | 4 --- test/Utilities/copy.jl | 2 +- 4 files changed, 18 insertions(+), 28 deletions(-) diff --git a/docs/src/submodules/Utilities/reference.md b/docs/src/submodules/Utilities/reference.md index 17183601e8..41b6c08ec9 100644 --- a/docs/src/submodules/Utilities/reference.md +++ b/docs/src/submodules/Utilities/reference.md @@ -80,8 +80,8 @@ Utilities.IndexMap Utilities.identity_index_map Utilities.ModelFilter Utilities.loadfromstring! -Utilities.SortedListOfModelAttributesSet -Utilities.sort_by_weight +Utilities.sorted_list_of_model_attributes +Utilities.sorted_list_of_model_attributes_weight ``` ## Penalty relaxation diff --git a/src/Utilities/copy.jl b/src/Utilities/copy.jl index 050c76e10c..f7d80fefbf 100644 --- a/src/Utilities/copy.jl +++ b/src/Utilities/copy.jl @@ -10,10 +10,10 @@ include("copy/index_map.jl") """ - SortedListOfModelAttributesSet() + sorted_list_of_model_attributes(model::MOI.ModelLike) Return the vector of [`MOI.ListOfModelAttributesSet`](@ref), except that the -elements are sorted according to [`sort_by_weight`]. +elements are sorted according to [`sorted_list_of_model_attributes`](@ref). During [`MOI.copy_to`](@ref), we need to copy [`MOI.UserDefinedFunction`](@ref)s first, so that they are in the model before we deal with the objective function @@ -21,32 +21,27 @@ or the constraints. Similarly, we need to [`MOI.ObjectiveSense`](@ref) to be set before [`MOI.ObjectiveFunction`](@ref) so that bridges which depend on the sense can be used. """ -struct SortedListOfModelAttributesSet <: MOI.AbstractModelAttribute end - -function MOI.get_fallback( - model::MOI.ModelLike, - ::SortedListOfModelAttributesSet, -) +function sorted_list_of_model_attributes(model::MOI.ModelLike) attrs = MOI.get(model, MOI.ListOfModelAttributesSet()) - return sort(attrs; by = sort_by_weight) + return sort(attrs; by = sorted_list_of_model_attributes_weight) end """ - sort_by_weight(::MOI.AbstractModelAttribute) --> Float64 + sorted_list_of_model_attributes_weight(::MOI.AbstractModelAttribute) --> Float64 -The weights used to sort elements in [`SortedListOfModelAttributesSet`](@ref). +The weights used to sort elements in [`sorted_list_of_model_attributes`](@ref). The default weights are: - * `sort_by_weight(::MOI.UserDefinedFunction) = 0.0` - * `sort_by_weight(::MOI.ObjectiveSense) = 10.0` - * `sort_by_weight(::MOI.ObjectiveFunction) = 20.0` - * `sort_by_weight(::MOI.AbstractModelAttribute) = 30.0` + * `sorted_list_of_model_attributes_weight(::MOI.UserDefinedFunction) = 0.0` + * `sorted_list_of_model_attributes_weight(::MOI.ObjectiveSense) = 10.0` + * `sorted_list_of_model_attributes_weight(::MOI.ObjectiveFunction) = 20.0` + * `sorted_list_of_model_attributes_weight(::MOI.AbstractModelAttribute) = 30.0` """ -sort_by_weight(::MOI.UserDefinedFunction) = 0.0 -sort_by_weight(::MOI.ObjectiveSense) = 10.0 -sort_by_weight(::MOI.ObjectiveFunction) = 20.0 -sort_by_weight(::MOI.AbstractModelAttribute) = 30.0 +sorted_list_of_model_attributes_weight(::MOI.UserDefinedFunction) = 0.0 +sorted_list_of_model_attributes_weight(::MOI.ObjectiveSense) = 10.0 +sorted_list_of_model_attributes_weight(::MOI.ObjectiveFunction) = 20.0 +sorted_list_of_model_attributes_weight(::MOI.AbstractModelAttribute) = 30.0 """ pass_attributes( @@ -62,7 +57,7 @@ function pass_attributes( src::MOI.ModelLike, index_map::IndexMap, ) - for attr in MOI.get(src, SortedListOfModelAttributesSet()) + for attr in sorted_list_of_model_attributes(src) if !MOI.supports(dest, attr) if attr == MOI.Name() continue # Skipping names is okay. @@ -621,7 +616,6 @@ function MOI.get( MOI.ListOfConstraintTypesPresent, MOI.ListOfModelAttributesSet, MOI.ListOfVariableAttributesSet, - SortedListOfModelAttributesSet, }, ) return filter(model.filter, MOI.get(model.inner, attr)) diff --git a/src/Utilities/universalfallback.jl b/src/Utilities/universalfallback.jl index 218bc3c5cd..e167fcd184 100644 --- a/src/Utilities/universalfallback.jl +++ b/src/Utilities/universalfallback.jl @@ -503,10 +503,6 @@ function MOI.get(uf::UniversalFallback, listattr::MOI.ListOfModelAttributesSet) return list end -function MOI.get(uf::UniversalFallback, attr::SortedListOfModelAttributesSet) - return MOI.get_fallback(uf, attr) -end - function MOI.get( uf::UniversalFallback, listattr::MOI.ListOfVariableAttributesSet, diff --git a/test/Utilities/copy.jl b/test/Utilities/copy.jl index f1b2a45346..53cf7dda77 100644 --- a/test/Utilities/copy.jl +++ b/test/Utilities/copy.jl @@ -947,7 +947,7 @@ function test_sorted_copy_to() MOI.set(src, attr_1, (sqrt,)) MOI.set(src, attr_3, f) MOI.set(src, attr_2, MOI.MAX_SENSE) - @test MOI.get(src, MOI.Utilities.SortedListOfModelAttributesSet()) == + @test MOI.Utilities.sorted_list_of_model_attributes(src) == [attr_1, attr_2, attr_3, attr_4] dest = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()) index_map = MOI.copy_to(dest, src)