linrax: A JAX-Compatible, SimplexThC21.1 @ ACC 2026
Georgia Institute of Technology
Many control techniques solve an automatically generated optimization problem at every time step:
Big Questions
JAX Functional ParadigmMany toolkits can solve general form:
\[ \min_{x \in [l, u]} c^\top x \quad \text{s.t.} \quad A_{\rm eq}\, x = b_{\rm eq}, \quad A_{\rm ub}\, x \leq b_{\rm ub}. \]
Our Contribution
linrax: the first simplex-based LP solver in JAX.
jit, jacfwd, vmap)Nominal optimal control trajectories often hug obstacles
Problem
We want to “nudge” the feedforward input \(u_{\rm ff}\) such that the entire reachable set robustly avoids the obstacle.
LP refinement greatly tightens reachable sets
JAX Control Pipelinejit
vmap
\(\texttt{SafetyCheck}\):jacfwd
ComputeConvert to canonical form:
Convert to canonical form:
Problem
JAX does not allow the static shape of arrays to depend on traced values.
Problem
Requires BFS (vertex of the feasible region) to initialize pivoting process.
Solution
Auxiliary problem finds a feasible vertex:
\[ \min_{x, a \ge 0} \begin{bmatrix} 0_{1 \times n} & 1_{1 \times m} \end{bmatrix} \begin{bmatrix} x \\ a\end{bmatrix} \text{ s.t. } \begin{bmatrix} A & \mathbf{I}_{m} \end{bmatrix} \begin{bmatrix} x \\ a \end{bmatrix} = b. \]
Problem
For degenerate LPs, auxiliary variables may remain in the active set after phase 1.
Idea: Mark stuck auxiliary rows in ratio test so they exit the basis on the first opportunity in Phase 2.
20 input variables, 15 inequality constraints, \(N = 100\) samples.
| Method | jit (s) | Solve time (s) |
|---|---|---|
scipy |
— | \(1.08\cdot 10^{-3} \pm 7.96\cdot 10^{-4}\) |
gurobi |
— | \(2.23\cdot 10^{-3} \pm 4.61\cdot 10^{-3}\) |
cvxpy |
— | \(1.18\cdot 10^{-3} \pm 8.88\cdot 10^{-4}\) |
jaxopt |
0.95 | \(3.48\cdot 10^{-2} \pm 3.50\cdot 10^{-3}\) |
linrax |
1.23 | \(\mathbf{6.26\cdot 10^{-3} \pm 7.87\cdot 10^{-4}}\) |
Results
JAX optionVan der Pol reachable set computation, \(\mu = 1\), \(t_f = 0.628\), \(N = 10\).
| Method | jit (s) | Total time (s) | Bound size |
|---|---|---|---|
scipy |
— | \(37.8 \pm 1.0\) | \(7.01\cdot 10^{-2}\) |
gurobi |
— | \(44.7 \pm 2.2\) | \(6.86\cdot 10^{-2}\) |
cvxpy |
— | crashed | — |
jaxopt |
4.13 | \(56.6 \pm 0.6\) | \(8.85\cdot 10^{-2}\) (loose) |
linrax |
6.25 | \(\mathbf{2.13 \pm 0.06}\) | \(6.87\cdot 10^{-2}\) |
Results
scipy, ~20× faster than gurobicvxpy crashes; jaxopt is slow and converges to a worse boundJAX optimization for control has unique advantages and challenges
linrax: first simplex-based LP solver in JAX
jit, jacfwd, vmap Possible Future work:
pip install linrax
Personal website: