-
Notifications
You must be signed in to change notification settings - Fork 94
Refactor DoubleDicts.jl #1446
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
Refactor DoubleDicts.jl #1446
Conversation
No there are plan to us it in more places than the IndexMap, e.g. UniversalFallback, DiffOpt but it hasn't been done yet. |
My problem with this is that we have a lot of code in MOI that is sitting there un-used on the off-chance that it might be useful in the future. We should tear it out prior to 1.0. We can always add it back later... |
Okay. This needs a pretty thorough review by @joaquimg and @blegat. The changes are actually less scary than the diff seems. It may be best to review in side-by-side mode. The interleaved diff isn't very helpful.
|
Bump @blegat |
Will read tomorrow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use case for ParametricOptInterface would be ci as keys and arrays of Linear/QuadraricTerms as values.
DiffOpt already uses CIs as keys and functions (SAF) as values.
I am planning to test DDs in xpress in the short term. CleverDicts inside double dicta might be nice to consider.
Here is one usage of DoubleDicts in DiffOpt: Here we are not using in POI, but we should be: I should use it here also: |
These use-cases are all fine for |
As long as values have a single type they fall into the simpler version of DoubleDict. The odd one is DiffOpt, which has two DD's, one for scalar and another for vector. It is not clear to me if they should be merged. |
const AD = AbstractDict | ||
|
||
const DataTypePair = Tuple{DataType,DataType} | ||
abstract type AbstractDoubleDict{V} <: AbstractDict{MOI.ConstraintIndex,V} end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we end up with this simple implementation...
We should rename this to ConstraintIndexedDict and reserve DoubleDict for future flexible implementation. Or ConstraintIndexDict or something along those lines.
DoubleDictInner could be SingleTypeConstraintIndexedDict.
IndexDoubleDict would become ConstraintIndexMap...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can get rid of a few haskey's
Yes with DiffOpt, I could just split it in two but in general, it would be nice to have any value type parametrized by |
The right way to do this is for DiffOpt to implement this locally as a subtype of I don't think we should add in this PR. |
Okay. I've addressed the It solves the major issue, and provides a decent fallback for other cases. I'm in favor of merging as-is. |
struct IndexDoubleDict{DI,DO} <: AbstractDoubleDict{DataTypePair,CI,Int64,DI,DO} | ||
dict::DO | ||
struct IndexDoubleDict <: AbstractDoubleDict{MOI.ConstraintIndex} | ||
dict::Dict{Tuple{DataType,DataType},Dict{Int64,Int64}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use a CleverDict
here. With VectorOfConstraints and MatrixOfConstraints, the constraint indices are now 1:n for scalar constraints so using CleverDict here would speed up copy time for large LP's
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, that is why it was previously parametrized by dict.
That is for the second Dict....
And.... we might consider LittleDict for the outer Dict.... (it is from OrderedCollections) leave it as comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so using CleverDict here would speed up copy time for large LP's
Benchmark? I struggle to believe that the time looking up the index translation is significant. I'm against adding complexity, even if it is a minor speed improvement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When doing the benchmarks for MatrixOfConstraints, I noticed creating the IndexMap was taking a significant time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In a proper model? Or in a microbenchmark?
struct DoubleDict{V,DI,DO} <: AbstractDoubleDict{DataTypePair,V,Int64,DI,DO} | ||
dict::DO | ||
struct DoubleDict{V} <: AbstractDoubleDict{V} | ||
dict::Dict{Tuple{DataType,DataType},Dict{Int64,V}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a function _inner_type(F, S) = V
and have
dict::Dict{Tuple{DataType,DataType},Dict{Int64,V}} | |
dict::Dict{Tuple{DataType,DataType},Dict{Int64}} |
""" | ||
struct DoubleDict{V,DI,DO} <: AbstractDoubleDict{DataTypePair,V,Int64,DI,DO} | ||
dict::DO | ||
struct DoubleDict{V} <: AbstractDoubleDict{V} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potentially call it ConstraintIndexDict
@blegat shall I merge this for now, and we can address any other issues in a follow-up PR? |
I took a look through DoubleDicts for the first time in a long time (ever?).
Why are there so many types and implementations? This is very complicated (600 lines!) for something that should be simple.
From what I can tell, the only type in DoubleDicts that is used is
MathOptInterface.jl/src/Utilities/copy/index_map.jl
Line 8 in 667ad66
With this constructor
MathOptInterface.jl/src/Utilities/copy/index_map.jl
Line 24 in 667ad66
And this related type which is used to access the inner dictionaries
MathOptInterface.jl/src/Utilities/copy/index_map.jl
Line 49 in 667ad66
called from here
MathOptInterface.jl/src/Utilities/copy/index_map.jl
Line 70 in 667ad66
Does that mean I can remove anything unused? Are other packages using this somewhere? If so, how?
Closes #1230