Skip to content

Use MOI.Nonlinear.ModelWithQuad instead of QPBlockData - #643

Closed
blegat wants to merge 11 commits into
madsuite-org:masterfrom
blegat:bl/model_with_quad
Closed

Use MOI.Nonlinear.ModelWithQuad instead of QPBlockData#643
blegat wants to merge 11 commits into
madsuite-org:masterfrom
blegat:bl/model_with_quad

Conversation

@blegat

@blegat blegat commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

blegat added 11 commits August 13, 2026 12:31
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.
@blegat

blegat commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

Merged into #640

@blegat blegat closed this Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant