Do Not Merge Yet: Add MOI Disjunction Set Reformulation
This adds the MOIDisjunction reformulation method which transforms disjunctions in vector constraints that use DisjunctionSet. This enables us to pass disjunctions directly down to the MOI level.
As an update, it seems MOI bridges will likely not work with disjunctions. The problem is that each disjunct can contain an arbitrary number of constraints of any type (including other disjunctions). For a bridge to work, MOI needs to be able to infer want reformulation constraints will be constructed based on the set type. With:
struct DisjunctionSet{S <: _MOI.AbstractSet} <: _MOI.AbstractVectorSet
dimension::Int
disjunct_indices::Vector{Int}
constraint_sets::Vector{Vector{S}}
end
we will most often end up with something like DisjuctionSet{MOI.AbstractSet} which doesn't tell us what type of constraints it contains. Alternatively, we could use a tuple to put all the constraint set types as parametric types:
struct DisjunctionSet{T <: Tuple} <: _MOI.AbstractVectorSet
dimension::Int
disjunct_indices::Vector{Int}
constraint_sets::T # flatten everything into a tuple
end
Now T will contain all constraint set types, but to make a MOI bridge we would have to account for every concrete typed case. This leads to an infinite number of combinations, since there can be any number of disjuncts and constraints with any type.
So, in the end, it is possible to represent disjunctions in MOI, but bridges won't be practical to implement. However, solvers (e.g., ToQUBO.jl) can still support DisjunctionSets directly. Ultimately, we can make an MOI solver layer similar to ParametricOptInterface that converts DisjunctionSets into forms that other solvers can handle. Moreover, such a layer could support more advanced solution techniques like logic-based outer approximation.
After talking offline with @hdavid16, another option to is add a canonicalized disjunction set where all the constraints are converted to inequalities first:
struct DisjunctionSet{T <: Real} <: _MOI.AbstractVectorSet
dimension::Int
disjunct_indices::Vector{Int}
constraint_sets::Vector{Vector{MOI.LessThan{T}}}
end
This would require more processing upfront, change the structure, and potentially exclude some constraint types (e.g., cones), but this would be easy to implement a bridge for.
Codecov Report
Attention: 26 lines in your changes are missing coverage. Please review.
Comparison is base (
3af182e) 98.91% compared to head (e0570d8) 96.19%.
Additional details and impacted files
@@ Coverage Diff @@
## master #71 +/- ##
==========================================
- Coverage 98.91% 96.19% -2.72%
==========================================
Files 10 11 +1
Lines 921 947 +26
==========================================
Hits 911 911
- Misses 10 36 +26
| Files | Coverage Δ | |
|---|---|---|
| src/datatypes.jl | 100.00% <ø> (ø) |
|
| src/moi.jl | 0.00% <0.00%> (ø) |
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
@bernalde and @pedromxavier I think this PR gives you the MOI representation that you need. Namely, the addition of DisjunctionSet <: MOI.AbstractVectorSet. Let me know your thoughts and if it looks good, I will add tests and we can merge this for you to use.
It looks good to me. I'd be curious to see the tests to see how to interact with the new code.
Should there be a MOI.get interface for accessing the contents of the Disjunction Set?
Should there be a
MOI.getinterface for accessing the contents of the Disjunction Set?
Any suggestions on what the input and output would be precisely?
Any suggestions on what the input and output would be precisely?
@bernalde @pedromxavier