Use MOI.Nonlinear.QPBlockData - #640
Open
blegat wants to merge 12 commits into
Open
Conversation
Delete the local QPBlockData (MOI_utils.jl) in favor of the copy that moved to MathOptInterface, which includes the Jacobian and Hessian product callbacks this copy had added. Two adaptations: - MOI's QPBlockData treats a variable as a parameter if and only if its index is a key of the parameters dictionary, instead of the index-offset convention, so parameters are registered when the constrained variable is added (the value is still re-synced before every solve). - eval_constraint_jacobian and eval_hessian_lagrangian now return the number of entries written instead of a one-indexed cursor, so the callers drop the offset adjustment.
The evaluator methods of MOI.Nonlinear.QPBlockData now return nothing, following the documented contract of MOI.eval_constraint_jacobian and MOI.eval_hessian_lagrangian, so the offsets of the oracle and NLP blocks are computed once in _setup_model instead.
Follow-up to the rename in MathOptInterface: the accumulating product functions of QPBlockData are no longer methods of the MOI.eval_... generic functions.
The fused MOI.eval_constraint_jacobian_transpose_product called the nonlinear-expressions evaluator LAST with the full output vector. Implementations of that function store the result (ReverseAD zeroes the output before writing), so the contributions of the QP block and of the vector-nonlinear-oracle constraints accumulated beforehand were erased whenever the model also had ScalarNonlinearFunction constraints. Call the evaluator first and accumulate the other blocks afterwards, like the fused Jacobian and Hessian products already did.
Store the affine and quadratic objective and constraints in a MOI.Nonlinear.ModelWithQuad whose inner model is the nonlinear model (nlp_model now aliases quad_data.inner), and evaluate everything through a MOI.Nonlinear.EvaluatorWithQuad built in _setup_model. The evaluator owns the QP block entry counts, so the qp_nnzj/qp_nnzh fields are removed. The inner evaluator is a new _OracleNLPEvaluator that stacks the VectorNonlinearOracle rows before the NLPBlock rows; it extends the private MOI.Nonlinear._constraint_bounds so that the constraint bounds of the whole stack are assembled by the evaluator, and it owns the transposed-Jacobian product fallback of the oracles. The jprod/hprod/hess availability flags now read directly off MOI.features_available of the evaluator, which performs the same oracle filtering.
MOI.Nonlinear.ModelWithQuad no longer implements MOI.set for the objective; Nonlinear.set_objective is the single way to set it.
MOI.Nonlinear.ModelWithQuad now owns the variables (with indices guaranteed to be 1:n) and the parameters of the model, so the variables, parameters, quad_data and nlp_model fields collapse into a single model field that most of the MOI API forwards to. The parameter convention is back to the simple _PARAMETER_OFFSET test, now defined in MOI.Nonlinear, and the parameter values are stored once, in the inner nonlinear model, aliased by the QP block: the per-solve parameter sync is gone. A uses_nlp_block flag replaces the nlp_model !== nothing test to tell the legacy MOI.NLPBlock API apart, because optimize! overwrites nlp_data; the NLPBlock is rebuilt on every setup unless that flag is set, so that a stale objective cannot survive an objective switch.
Defining the term methods on a local alias of the function pirated it; the term methods are in MOI.Nonlinear now.
The generic add_constraint and set_objective of the layer replace the offset parameter indices by ParameterIndex, so forward nonlinear constraints to the layer instead of its inner model and drop _replace_parameters.
frapac
reviewed
Aug 17, 2026
frapac
left a comment
Member
There was a problem hiding this comment.
LGTM! We can merge this PR once the PR has been merged en released in MOI.
frapac
approved these changes
Aug 17, 2026
Member
|
Please do exactly the sme modifications in |
Contributor
Author
|
I can take care of Uno as well, I am doing Ipopt first but I plan to do MadNLP the same way. |
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A net line deletion of 685 lines. Needs
Two adaptations:
MOI's QPBlockDatatreats a variable as a parameter if and only if its index is a key of the parameters dictionary, instead of the index-offset convention, so parameters are registered when the constrained variable is added (the value is still re-synced before every solve).eval_constraint_jacobianandeval_hessian_lagrangiannow return the number of entries written instead of a one-indexed cursor, so the callers drop the offset adjustment.