Releases: jkitchin/ripopt
ripopt v0.7.1
Patch release focused on the Reference-Gap Roadmap: porting concrete behavioral details from Ipopt 3.14 that the v0.7.0 ripopt-vs-Ipopt audit flagged as missing.
Algorithmic ports from Ipopt 3.14
- Full
IpScaledNLP-equivalent x-scaling wrapper (roadmap #6) PDPerturbationHandlerδ-escalation schedule (roadmap #19)- Soft restoration phase:
TrySoftRestoStepwith the E_μ test (roadmap #12) - Restoration convergence three-gate:
RestoFilterConvCheck(roadmap #13) - μ-dependent δ_c regularization (roadmap #6)
- Separate s_d / s_c convergence scaling, drop of the legacy 1e4 cap (roadmap #1)
- Drop of the ±1 inertia acceptance heuristic (roadmap #5)
- Centrality term in the Quality-Function μ oracle (roadmap #14)
New features
- AMPL external functions via the
funcadd_ASLABI: models depending on user-supplied function libraries (IDAEScbrt, Sundials, custom property packages) now load and solve in ripopt without modification (#15, #20) warm_start_target_muoption for warm-start μ override (roadmap #18)user_obj_scaling,mu_oracle_quality_function,quality_function_centralityexposed through C API, AMPL CLI, and the Python binding- IPM iteration log gains a
complcolumn
Refactoring
~198 commits extracting named helpers from src/ipm.rs (e.g. compute_barrier_phi, apply_gondzio_mcc, run_line_search_loop, run_post_ls_restoration_cascade, try_soft_restoration, try_nlp_restoration_phase). No behavioral change — the IPM main loop now reads as a sequence of named phases instead of a 3000-line control-flow blob.
Benchmarks
| Suite | v0.7.0 | v0.7.1 | Native Ipopt |
|---|---|---|---|
| HS strict-Optimal | 118/120 | 118/120 | 116/120 |
| CUTEst strict-Optimal | 560/727 | 556/727 | 556/727 |
| HS geo-mean speedup | 15.0× | 20.8× | 1× (baseline) |
| CUTEst geo-mean speedup | 9.9× | 12.0× | 1× (baseline) |
CUTEst regressed by 4 problems (20 lost, 16 gained) on least-squares / rank-deficient Jacobian families. The most plausible suspects are the stricter s_d/s_c convergence metric and the new μ-dependent δ_c regularization. Tagged comparison artifacts: benchmarks/cutest/results_v0.7.0.json vs benchmarks/cutest/results_v0.7.1.json.
Distribution
cargo add ripopt(crates.io) — the core Rust librarypip install ripopt(PyPI) — Python binding via the AMPL NL interfacepip install pyomo-ripopt(PyPI) — PyomoSolverFactory('ripopt')integrationRipopt.jl— Julia/JuMP via MathOptInterface- GAMS solver link via the GMO API
- AMPL via
--solver=ripopt
See CHANGELOG.md for the full list of changes.
v0.7.0
[0.7.0] - 2026-04-23
First release where ripopt solves strictly more HS and more CUTEst
problems than native Ipopt (+2 HS, +1 CUTEst). The headline theme of
this cycle is closing the remaining behavioral gaps between ripopt and
Ipopt 3.14.x — most importantly the convergence semantics around the
bound multipliers z_L/z_U, the post-restoration multiplier reset,
the Mehrotra predictor-corrector, the KKT backward-error probe, and
the barrier-subproblem stop-test gate in Free-mode μ updates.
Breaking changes
- **
refactor(ipm)!: dropz_opt, align convergence with Ipopt's iterative-zsemantics** (e35407c). Previously ripopt kept a separatez_optreconstruction used only by the convergence test; now the iterativez_L/z_Uthemselves are the convergence vector, matching Ipopt'sPDFullSpaceSolversemantics. TheSolveDiagnostics::final_dual_inf_scaledfield has been removed — callers that consumed it should switch tofinal_dual_inf`. Bumped
to a minor release for this reason. SolveStatus::Acceptablewas removed. Non-Optimalstatuses now
always surface honestly (MaxIterations,NumericalError,
RestorationFailed,Infeasible). Consumers that treated
Acceptableas success should audit their integration.
Added
ripopt-py: direct Python interface with JAX autodiff (b89f169,
a9ba046). Exposes a persistentProblemclass with dual warm start
(Problem.solve(lam0=, z_l0=, z_u0=), b95e5b8), accepts Ipopt-style
option aliases (mu_strategy,sb,bound_push, cyipopt-style
names, 4779b37), and is now published on PyPI (e32b57b) alongside
pyomo-ripopt(8cce31a).- NaN/Inf evaluation hardening and C API parity (66d77a1,
42f4015). ripopt now matches Ipopt's behavior when user callbacks
return NaN/Inf or signal failure: α-halving retry on post-step
evaluation failure (2b5cb99), softEvalError → NumericalError
transition instead of hard abort (07cf37f), and structural parity
with Ipopt'sTNLP::eval_*error-handling contract. NlpProblem::new_xflag for evaluation caching (d138a25). User
code can now short-circuit repeated evaluations at the same
iterate, matching Ipopt'snew_xcontract. Existing trait
implementations compile unchanged (the parameter defaults totrue
on old code paths).num-dualautomatic-differentiation example (4aad98a) with a
dedicated README section showing forward-mode AD through
NlpProblem.- TSV direction-diff harness for step-by-step comparison against
a reference solver trace (e11832f), with an extended trace schema
(α_max, τ, Σ condition number, SOC-accepted, c6178d6). - GAMS nlpbench benchmark harness (eac674b). New
gams/Makefile
targetsbench-smoke/bench-small/bench-medium/bench-large
/bench-alldrive the (vendored, gitignored)gams/nlpbench/
test-set runner against both ripopt and ipopt and emit
BENCHMARK_REPORT_<size>_<version>.md. Status returned by ripopt is
mapped to nlpbench's signed-status convention so reports classify
"locally optimal", "infeasible", and "iteration limit" correctly. - Adversary agent sweep (new
adversary/runs/). First full run of
the automated NLP correctness-testing harness: Rosen-Suzuki, HS13,
Discrete Boundary Value (n ∈ {20, 200, 500, 1000, 2000, 5000}),
parametric projection, Powell badly-scaled. Four PASS; HS13 filed as
issue #19 (solver limitation on a known LICQ/MFCQ-degenerate problem). - Reference-gap roadmap (
docs/REFERENCE_GAP_ROADMAP.md). ~700-line
ripopt-vs-Ipopt and rmumps-vs-MUMPS gap analysis drafted with the
ipopt-expert and mumps-expert agents, cataloging known deficiencies
(D1-D10 for ripopt, (a)-(i) for rmumps), genuine advantages, and a
ranked roadmap of 20 cross-cutting items (correctness-first).
Changed
- Post-restoration multiplier reset matches Ipopt exactly (07dcdcc,
20b51ce, af0bf09). Thez_L/z_Ureset after restoration now
absorbs the correct contribution into the least-squaresy
re-solve, computed via Ipopt's exact augmented system. This was the
source of several silent failures at the boundary between
restoration and the main IPM. - Mehrotra predictor-corrector: removed the skip gate that
previously disabled corrections on highly infeasible iterates
(72bae01); fixed the cross-term in the primal RHS and thedz
recovery step (9deaff4); split Mehrotra vs filter-LS RHS
assembly so the corrector and the line-search share no hidden
state (eeae3d5). - Ipopt barrier-subproblem stop-test gate in Free-mode μ updates
(7f333de). μ no longer decreases until the current barrier
subproblem passes Ipopt's stop test, preventing premature
centering collapse on marginally feasible iterates. - Always verify KKT backward error; no IC-undoing iterative
refinement (66bce53). Then+m ≥ 100shortcut in
factor_with_inertia_correctionis gone — every accepted
factorization now runs the backward-error probe. Iterative
refinement no longer tries to undo the inertia-correction
perturbation; Ipopt treats IC as part of the linear system, and so
does ripopt now. - Reject rank-deficient solutions with huge magnitude (3211838).
When the solve produces a correction whose norm is inconsistent
with the residual, the factorization is rejected and perturbation
escalates, matching Ipopt'sPDPerturbationHandlerbehavior. - Iterative refinement in custom-RHS and condensed solves
(96329a2). Custom-RHS solves (used by sensitivity, SOC, and the
condensed-KKT path) now run the same iterative-refinement loop as
the primary solve. - Dropped element-wise NaN checks on
grad_fandg(0ed77e1).
Replaced with vector-norm finiteness checks, matching Ipopt. - Loqo μ-oracle monotone floor (02471aa). Re-applies the floor
that prevents μ from increasing inside a barrier subproblem.
Fixed
- Documentation: rustdoc intra-doc link warnings from
[i]index
brackets — escape as\[i\]to prevent rustdoc from parsing them
as link references. - Benchmark runners: drop stale
final_dual_inf_scaledreferences in
the CUTEst runner (bc1fa21) and the HS native-ipopt runner
(2780600). - CI: gate
cat_a_probeexample behind thecutestfeature (2b293e2). - Two cyipopt-style spelling aliases were accepted on both the
Python and Rust option paths (4779b37). - Preprocessing: skip redundancy detection on callback eval failure
(ff9144e).detect_redundant_constraintspreviously panicked when
the user'sconstraints()callback returnedfalseat the synthetic
probe point; it now bails out cleanly, leaves the original
constraint set intact, and lets the IPM handle the eval failure
through the normal α-halving path. - Julia binding: status-code constants align with
RipoptReturnStatus
(437bba0, 7733576).Ripopt.jland the embedded C wrapper status
enums had drifted from the Rust-sideRipoptReturnStatus
definitions; both are now regenerated from the canonical list so
MOI.TerminationStatusreports the correct Ipopt-compatible code. - GAMS bridge: pass
index_styletoripopt_create(61aa808).
The GAMS bridge was callingripopt_createwithout the new
index_styleargument, causing 1-based / 0-based indexing confusion
on GAMS-formulated NLPs. - Dead code removed (6e91f55). LS-y helpers and unused imports
pruned fromsrc/ipm.rs,src/kkt.rs, andsrc/c_api.rs. No
behavioral change.
Performance
Fresh benchmark results (2026-04-21 on Apple Mac Mini, aarch64-apple-darwin):
- HS suite: ripopt 118/120 (98.3%), Ipopt 116/120 (96.7%).
15.0× geometric-mean speedup on 116 commonly-solved, median 14.2×,
ripopt faster on 113/116 (97%). ripopt-only solves: HS214, HS223.
Ipopt-only solves: 0. - CUTEst suite: ripopt 562/727 (77.3%), Ipopt 561/727 (77.2%).
9.9× geometric-mean speedup on 525 commonly-solved, median 18.9×,
ripopt faster on 440/525 (84%). ripopt-only solves: 37;
Ipopt-only solves: 36. - Electrolyte thermodynamics: ripopt 13/13, Ipopt 12/13. 17.5×
geometric-mean speedup on 12 commonly-solved. Seawater speciation
now takes 1,415 iterations (was 22 at v0.6.2) under the stricter
v0.7.0 convergence semantics, but still solves where Ipopt declares
Infeasible. - Grid (AC OPF): ripopt 3/4, Ipopt 4/4. Geometric-mean 2.8× on
the 3 commonly-solved. See Notes below for the case30_ieee
regression.
Notes
- case30_ieee regression. At v0.7.0 ripopt reaches
MaxIterations
on PGLib-OPFcase30_ieee, regressing from v0.6.2 which converged
to a different local minimum (obj=8,609.66, 4.6% above the known
optimum of 8,081.52, compared to Ipopt's 8,208.52 at 1.6% above).
The regression is a side-effect of dropping then+m ≥ 100
shortcut infactor_with_inertia_correction(66bce53): the
stricter backward-error probe now perturbs more aggressively on
this rank-deficient AC-OPF Jacobian. The v0.6.2 "solve" was in
fact converging to a different local optimum than Ipopt, so this
is less of a correctness regression than a robustness regression;
still, ripopt now solves one fewer grid problem than it did at
v0.6.2. Tracked for a future patch. - Poisson 2.5K large-scale benchmark. The Poisson 2.5K problem
exhaustsmax_iterunder the v0.7.0 convergence semantics and
causesmake benchmarkto hang if run to completion; the large-
scale sweep is therefore reported for the 4 problems that finish
quickly (Rosenbrock 500, Bratu 1K, SparseQP 1K, OptControl 2.5K).
Historical v0.6.2 timings for the other large-scale problems
remain inbenchmarks/large_scale/large_scale_results.txt. Full
sweep is gated on a separate investigation. - ripopt-py on PyPI as
ripopt-py(direct JAX-backed interface)
andpyomo-ripopt(Pyomo plugin). Workspace crates stay on
semver:ripopt→ 0.7.0,rmumpsunchanged at 0.1.1.
ripopt v0.6.2
[0.6.2] - 2026-04-12
Added
- Reorganized benchmarks under
benchmarks/with one self-contained
subdirectory per suite:hs/,cutest/,electrolyte/,grid/(renamed
fromopf/),cho/,large_scale/,gas/, and the newwater/. Each
suite has its own README and per-suite report. The composite report at
benchmarks/BENCHMARK_REPORT.mdaggregates HS + CUTEst + electrolyte +
grid + CHO + large-scale; the gas and water suites are standalone (AMPL
.nlinterface, per-problem.soloutput). benchmarks/water/: 6 water distribution network design NLPs from
MINLPLib (Hazen-Williams head-loss formulation). Solved via the AMPL
interface; ripopt matches the best-known primal bound forwater.nl
(963.13) where Ipopt converges to a different local minimum (1001.16).benchmarks/gas/: 4 gas pipeline NLPs from PDE-discretized Euler
equations on pipe networks (gaslib11/40, steady/dynamic). Solved via the
AMPL interface.- Loqo mu oracle (
mu_oracle = "loqo") enabled by default, matching Ipopt's
mu_oracle=quality-functionstrategy. Uses centrality measure
xi = min(z*s)/avg_complto set centering parametersigma, preventing
premature mu decrease from highly infeasible starting points. On gaslib11_steady:
164→134 iters, NLP restorations 1→0, mode switches 24→8. - Sparse Gauss-Newton restoration: sparse
J*J^Tfactorization for GN restoration
when m > 500, removing the dense Bunch-Kaufman bottleneck (6s/step → 0.02s for
gas pipeline NLPs). Sparse LS multiplier estimates for post-restorationy
initialization. - Ruiz equilibration KKT scaling matching MUMPS
SimScaleschedule
(KEEP(52)=7 for SYM=2): 1 inf-norm iteration + 3 one-norm iterations. Activated
on demand when backward error is poor. Addedrow_abs_sum()to
DenseSymmetric,SparseSymmetric, andKktMatrix. - Pretend-singular fallback using Ipopt's normwise residual ratio (threshold
1e-5). When iterative refinement cannot reach target accuracy, triesdelta_c
first (PerturbForSingularity), thendelta_w. - Adaptive mu dual infeasibility safeguard: prevents mu from collapsing to
1e-11 while dual infeasibility remains large. Addsdu_floorto barrier error
and dual-infeasibility stagnation detection. - Structural degeneracy detection: after 3 consecutive iterations requiring
delta_w > 0, skips the unperturbed factorization trial on subsequent iterations. - Dense BK
increase_quality(): configurable pivot threshold with escalation
0.64 → 0.8 → 0.95 → 1.0. - KKT factorization diagnostics (dim, nnz, wall time) at
print_level ≥ 5.
Line-search rejection details atprint_level ≥ 7.
Changed
- PretendSingular chain now matches Ipopt's
PDFullSpaceSolver:
solve → refine(fail) → IncreaseQuality → re-solve → perturbation.
Previously perturbation was applied beforeIncreaseQuality. - Iterative refinement: max steps raised from 3–5 to 5–10 (matching Ipopt
default). Stagnation detection extended to the non-IC path with a relaxed
factor (1−1e−6 vs Ipopt's 1−1e−9). - Default sparse threshold unchanged (n+m ≥ 110) but sparse GN restoration
now activates at m > 500 even when the outer IPM is dense. - Workspace version bumped —
ripopt→ 0.6.2,rmumps→ 0.1.1. ref/directory andpyomo-ripopt/build/now ignored in git.
Fixed
- Fallback-result regression (
is_strictly_better): when the main IPM
reportsNumericalErrorat a feasible iterate with a meaningful objective,
a fallback solver that converges to a worse local minimum no longer
silently replaces the main-IPM result. The comparator now requires either
strict objective improvement (with primal feasibility ≤ 1e-4) or that the
current result has no usable objective. This was the root cause of the
c_api_hs071_basic,c_api_hs071_multiplier_extraction,
c_api_null_output_params,test_hs071_sensitivity_vs_finite_differences,
andtest_sensitivity_linear_prediction_accuracyregressions introduced by
the recent Loqo oracle / KKT quality-chain work. - Phosphoric-acid electrolyte test (
electrolyte_05_phosphoric_acid)
pinned tomu_oracle_quality_function=false. The Loqo oracle steers the
solver into a chemically-wrong local minimum (pH ≈ 11.84) of the Gibbs
free-energy surface; the pre-Loqo default converges to the correct basin
(pH ≈ 2.25). Documented in the test comment. - All compiler warnings cleaned up in
src/ipm.rs,rmumps/src/frontal.rs,
and the adversary example suite. - 13 adversary example files updated to the current
NlpProblemtrait
signature (removed_new_x: boolparameters and-> boolreturn types). tests/large_scale_benchmark.rsunused import cleaned up.
Performance
- Fresh benchmark results (2026-04-11 on Apple Mac Mini, aarch64-apple-darwin):
- HS suite: ripopt 115/120 (95.8%), Ipopt 116/120 (96.7%) — nearly tied.
14.0× geometric mean speedup on 113 commonly solved, median 15.1×,
ripopt faster on 111/113 (98%). - CUTEst suite: ripopt 553/727 (76.1%), Ipopt 561/727 (77.2%). 8.0× geometric
mean speedup on 513 commonly solved, median 18.8×, ripopt faster on 415/513 (81%).
ripopt-only solves: 40; Ipopt-only solves: 48. - Electrolyte thermodynamics: ripopt 13/13 (100%), Ipopt 12/13, 20.8× geo mean.
- Grid (AC OPF): 4/4 for both, Ipopt faster (0.2× geo mean).
- HS suite: ripopt 115/120 (95.8%), Ipopt 116/120 (96.7%) — nearly tied.
- gas pipeline NLPs: sparse GN restoration reduces per-step cost 300× on m > 500.
Notes
- The fresh benchmark shows a small shift in both solvers' solve counts vs. the
0.6.1 numbers reported in the prior CHANGELOG. This reflects run-to-run
floating-point sensitivity on borderline problems combined with the quality-chain
changes; the dominant failure modes (NumericalError, LocalInfeasibility) are
unchanged.