ripopt (Python)
Direct Python bindings for ripopt, the Rust interior-point NLP solver. Derivatives are built automatically from the user's objective and constraints via JAX autodiff, so you only have to write f(x) and g(x).
This is the analogue of cyipopt for ripopt. For symbolic modeling via Pyomo, see the separate pyomo-ripopt package.
Install
pip install maturin jax jaxlib numpy
maturin develop --release
Example: HS071
import jax.numpy as jnp
import numpy as np
from ripopt import minimize
def f(x):
return x[0] * x[3] * (x[0] + x[1] + x[2]) + x[2]
def g(x):
return jnp.array([
x[0] * x[1] * x[2] * x[3],
x[0]**2 + x[1]**2 + x[2]**2 + x[3]**2,
])
res = minimize(
f,
x0=[1.0, 5.0, 5.0, 1.0],
bounds=(1.0, 5.0),
constraints={"fun": g, "lb": [25.0, 40.0], "ub": [np.inf, 40.0]},
options={"tol": 1e-8},
)
print(res.x, res.fun)
Reusing a problem across many solves
minimize(...) is a single-shot scipy-style API: every call re-traces and re-JITs jax.hessian(lagrangian), which is the single most expensive step for a medium-sized problem. When you solve the same NLP structure many times in a row (e.g. closed-loop NMPC), use the persistent Problem class instead — it builds every JAX callback exactly once and reuses the XLA cache across all solves:
import jax.numpy as jnp
from ripopt import Problem
def stage_cost(z, x0):
x, u = z[:N], z[N:]
return jnp.sum((x - r) ** 2) + 0.01 * jnp.sum(u ** 2)
def dynamics(z, x0):
x, u = z[:N], z[N:]
x_prev = jnp.concatenate([jnp.atleast_1d(x0[0]), x[:-1]])
return x - A * x_prev - B * u
prob = Problem(
stage_cost,
x0=np.zeros(2 * N),
bounds=(lb, ub),
constraints={"fun": dynamics, "lb": 0.0, "ub": 0.0},
params=jnp.array([x0_current]), # extra traced arg threaded into fun and g
jac_mode="reverse", # jacrev is typically cheaper when m ≤ n
options={"tol": 1e-6},
)
for step in range(100):
prob.update_parameters(jnp.array([x0_current]))
res = prob.solve() # warm-starts from previous x* by default
examples/bench_nmpc.py runs this same pattern 100 times and compares minimize() vs Problem.solve() — the persistent object is typically several× faster because JAX tracing and XLA lowering of the Lagrangian Hessian happen exactly once for the Problem's lifetime, not once per call.
Warm-starting from an external solution
Problem.solve() accepts an explicit dual warm-start triple (lam0, z_l0, z_u0) — the constraint multipliers and upper/lower bound multipliers. This is the ripopt equivalent of seeding Ipopt with a cyipopt solution and lets you verify "is the reported x, λ, z_L, z_U a KKT point of this NLP?" independently of the solver's own initial-point and LS-estimate paths:
# e.g. a cyipopt solution you want ripopt to verify
x_star, lam_star, z_l_star, z_u_star = cyipopt_result
res = prob.solve(
x0=x_star,
lam0=lam_star,
z_l0=z_l_star,
z_u0=z_u_star,
)
All three dual arrays must be supplied together (partial specs raise ValueError); passing any of them implies warm_start=True. On plain NMPC-style restarts where you simply want to reuse the previous solve's multipliers, prob.solve(warm_start=True) is the shorter form.
API
minimize(fun, x0, *, bounds=None, constraints=None, options=None, sparsity='dense', params=None, jac_mode='forward') -> OptimizeResult
fun(x)— scalar, JAX-traceable.bounds—None,(lb, ub)with scalars or arrays of length n, or a scipy-style list of(lb_i, ub_i)pairs.constraints— a dict{"fun": g, "lb": ..., "ub": ...}or a list of such dicts. Uselb == ubfor equality.options— recognized keys:tol,max_iter,print_level,constr_viol_tol,dual_inf_tol,compl_inf_tol,max_wall_time,mu_init,hessian_approximation("exact"or"limited-memory").sparsity—'dense'(default) declares every entry structurally nonzero.'detect'probes the Jacobian and Lagrangian Hessian with two random(x, sigma, lambda)samples and takes the union of nonzero entries; with random multipliers, structural nonzeros are identified almost surely.
hessian_approximation="limited-memory" skips building the Hessian entirely and uses ripopt's L-BFGS path — useful when jax.hessian becomes expensive for larger problems.
Ctrl-C is honored: each callback polls PyErr_CheckSignals and the stashed KeyboardInterrupt is re-raised when the solve returns.
Performance
Rough numbers for HS071 on an M-series Mac, release build, warm JIT cache:
| configuration | total wall | solver only | iterations |
|---|---|---|---|
sparsity='dense' |
~155 ms | ~32 ms | 18 |
sparsity='detect' |
~155 ms | ~32 ms | 18 |
Raw ripopt (Rust) on the same problem is ~3 ms. The gap is per-callback JAX dispatch (~300 µs × 5 callbacks × 18 iterations ≈ 27 ms); for problems where ripopt dominates the wall clock this gap is amortized. Run python examples/bench_hs071.py to reproduce.
Documentation
examples/tutorial.ipynb— runnable notebook walking through unconstrained, box-constrained, HS071, options, L-BFGS, sparsity detection, and multi-block constraintsdocs/user_guide.md— task-oriented prose guide (JAX tips, constraint patterns, troubleshooting)docs/api.md— strict reference forminimize,OptimizeResult, and the options dict
Status
Early prototype. Sparsity detection uses a two-probe random-multiplier union — safe for structurally-honest code but defeated by rare numerical cancellations. A wheel is built by maturin build --release; cross-platform wheels, PyPI release, and a symbolic sparsity path are future work.
Metadata
Release files for ripopt 0.8.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| ripopt-0.8.2-cp39-abi3-win_amd64.whl | CPython 3.9 | abi3 | Windows x86-64 | Details |
| ripopt-0.8.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| ripopt-0.8.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| ripopt-0.8.2-cp39-abi3-macosx_11_0_arm64.whl | CPython 3.9 | abi3 | macOS 11.0+ ARM64 | Details |
| ripopt-0.8.2-cp39-abi3-macosx_10_12_x86_64.whl | CPython 3.9 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 49.3 MB
Release files / ripopt-0.8.2-cp39-abi3-win_amd64.whl
| Download URL | ripopt-0.8.2-cp39-abi3-win_amd64.whl |
|---|---|
| Size | 2.2 MB |
| Tags | CPython 3.9 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
ac0c58b8a279ccacd3db45a24d329bc94920b0d203e9aca1278b1ee78ef9902a
|
|
BLAKE2b-256 checksum How to use checksums |
88a171d48ebcb4ea0508dd8f61a7ca1e332f1a7775c431adb1ea6bbed848d341
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 22, 2026.
Transparency logRelease files / ripopt-0.8.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | ripopt-0.8.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 22.0 MB |
| Tags | CPython 3.9 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
e44e51ee1d8044caa4d972ec26cd45bbe2306e69e3b2ce3f2acb19146d074ee8
|
|
BLAKE2b-256 checksum How to use checksums |
243896d22649d8dca6a425afc35b7a1a22105ed56eda07ba23c8b4af1dc6ecb6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 22, 2026.
Transparency logRelease files / ripopt-0.8.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | ripopt-0.8.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 20.8 MB |
| Tags | CPython 3.9 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
2173820c5427c38c26b203f1cf94e0da407b5fc5dc99ecb45fd09913f071a3a8
|
|
BLAKE2b-256 checksum How to use checksums |
21fad9d8095e76f8853a2cf37ef572cff3d58608f6cfc77b5ffff00ed789b1d7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 22, 2026.
Transparency logRelease files / ripopt-0.8.2-cp39-abi3-macosx_11_0_arm64.whl
| Download URL | ripopt-0.8.2-cp39-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 2.1 MB |
| Tags | CPython 3.9 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
3a56e6070c5c90a4906dbea8cb0b2a318f655d400e0a9fc17a4548d31d87c12e
|
|
BLAKE2b-256 checksum How to use checksums |
0097ee082de34245d82d4ff9d192a78d6d6e2ea1a15321587a4247b9c8f7be9b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 22, 2026.
Transparency logRelease files / ripopt-0.8.2-cp39-abi3-macosx_10_12_x86_64.whl
| Download URL | ripopt-0.8.2-cp39-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 2.2 MB |
| Tags | CPython 3.9 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
e500cc082ec311182e686c3ccb105e71711ae407e77f89b834e0f5090200af6f
|
|
BLAKE2b-256 checksum How to use checksums |
7e65e8fefa475ffc70177dcce44c68d898ee35560ef793046913b5f78a2392e3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 22, 2026.
Transparency logSecurity for ripopt 0.8.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 5 files in this release have been uploaded with provenance metadata.
Attestation for ripopt-0.8.2-cp39-abi3-win_amd64.whl
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 22, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.