-
-
Notifications
You must be signed in to change notification settings - Fork 411
Refactor to use MOI.Nonlinear #2955
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
Conversation
Codecov Report
@@ Coverage Diff @@
## master #2955 +/- ##
==========================================
+ Coverage 95.44% 96.12% +0.67%
==========================================
Files 43 32 -11
Lines 5824 4130 -1694
==========================================
- Hits 5559 3970 -1589
+ Misses 265 160 -105
Continue to review full report at Codecov.
|
f4a9fe9 to
b12f22e
Compare
|
What are the concrete next steps for merging this into JuMP? It's a bit of a weird PR, because on one hand, it changes a lot of code, but on the other hand, very little actually changes at the user-facing level (just a couple of errors move from compile time to run time, and some constants change from I think at minimum, we need the following reviews: Optional |
frapac
left a 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.
This PR is a net improvement imo. The code is a lot cleaner now the nonlinear backend is factorized on the MOI side. I have tested this branch on my custom nonlinear models, and JuMP works like a charm on them, returning the same results as before.
I only have a few minor comments (I don't have the expertise to assess the correctness of the macro in JuMP).
Also, one remaining TODO on the JuMP side was the support of incremental solves for nonlinear model:
https://github.com/jump-dev/JuMP.jl/blob/od/moi-nonlinear/src/optimizer_interface.jl#L156
I am wondering how difficult it would be to support incremental nonlinear solves with the new nonlinear interface? E.g. to add new nonlinear constraints MOI.Nonlinear.Model between two consecutive solves.
mlubin
left a 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.
Have you run end-to-end benchmarks? Maybe this was already done, but I remember at some point there were performance TODOs in MOI.Nonlinear.
That's my plan once this is merged, but it should be a separate PR. |
I reverted the performance TODOs in MOI.Nonlinear, so now the only change is moving some of the expression generation from compile time in the macros to runtime. I can make some more benchmarks. |
|
I reviewed the code changes and nothing stood out to me as problematic. But I'll also confess that the bulk the details are beyond my level of expertise. I would suggest that any feature adds, which run the risk of generating a desire for possible future breaking changes be discussed at the JuMP developer call for concurrence across the wider group (if this has not already been done). The only two points that I saw that would fall into this category were:
One option to keep feature progress without breaking changes would be to make these new features accessible only from internal functions for a time. Then move them to exported functions after advanced users have had a chance to use them for several months? |
Updates More updates with beginnings of auto-registration Add back printing Simplify parsing macro Re-add support for generators Support . field access More updates More updates More fixes Updates to the docs More fixes for the docs Documentation fix More fixes Lots more fixes Fix format More fixes Fix formatting and re-org Coloring tests More tests Fix tests More test fixes More fixes More printing fixes F Implement value Fix test failure Fix broken tests Revert change to nonlinear constraint expressions Update Fix tests Another fix Fix test Another fix Start on documentation Reenable precompile Various updates and improvements Add more docs Fix docs Add docstrings Variety of docs and other improvements Fix typo More updates Fix formatting More updates Remove utils.jl Tidy Coloring Fix typo Improve test coverage Remove unneeded type Union is called in docs Add back NaNMath
Misc fixes Fix formatting More tests Fix test Fix formatting Update for latest changes Fix typo Fix formatting Fix typo Latest updates Updates from latest MOI changes Update for latest changes Fix tests More fixes
|
I've opened issues in the packages that will break. I found them by searching Julia hub for things like A few, like NLPModelsJuMP, are easy fixes to use only the public API. But others like EAGO are pretty much dead in the water because they heavily used a lot of the stuff in Some of the others are just for printing (MPSGE), which I guess going without isn't too much of a penalty. Others like Complementarity and DisjunctiveProgramming (ab)use the API to do things like delete nonlinear constraints and modify nonlinear expressions, so I don't know if we have a safe work-around. The main takeaway from this that I will push a commit to shortly, is to overload |
|
I took a look at some of the packages:
Action items:
|
| julia> index(cons1) | ||
| NonlinearConstraintIndex(1) | ||
| MathOptInterface.Nonlinear.ConstraintIndex(1) |
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.
This part has changed, but I've added const NonlinearConstraintIndex = MOI.Nonlinear.ConstraintIndex so it isn't breaking.
|
Cross posting a message I just left on discourse:
|
|
Also, another question: I remember that there was discussion to move the functionality of Complementarity into JuMP eventually, and I think the idea was to first revamp the NLP stuff and then do that. Just wondering whether the current redesign is such that it would facilitate such a step? |
This is the same as for Julia itself, relying on internals and unexported modules makes it possible that future versions will break one's code.
Yes Pkg does that with Tilde or equality specifies https://pkgdocs.julialang.org/v1/compatibility/#Tilde-specifiers
This is a very valid point, that's why @odow opened PRs or at least issues on all packages depending on the nonlinear part and that will break with the upgrade, similar to what Julia does when something is "theoretically" not breaking but practically is because of reliance on internals or unspecified behavior |
|
Resolution from today's monthly call is that before merging, we should:
|
No progress on this yet. The current change is very much a maintenance, documentation, and paying down technical debt change. There's no real new functionality. The nonlinear complementarity is something I'm thinking about though. |
|
Opened PRs to fix compat bounds. EAGO, Complementarity, and MPSGE haven't released tagged versions that are compatible with JuMP 1.0 yet. |
|
Hmm. @abelsiqueira found an unintentional breaking change we obviously don't have any tests for: https://github.com/JuliaSmoothOptimizers/NLPModelsJuMP.jl/pull/118/files#r911475220 julia> using JuMP
julia> model = Model()
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: AUTOMATIC
CachingOptimizer state: NO_OPTIMIZER
Solver name: No optimizer attached.
julia> @variable(model, x)
x
julia> @NLconstraint(model, sin(x) ≤ 1)
ERROR: Unrecognized function "≤" used in nonlinear expression.
You must register it as a user-defined function before building
the model. For example, replacing `N` with the appropriate number
of arguments, do:
```julia
model = Model()
register(model, :≤, N, ≤, autodiff=true)
# ... variables and constraints ...
```
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:33
[2] assert_registered(registry::MathOptInterface.Nonlinear.OperatorRegistry, op::Symbol, nargs::Int64)
@ MathOptInterface.Nonlinear ~/.julia/packages/MathOptInterface/kCmJV/src/Nonlinear/operators.jl:416
[3] macro expansion
@ ~/.julia/dev/JuMP/src/macros.jl:1874 [inlined]
[4] top-level scope
@ REPL[4]:1This used to work: julia> using JuMP
[ Info: Precompiling JuMP [4076af6c-e467-56ae-b986-b466b2749572]
julia> model = Model(); @variable(model, x)
x
julia> @NLconstraint(model, sin(x) ≤ 1)
sin(x) - 1.0 ≤ 0Fix and tests incoming. |
|
Merging this now, but I'll wait a while longer before tagging v1.2.0 so we can have a go at updating some of the extensions. |
ANN: upcoming refactoring of JuMP's nonlinear API
tl;dr: The next feature release of JuMP (probably v1.2.0) introduces a large
refactoring of JuMP's nonlinear API. If you have code that accessed private
features of the nonlinear API, such as
JuMP._Derivativesormodel.nlp_data,your code will break. If you used only the public, documented API such as
register,@NLconstraintandnum_nonlinear_constraints, this change doesnot affect you. To try the uncoming release, use
import Pkg; Pkg.pkg"add JuMP#od/moi-nonlinear".The relevant pull request is #2955
What are we doing?
Over the last few months, we have been refactoring how JuMP supports nonlinear
programs. This involved moving and re-organizing a large amount of code from
JuMP into MathOptInterface.
The result is the new
MOI.Nonlinearsubmodule in MathOptInterface, with adocumented public API for creating and dealing with nonlinear programs. Read
more about it here: https://jump.dev/MathOptInterface.jl/stable/submodules/Nonlinear/overview/
However, as part of this work we are removing code from JuMP. This code was
internal, undocumented, and not intended for public use. Most of it was
contained in the
JuMP._Derivativessubmodule, but we also made changes suchas removing
model.nlp_data.Why did we do this?
The nonlinear code in JuMP was a clear example of technical debt. It was
complicated, convoluted, and largely undocumented. People wanting to extend JuMP
for nonlinear programs were forced to use a range of hacks that relied on
undocumented internals.
The new
MOI.Nonlinearsubmodule offers a stable, documented, and public APIfor people to build JuMP extensions on. It also enables new features like
swappable automatic differentiation backends, and hessians of user-defined
functions.
We originally considered that any change in the nonlinear API would be a
breaking v2.0.0 release of JuMP and occur at least two years after the release
of JuMP 1.0. However, we implemented the changes quicker than expected, and were
able to do so in a way that does not break the public nonlinear API. Therefore,
we elected to classify this as a non-breaking feature release.
Does it affect me?
If you have any code that called private features of the JuMP nonlinear API,
such as
JuMP._Derivativesormodel.nlp_data, your code will break.If you used only the public, documented API such as
register,@NLconstraintand
num_nonlinear_constraints, this does not affect you.What are the next steps
Try the uncoming release as follows:
import Pkg; Pkg.pkg"add JuMP#od/moi-nonlinear".If you find any bugs or changes in performance, please post below, or open a
GitHub issue. Once we're happy that there are no issues with the changes, we
will release a new version of JuMP with the changes.