Rust-backed SLSQP optimiser with Python bindings
Project description
rslsqp
A fast, pure-Rust reimplementation of the classic SLSQP (Sequential Least-Squares Quadratic Programming) optimiser — 1.5× faster than SciPy on average, up to 2.5× on constraint-heavy problems — with seamless Python bindings via PyO3.
Drop-in replacement for scipy.optimize.minimize(method='SLSQP'). Change one
import line — get a faster solver.
✨ Features
- 🚀 1.5× faster than SciPy — benchmarked across 12 problems (Rosenbrock, portfolio optimisation, constrained quadratics, nonlinear least-squares). Up to 2.5× faster on large, constraint-heavy problems.
- 🦀 Pure-Rust solver core — the entire iteration loop, BFGS update, QP sub-problem, and line-search run in compiled Rust; only objective/gradient callbacks cross the Python boundary.
- 🔌 Drop-in SciPy replacement —
from rslsqp import minimizeworks exactly likescipy.optimize.minimize(method='SLSQP'). - 🐍 Pythonic OO interface —
SlsqpSolverwith analytic or finite-difference gradients, iteration callbacks, and user-triggered abort. - 🧮 Optional BLAS acceleration — link against macOS Accelerate or Linux OpenBLAS for even faster Level-1 / LAPACK operations.
- ⚡ Zero-copy where possible — 1-D arrays are shared between NumPy and Rust without copying.
Installation
Requires Python ≥ 3.12, a Rust toolchain, and maturin.
# Clone and build
git clone https://github.com/<you>/rslsqp.git
cd rslsqp
uv sync
uv run maturin develop --release # pure-Rust build
# — or —
uv run maturin develop --release --features blas # with BLAS/Accelerate
Runtime dependency: NumPy ≥ 2.4. For tests and benchmarks: SciPy ≥ 1.17.
Quick start
import numpy as np
from rslsqp import SlsqpSolver, GradientMode
def func(x):
f = 100 * (x[1] - x[0]**2)**2 + (1 - x[0])**2
c = np.array([1 - x[0]**2 - x[1]**2]) # inequality: c >= 0
return f, c
def grad(x):
g = np.array([
-400 * (x[1] - x[0]**2) * x[0] - 2 * (1 - x[0]),
200 * (x[1] - x[0]**2),
])
a = np.array([[-2 * x[0], -2 * x[1]]])
return g, a
solver = SlsqpSolver(
func=func, grad=grad,
xl=np.array([-1.0, -1.0]),
xu=np.array([ 1.0, 1.0]),
m=1, meq=0,
)
result = solver.optimize(np.array([0.1, 0.1]))
print(result.x, result.fun, result.success)
SciPy-compatible interface
rslsqp.minimize is a drop-in replacement for
scipy.optimize.minimize(method='SLSQP'). It accepts the same arguments and
returns a compatible OptimizeResult:
from rslsqp import minimize
result = minimize(
fun, x0,
jac=jac, # callable, True, '2-point', '3-point'
bounds=bounds, # sequence of (lo, hi) or scipy.optimize.Bounds
constraints=constraints, # list of {'type': 'eq'/'ineq', 'fun': …, 'jac': …}
options={'maxiter': 200, 'ftol': 1e-10},
)
print(result.x, result.fun, result.nit, result.success)
Switching from SciPy requires changing only the import line:
- from scipy.optimize import minimize
+ from rslsqp import minimize
API overview
Enums
| Enum | Values | Description |
|---|---|---|
GradientMode |
USER, FORWARD, BACKWARD, CENTRAL |
How gradients are supplied or approximated |
LinesearchMode |
INEXACT, EXACT |
Line-search strategy |
NnlsMode |
NNLS, BVLS |
Non-negative least-squares sub-solver |
SlsqpStatus |
CONVERGED, MAX_ITERATIONS_REACHED, … |
Solver exit status |
Classes
| Class | Description |
|---|---|
SlsqpSolver |
OO interface — configure once, call optimize(x0) |
SlsqpResult |
Result of SlsqpSolver.optimize() (x, fun, constraints, status, iterations, success) |
OptimizeResult |
SciPy-compatible result from minimize() (x, fun, jac, nit, nfev, njev, success, message) |
Benchmark: rslsqp vs SciPy SLSQP
All benchmarks run with the blas feature enabled (macOS Accelerate on
Apple Silicon). Both solvers receive identical analytic gradients so the
comparison isolates solver-core overhead.
Environment: Python 3.12, NumPy 2.4, SciPy 1.17 — Apple Silicon (arm64), macOS — release build with
--features blas— 10 timed runs, 2 warm-up,maxiter=500,ftol=1e-10.
| Problem | n | Constraints | SciPy (ms) | rslsqp (ms) | Speedup |
|---|---|---|---|---|---|
| Rosenbrock unconstrained | 50 | 0 | 14.85 | 11.58 | 1.28× |
| Rosenbrock unconstrained | 100 | 0 | 62.71 | 54.14 | 1.16× |
| Rosenbrock unconstrained | 200 | 0 | 231.06 | 191.80 | 1.20× |
| Rosenbrock constrained | 50 | 2 | 11.87 | 8.67 | 1.37× |
| Rosenbrock constrained | 100 | 2 | 50.67 | 37.54 | 1.35× |
| Portfolio optimisation | 50 | 2 | 8.32 | 5.18 | 1.61× |
| Portfolio optimisation | 100 | 2 | 63.92 | 29.84 | 2.14× |
| Portfolio optimisation | 200 | 2 | 494.26 | 195.14 | 2.53× |
| Quadratic + 100 ineq | 50 | 100 | 33.15 | 16.33 | 2.03× |
| Quadratic + 200 ineq | 100 | 200 | 266.12 | 117.99 | 2.26× |
| Least-squares fitting | 20 | 1 | 1.35 | 1.34 | 1.00× |
| Least-squares fitting | 40 | 1 | 0.85 | 0.64 | 1.32× |
Geometric mean speedup: 1.54×
The advantage grows with problem size and constraint count — for constraint-heavy problems at n = 100–200 the Rust core is 2–2.5× faster than SciPy's Fortran-based SLSQP.
To reproduce:
uv run maturin develop --release --features blas
uv run python benchmarks/benchmark.py
BLAS acceleration (optional)
On macOS (Accelerate) or Linux (OpenBLAS), build with the blas feature
for faster BLAS Level 1 operations and LAPACK-accelerated QR:
uv run maturin develop --release --features blas
Development
# Install in editable mode (requires maturin + uv)
uv sync
uv run maturin develop --release
# Run tests
uv run pytest
# Run benchmarks
uv run python benchmarks/benchmark.py
A justfile is provided for common tasks:
just release # build in release mode
just release-blas # build with BLAS/Accelerate
just test # run Rust + Python tests
just benchmark-blas # benchmark with BLAS enabled
just lint # lint Rust + Python
just fmt # format all code
Licence
BSD-3-Clause — see LICENSE for details.
Based on the SLSQP algorithm by Dieter Kraft (1988), modernised in Fortran by Jacob Williams (slsqp, BSD-3-Clause).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rslsqp-0.1.1.tar.gz.
File metadata
- Download URL: rslsqp-0.1.1.tar.gz
- Upload date:
- Size: 393.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
86c0df8386f7985fa965ad1ab05dc39d9c71100008458d6a04096883a4007d3e
|
|
| MD5 |
b1279fcd54a93772c6d7c6b1b97f6f8a
|
|
| BLAKE2b-256 |
8e4de6926fb13c95aa0809755cf0f45a8345b534ee4bbe599c38d920ae686a1d
|
Provenance
The following attestation bundles were made for rslsqp-0.1.1.tar.gz:
Publisher:
release.yml on oberbichler/rslsqp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rslsqp-0.1.1.tar.gz -
Subject digest:
86c0df8386f7985fa965ad1ab05dc39d9c71100008458d6a04096883a4007d3e - Sigstore transparency entry: 1615411923
- Sigstore integration time:
-
Permalink:
oberbichler/rslsqp@6e02697751fbd3a1e7e438f4303e268dbc83eac6 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/oberbichler
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6e02697751fbd3a1e7e438f4303e268dbc83eac6 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file rslsqp-0.1.1-cp39-abi3-win_amd64.whl.
File metadata
- Download URL: rslsqp-0.1.1-cp39-abi3-win_amd64.whl
- Upload date:
- Size: 248.1 kB
- Tags: CPython 3.9+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8111370c957c1ed23457fff0e59a4e8a7ba45af30307bc79ea15f2296ec079d4
|
|
| MD5 |
e82144ece801dd05d3cab9619c224e76
|
|
| BLAKE2b-256 |
2964b84f036e00dbce4a23c6b79de27c32a490bcc9b8cb95eb80b64bff44854f
|
Provenance
The following attestation bundles were made for rslsqp-0.1.1-cp39-abi3-win_amd64.whl:
Publisher:
release.yml on oberbichler/rslsqp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rslsqp-0.1.1-cp39-abi3-win_amd64.whl -
Subject digest:
8111370c957c1ed23457fff0e59a4e8a7ba45af30307bc79ea15f2296ec079d4 - Sigstore transparency entry: 1615411930
- Sigstore integration time:
-
Permalink:
oberbichler/rslsqp@6e02697751fbd3a1e7e438f4303e268dbc83eac6 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/oberbichler
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6e02697751fbd3a1e7e438f4303e268dbc83eac6 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file rslsqp-0.1.1-cp39-abi3-manylinux_2_34_aarch64.whl.
File metadata
- Download URL: rslsqp-0.1.1-cp39-abi3-manylinux_2_34_aarch64.whl
- Upload date:
- Size: 7.9 MB
- Tags: CPython 3.9+, manylinux: glibc 2.34+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e195b34d43f1bb22e9a7e9fbac01fc7cbba25799786cc682fdb4563e99d55208
|
|
| MD5 |
014687ada3f7609d32d86035de29fcde
|
|
| BLAKE2b-256 |
070a56e29ed127e7b51b52d5f1a7eb8ffb0cb04715689de75cb748ef6621c96c
|
Provenance
The following attestation bundles were made for rslsqp-0.1.1-cp39-abi3-manylinux_2_34_aarch64.whl:
Publisher:
release.yml on oberbichler/rslsqp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rslsqp-0.1.1-cp39-abi3-manylinux_2_34_aarch64.whl -
Subject digest:
e195b34d43f1bb22e9a7e9fbac01fc7cbba25799786cc682fdb4563e99d55208 - Sigstore transparency entry: 1615411961
- Sigstore integration time:
-
Permalink:
oberbichler/rslsqp@6e02697751fbd3a1e7e438f4303e268dbc83eac6 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/oberbichler
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6e02697751fbd3a1e7e438f4303e268dbc83eac6 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file rslsqp-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: rslsqp-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 10.9 MB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0ac47502e822b43e4568370e3e8120357ec3c3c887148395ffac7b21638e7a79
|
|
| MD5 |
27855c2a84e23a775c87070098e2f32c
|
|
| BLAKE2b-256 |
8740edcce3824ef27a7a35a9014386528dd19e67d8e6112aeb2491fd792ef585
|
Provenance
The following attestation bundles were made for rslsqp-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on oberbichler/rslsqp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rslsqp-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
0ac47502e822b43e4568370e3e8120357ec3c3c887148395ffac7b21638e7a79 - Sigstore transparency entry: 1615411941
- Sigstore integration time:
-
Permalink:
oberbichler/rslsqp@6e02697751fbd3a1e7e438f4303e268dbc83eac6 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/oberbichler
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6e02697751fbd3a1e7e438f4303e268dbc83eac6 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file rslsqp-0.1.1-cp39-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: rslsqp-0.1.1-cp39-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 333.4 kB
- Tags: CPython 3.9+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
22c77874ff7b8e487ee0753f9677f2f8a16925806e1b73fdc7014cf0ad3ea6b4
|
|
| MD5 |
d1ee5993f0b3cdcea9eae5cdd8f93182
|
|
| BLAKE2b-256 |
3ddcfc9f8c72b156c1a71fd2050810eed55b0a4eb1031f3b31a7539b93aa0128
|
Provenance
The following attestation bundles were made for rslsqp-0.1.1-cp39-abi3-macosx_11_0_arm64.whl:
Publisher:
release.yml on oberbichler/rslsqp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rslsqp-0.1.1-cp39-abi3-macosx_11_0_arm64.whl -
Subject digest:
22c77874ff7b8e487ee0753f9677f2f8a16925806e1b73fdc7014cf0ad3ea6b4 - Sigstore transparency entry: 1615411950
- Sigstore integration time:
-
Permalink:
oberbichler/rslsqp@6e02697751fbd3a1e7e438f4303e268dbc83eac6 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/oberbichler
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6e02697751fbd3a1e7e438f4303e268dbc83eac6 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file rslsqp-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: rslsqp-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 348.5 kB
- Tags: CPython 3.9+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
00e8db2ea1ba852dbe4111de093eb3320296f0e450a138fa53ac5d5e38ac10f1
|
|
| MD5 |
1f669292fb39adee58fca9e175ed1748
|
|
| BLAKE2b-256 |
1b4790b0085d2d9c65fafe1afc36be8a4dacb668f90f977fec04ca785183bcbe
|
Provenance
The following attestation bundles were made for rslsqp-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl:
Publisher:
release.yml on oberbichler/rslsqp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rslsqp-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl -
Subject digest:
00e8db2ea1ba852dbe4111de093eb3320296f0e450a138fa53ac5d5e38ac10f1 - Sigstore transparency entry: 1615411957
- Sigstore integration time:
-
Permalink:
oberbichler/rslsqp@6e02697751fbd3a1e7e438f4303e268dbc83eac6 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/oberbichler
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6e02697751fbd3a1e7e438f4303e268dbc83eac6 -
Trigger Event:
workflow_dispatch
-
Statement type: