Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Utilities.sorted_list_of_model_attributes #2371

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/src/submodules/Utilities/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ Utilities.IndexMap
Utilities.identity_index_map
Utilities.ModelFilter
Utilities.loadfromstring!
Utilities.sorted_list_of_model_attributes
Utilities.sorted_list_of_model_attributes_weight
```

## Penalty relaxation
Expand Down
43 changes: 34 additions & 9 deletions src/Utilities/copy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,39 @@

include("copy/index_map.jl")

_sort_priority(::Any) = 2
_sort_priority(::MOI.UserDefinedFunction) = 0
_sort_priority(::MOI.ObjectiveSense) = 1
Copy link
Member Author

@odow odow Dec 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So in retrospect, all this PR really needed was _sort_priority(::Any) = 3 and _sort_priority(::MOI.ObjectiveFunction) = 2.

Do we want to make this all public?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would do this simple fix, and reopen this PR if this keeps coming back and someone actually needs to extend this kind of methods.

"""
sorted_list_of_model_attributes(model::MOI.ModelLike)

Return the vector of [`MOI.ListOfModelAttributesSet`](@ref), except that the
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
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.
"""
function sorted_list_of_model_attributes(model::MOI.ModelLike)
attrs = MOI.get(model, MOI.ListOfModelAttributesSet())
return sort(attrs; by = sorted_list_of_model_attributes_weight)
end

"""
sorted_list_of_model_attributes_weight(::MOI.AbstractModelAttribute) --> Float64

The weights used to sort elements in [`sorted_list_of_model_attributes`](@ref).

The default weights are:

* `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`
"""
sorted_list_of_model_attributes_weight(::MOI.UserDefinedFunction) = 0.0

Check warning on line 41 in src/Utilities/copy.jl

View check run for this annotation

Codecov / codecov/patch

src/Utilities/copy.jl#L41

Added line #L41 was not covered by tests
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

Check warning on line 44 in src/Utilities/copy.jl

View check run for this annotation

Codecov / codecov/patch

src/Utilities/copy.jl#L44

Added line #L44 was not covered by tests

"""
pass_attributes(
Expand All @@ -27,12 +57,7 @@
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 sorted_list_of_model_attributes(src)
if !MOI.supports(dest, attr)
if attr == MOI.Name()
continue # Skipping names is okay.
Expand Down
24 changes: 24 additions & 0 deletions test/Utilities/copy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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.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)
@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()
Loading