Skip to content

Define operate and refactor moivcat #455

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

Merged
merged 12 commits into from
Aug 16, 2018
Merged

Define operate and refactor moivcat #455

merged 12 commits into from
Aug 16, 2018

Conversation

blegat
Copy link
Member

@blegat blegat commented Aug 6, 2018

Bridges need to do some arithmetic operations like vcat, +, -, ... and need to be able to determine the result of such operation to determine which constraints the bridge generate at compile time.
To achieve this, this PR suggest to define operate(op::Function, ::Type{T}, args...) that does the operation op(args...)with coefficient typeTandpromote_operationthat gives the type of the output the functionoperate` without the need for Julia's inference system.

Currently most bridges only work when the function is VectorAffineFunction and convert VectorOfVariables to VectorAffineFunction while they could also work with VectorQuadraticFunction and keep VectorAffineFunction unconverted would allow the bridge to create VectorAffineFunction functions which could be handled more efficiently by the solver.
Using these functions instead of hardcoding the operations for VectorAffineFunction would allow to easily build bridges that work for any AbstractVectorFunction as input (just like SplitIntervalBridge currently).

@blegat blegat mentioned this pull request Aug 7, 2018
1 task
@codecov-io
Copy link

codecov-io commented Aug 8, 2018

Codecov Report

Merging #455 into master will decrease coverage by 0.7%.
The diff coverage is 95.59%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #455      +/-   ##
==========================================
- Coverage   95.24%   94.54%   -0.71%     
==========================================
  Files          42       44       +2     
  Lines        4960     5423     +463     
==========================================
+ Hits         4724     5127     +403     
- Misses        236      296      +60
Impacted Files Coverage Δ
src/Bridges/Bridges.jl 100% <ø> (ø) ⬆️
src/Bridges/rsocbridge.jl 100% <100%> (ø) ⬆️
src/Bridges/bridge.jl 100% <100%> (ø) ⬆️
src/Bridges/soctopsdbridge.jl 100% <100%> (ø) ⬆️
src/functions.jl 100% <100%> (ø) ⬆️
src/Utilities/constraints.jl 100% <100%> (ø)
src/Utilities/sets.jl 100% <100%> (ø) ⬆️
src/Bridges/geomeanbridge.jl 100% <100%> (ø) ⬆️
src/Bridges/detbridge.jl 98.82% <100%> (+0.02%) ⬆️
src/Bridges/intervalbridge.jl 84.61% <66.66%> (-3.39%) ⬇️
... and 10 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 253e16c...4348a91. Read the comment docs.

@blegat
Copy link
Member Author

blegat commented Aug 8, 2018

Ready for review, I am not planning to do any more changes :)

Copy link
Member

@mlubin mlubin left a comment

Choose a reason for hiding this comment

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

High level comment. This makes me think that we should instead implement the standard Julia operators for the MOI types. It's pretty roundabout to say MOIU.operate(vcat, T, a, b, c) instead of T[a; b; c] given that Julia has the syntax. What's the argument for creating our own operator and type promotion system?

@@ -164,6 +165,9 @@ function Base.getindex(it::ScalarFunctionIterator{<:VQF}, i::Integer)
return SQF(lin, quad, it.f.constants[i])
end

function Base.getindex(it::ScalarFunctionIterator{VVF}, I::AbstractVector)
return VVF(it.f.variables[I])
Copy link
Member

Choose a reason for hiding this comment

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

I don't think the abbreviation VVF helps readability here.

@blegat
Copy link
Member Author

blegat commented Aug 9, 2018

What's the argument for creating our own operator?

We want [a, b] where a and b and ScalarAffineFunction to be a Vector{ScalarAffineFunction}, not a VectorAffineFunction so we define moivcat which is now MOI.operate(vcat, ...).
Same thing for getindex and eachscalar except that for getindex we might still use eachscalar and not operate as eachscalar may allow doing some caching to speed up (see #418 (comment)).
What would we do for the call (+, - or *)(::MOI.SingleVariable, MOI.SingleVariable), which coefficient type do we use for the result ? Also, if we get +(::Any, ::MOI.SingleVariable) what is this first argument ? Is it a coefficient ? What is the type of a coefficient ? Number, Real ?

When doing a * b in JuMP we have the issue that we don't know if we can overwrite a so we have to copy it. Here we have operate! and operate so the user can use operate! if he knows the first argument can be overwritten.

In MOI we do not care too much about being super-user friendly (user friendly is enough).
In JuMP we need to be super-user friendly so we are forced to implement the Base methods,
here we have the choice and we can choose to be more explicit about inplace/coefficient type rather than being super-user friendly.

type promotion system?

Base.promote_op should not be used
JuliaLang/julia#26344 (comment)

@blegat
Copy link
Member Author

blegat commented Aug 10, 2018

As a second thought, it would indeed be nice to also define Base.:+, ... methods using operate

@mlubin
Copy link
Member

mlubin commented Aug 11, 2018

We want [a, b] where a and b and ScalarAffineFunction to be a Vector{ScalarAffineFunction}, not a VectorAffineFunction so we define moivcat which is now MOI.operate(vcat, ...).

I wonder if using a macro to switch the context could be useful. Like [a, b] returns Vector{ScalarAffineFunction} and @MOI.operate [a, b] returns VectorAffineFunction. But not needed immediately.

@blegat blegat merged commit 03cf6c8 into master Aug 16, 2018
@blegat blegat deleted the bl/operate branch August 28, 2018 14:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants