discopt.solvers.nlp_native#
Native POUNCE NLP solve — route node NLPs through POUNCE’s own AD.
The production node-NLP path drives POUNCE (a pure-Rust Ipopt port) through a
Python callback proxy (_IpoptCallbacks → JAX NLPEvaluator): POUNCE asks
for f/∇f/g/J/H once per IPM iteration and each request crosses the Rust→
Python→JAX boundary. POUNCE already parses .nl files into its own
AD-backed problem (pounce.read_nl → NlProblem), so for a model that
originated from (or can be emitted to) an .nl we can hand POUNCE the whole
problem once and let it differentiate natively — zero JAX in the node loop.
Why the orderings line up (validated by tests/test_native_nlp_equivalence):
Variables —
from_nlbuildsmodel._variablesin.nlcolumn order, and the JAX evaluator’s flatxis that same declaration order (dag_compiler._compute_var_offset). So for.nl-originated models the evaluator order is the.nlorder: objective/gradient/Hessian agree to ~1e-15 under the identity map. A model emitted viato_nlis reordered into canonical AMPL order (nonlinear-first); for that case we recover the exact permutation from the writer and apply it on the way in/out.Constraints — the
.nlcanonicalizes bodies (constant terms moved to the bound side, rows reordered) so its constraint representation differs from the evaluator’s. This is benign: POUNCE owns the constraints end-to-end from the.nl(same feasible region), and discopt only consumes the solution vector (variable-ordered) and the objective. The node solve overrides variable bounds only; constraint bounds are static and come from the.nl.
Objective sense: POUNCE always minimizes internally — base.objective,
base.gradient and the solved obj_val are all reported in minimization
sense even when base.minimize is False (a maximize .nl). The
evaluator/B&B also work in minimization sense (the evaluator negates a maximize
objective), so the two line up directly with no sign correction. base.minimize
is metadata only.
Every base is validated numerically (objective + gradient at a probe point) before use; on any mismatch (or when POUNCE/AD is unavailable) the caller falls back to the JAX path, so correctness never depends on an unverified assumption.
Attributes#
Classes#
A POUNCE-native NLP problem aligned to a discopt evaluator's variables. |
Functions#
|
Construct a POUNCE-native problem aligned to |
|
Return a cached native base for |
|
Solve one node NLP natively; return an |
Module Contents#
- discopt.solvers.nlp_native.logger#
- class discopt.solvers.nlp_native.NativeNlpBase#
A POUNCE-native NLP problem aligned to a discopt evaluator’s variables.
baseis the parsedNlProblem(POUNCE’s own AD).permmaps a.nlcolumn index to the evaluator’s flat variable index —perm[j]is the evaluator index of.nlcolumnj— sox_nl = x_eval[perm]andx_eval[perm] = x_nl.perm is Nonemeans the identity map (the commonfrom_nlcase). No objective-sign correction is needed: POUNCE reports everything in minimization sense (see module docstring);base.minimizeis metadata only.- base: pounce.NlProblem#
- n: int#
- perm: numpy.ndarray | None#
- source: str#
- to_nl_order(x_eval: numpy.ndarray) numpy.ndarray#
Permute an evaluator-ordered vector into
.nlcolumn order.
- to_eval_order(x_nl: numpy.ndarray) numpy.ndarray#
Permute a
.nl-ordered vector back into evaluator order.
- variant(node_lb, node_ub, x0)#
Build a per-node
NlProblemwith tightened variable bounds.Shares the parsed DAG / AD tapes with
base(cheap); only the bound / start vectors are replaced. Inputs are in evaluator order; they are permuted into.nlorder for POUNCE.
- cleanup() None#
- discopt.solvers.nlp_native.build_native_base(evaluator, *, validate: bool = True) NativeNlpBase | None#
Construct a POUNCE-native problem aligned to
evaluator, orNone.Prefers the model’s source
.nl(identity variable order). Falls back to emitting the model viato_nl(canonical reorder → recovered permutation). ReturnsNonewhen POUNCE is unavailable, the model cannot be expressed as an.nl, or numeric validation fails — the caller then uses the JAX path.
- discopt.solvers.nlp_native.get_native_base(evaluator) NativeNlpBase | None#
Return a cached native base for
evaluator’s model, building once.Cached on the model and invalidated by the same structural fingerprint the evaluator cache uses, so a reformulated/edited model rebuilds its base.
Falseis cached for a model that cannot use the native path, so we do not repeatedly re-attempt (and re-emit) a failing model.The cache is shared across threads, which POUNCE supports as of pounce#477; the first base built in a process verifies that (see
_CROSS_THREAD_OK) and the native path is disabled outright against a POUNCE that does not.
- discopt.solvers.nlp_native.solve_node_native(nb: NativeNlpBase, x0, node_lb, node_ub, options) object#
Solve one node NLP natively; return an
NLPResult(minimization sense).