Diffilqrax: Differentiable optimal control
What is it?
Diffilqrax is a JAX library for LQR and iterative LQR (iLQR) optimal control. It provides:
- Sequential and parallel solvers. The sequential solvers use a Riccati recursion
(
lqr.solve_lqr,ilqr.ilqr_solver). The parallel solvers use an associative scan with O(log T) depth (plqr.solve_plqr,parallel_ilqr.pilqr_solver). - Robust iLQR. It uses adaptive Levenberg–Marquardt regularisation and an Armijo line search, and stops based on the KKT conditions.
- Exact implicit gradients.
diff_lqr.dlqr,diff_ilqr.dilqrand their parallel versionspdlqrandpdilqrdefine custom VJPs, sojax.graddifferentiates the optimal trajectory with respect to the dynamics and cost parameters without backpropagating through the solver iterations. - Batched solves.
batch.batched_ilqr_solverandbatch.batched_dilqrsolve many problems that share a model, withvmap, chunkedlax.maporshard_mapacross devices.
Note on reverse mode. The solvers run as a
lax.while_loopby default (loop="while"), sojax.gradcannot backpropagate throughilqr_solverorpilqr_solverdirectly. To get gradients of the solution, usedilqr,pdilqrorbatched_dilqr. To backpropagate through the iterations themselves, passloop="scan". This stores every iteration and always runs allmax_iterof them undervmap.
Installation
From PyPI, with pip or uv:
pip install diffilqrax
uv pip install diffilqrax # into the active environment
uv add diffilqrax # as a dependency of a uv project
The latest version straight from GitHub:
uv pip install "git+https://github.com/ThomasMullen/diffilqrax"
For development, from a local clone:
git clone git@github.com:ThomasMullen/diffilqrax.git
cd diffilqrax
uv pip install -e ".[dev]" # or: pip install -e ".[dev]" (tests and linting)
uv pip install -e ".[doc]" # documentation
uv build # sdist + wheel in dist/
Importing diffilqrax enables JAX double precision (jax_enable_x64).
Quick example
This example swings a pendulum up from hanging down to upright:
import jax.numpy as jnp
from diffilqrax.ilqr import ilqr_solver
from diffilqrax.diff_ilqr import dilqr
from diffilqrax.typs import System, ModelDims, iLQRParams, PendulumParams
dims = ModelDims(n=2, m=1, horizon=100, dt=0.05)
def dynamics(t, x, u, theta): # x = [angle, angular velocity]
acc = -theta.g / theta.l * jnp.sin(x[0]) + u[0] / (theta.m * theta.l**2)
return x + dims.dt * jnp.stack([x[1], acc])
def cost(t, x, u, theta):
return 0.01 * jnp.sum(u**2)
def costf(x, theta):
return 10.0 * ((x[0] - jnp.pi) ** 2 + x[1] ** 2)
model = System(cost, costf, dynamics, dims)
params = iLQRParams(x0=jnp.zeros(2), theta=PendulumParams(m=1.0, l=1.0, g=9.81))
Us_init = jnp.zeros((dims.horizon, dims.m))
(Xs, Us, lambdas), total_cost, cost_history = ilqr_solver(model, params, Us_init, max_iter=200)
# differentiable version: tau = [x_t, u_t], with implicit gradients w.r.t. params
tau = dilqr(model, params, Us_init, max_iter=200)
More examples are in the documentation notebooks (docs/source/examples/) and in examples/.
Documentation
The documentation is hosted at https://thomasmullen.github.io/diffilqrax/.
Build the docs locally (this also needs pandoc, for example brew install pandoc):
pip install -e ".[doc]"
make -C docs html
open docs/build/html/index.html
Tests
pytest tests/ -m "not slow and not heavy" # quick tier, as run in CI
pytest tests/ -m "not slow" # fast suite: adds the heavy cases
pytest tests/ -m slow # large-dimension tests
The heavy cases (listed in tests/conftest.py) are too slow or memory-hungry for a GitHub runner and
re-check properties that a cheaper test already covers. CI runs the quick tier; the full tiers can be
started by hand from the "Python package" workflow.
Benchmarks import the shared test problems from tests/, so run them as modules from the repository root,
for example python -m benchmarks.timing --quick.
The tests run on the CPU by default. Set DIFFILQRAX_TEST_PLATFORM=gpu to run them on a GPU instead.
Design principle
License
This project is licensed under the Apache License 2.0. See the LICENSE file for details.
Acknowledgments
This project has received funding from the European Union’s Horizon 2020 research and innovation programme under the Marie Skłodowska-Curie grant agreement #813457.
Metadata
Release files for diffilqrax 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| diffilqrax-1.0.0.tar.gz | 83.9 kB | Without provenance | Details for diffilqrax-1.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| diffilqrax-1.0.0-py3-none-any.whl | Python 3 | none | any | Details for diffilqrax-1.0.0-py3-none-any.whl |
Total release size: 137.5 kB
Release files / diffilqrax-1.0.0.tar.gz
| Download URL | diffilqrax-1.0.0.tar.gz |
|---|---|
| Size | 83.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7a0ebb3d9fda60585808d6408e4f6af225edb2a16dab016763b0e18fffce0776
|
|
BLAKE2b-256 checksum How to use checksums |
c80290860f637e608b6c7db208101ac57bd5129cf113247ceb488de4f653cc94
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / diffilqrax-1.0.0-py3-none-any.whl
| Download URL | diffilqrax-1.0.0-py3-none-any.whl |
|---|---|
| Size | 53.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
488aef22cc88b22d367d52903f1ab575de385a3eb5d668b63ba13e7a0485cb02
|
|
BLAKE2b-256 checksum How to use checksums |
66803a2c0cfbf7c34cde5d9ae51a232b83d1cdb5d7c60a2a742b4c1ae8216caa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for diffilqrax 1.0.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A 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.
To learn more about protecting yourself from malicious actors, visit our package security documentation.