tiny-solver-rs
Warning! This project is still under development.
Inspired by ceres-solver, tiny-solver, and minisam.
This is a general optimizer written in Rust, including bindings for Python. If you're familiar with ceres-solver or factor-graph optimizers, you'll find it very easy to use.
Installation
python
The python package can be installed directly from PyPI:
pip install tiny-solver
rust
cargo add tiny-solver
Current Features
- Automatic Derivatives using num-dual
-
Sparse QR, Sparse Cholesky using faer - GaussNewtonOptimizer
- Multithreading jacobian
- loss function (Huber)
- Define factor in python
TODO
- LevenbergMarquardtOptimizer
- information matrix
Benchmark
| dataset | tiny-solver | gtsam | minisam |
|---|---|---|---|
| m3500 | 161.1ms | 130.7ms | 123.6 ms |
It's not extremely optimized, but it's easy to install and use.
Usage
Rust
// define your own Cost/Factor struct
// impl residual function
// and the jacobian will be auto generated
struct CustomFactor {}
impl tiny_solver::factors::Factor for CustomFactor {
fn residual_func(
&self,
params: &[nalgebra::DVector<num_dual::DualDVec64>],
) -> nalgebra::DVector<num_dual::DualDVec64> {
let x = ¶ms[0][0];
let y = ¶ms[1][0];
let z = ¶ms[1][1];
na::dvector![x + y.clone().mul(2.0) + z.clone().mul(4.0), y.mul(z)]
}
}
fn main() {
// init logger, `export RUST_LOG=trace` to see more log
env_logger::init();
// init problem (factor graph)
let mut problem = tiny_solver::Problem::new();
// add residual blocks (factors)
// add residual x needs to be close to 3.0
problem.add_residual_block(
1,
vec![("x".to_string(), 1)],
Box::new(tiny_solver::factors::PriorFactor {
v: na::dvector![3.0],
}),
None,
);
// add custom residual for x and yz
problem.add_residual_block(
2,
vec![("x".to_string(), 1), ("yz".to_string(), 2)],
Box::new(CustomFactor {}),
None,
);
// the initial values for x is 0.7 and yz is [-30.2, 123.4]
let initial_values = HashMap::<String, na::DVector<f64>>::from([
("x".to_string(), na::dvector![0.7]),
("yz".to_string(), na::dvector![-30.2, 123.4]),
]);
// initialize optimizer
let optimizer = tiny_solver::GaussNewtonOptimizer {};
// optimize
let result = optimizer.optimize(&problem, &initial_values, None);
// result
for (k, v) in result {
println!("{}: {}", k, v);
}
}
Python
import numpy as np
from tiny_solver import Problem, GaussNewtonOptimizer
from tiny_solver.factors import PriorFactor, PyFactor
# define custom cost function in python
# the trade off is the jacobian for the problem cannot be done in parallel
# because of gil
def cost(x: np.ndarray, yz: np.ndarray) -> np.ndarray:
r0 = x[0] + 2 * yz[0] + 4 * yz[1]
r1 = yz[0] * yz[0]
return np.array([r0, r1])
def main():
# initialize problem (factor graph)
problem = Problem()
# factor defined in python
custom_factor = PyFactor(cost)
problem.add_residual_block(
2,
[
("x", 1),
("yz", 2),
],
custom_factor,
None,
)
# prior factor import from rust
prior_factor = PriorFactor(np.array([3.0]))
problem.add_residual_block(1, [("x", 1)], prior_factor, None)
# initial values
init_values = {"x": np.array([0.7]), "yz": np.array([-30.2, 123.4])}
# optimizer
optimizer = GaussNewtonOptimizer()
result_values = optimizer.optimize(problem, init_values)
# result
for k, v in result_values.items():
print(f"{k}: {v}")
if __name__ == "__main__":
main()
Example
Basic example
cargo run -r --example small_problem
M3500 dataset
git clone https://github.com/powei-lin/tiny-solver-rs.git
cd tiny-solver-rs
# run rust version
cargo run -r --example m3500_benchmar
# run python version
pip install tiny-solver matplotlib
python3 examples/python/m3500.py
Metadata
Release files for tiny-solver 0.7.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| tiny_solver-0.7.0-cp37-abi3-manylinux_2_35_x86_64.whl | CPython 3.7 | abi3 | Linux glibc 2.35+ x86-64 | Details for tiny_solver-0.7.0-cp37-abi3-manylinux_2_35_x86_64.whl |
| tiny_solver-0.7.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.7 | abi3 | Linux glibc 2.17+ ARM64 | Details for tiny_solver-0.7.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
| tiny_solver-0.7.0-cp37-abi3-macosx_11_0_arm64.whl | CPython 3.7 | abi3 | macOS 11.0+ ARM64 | Details for tiny_solver-0.7.0-cp37-abi3-macosx_11_0_arm64.whl |
Total release size: 10.7 MB
Release files / tiny_solver-0.7.0-cp37-abi3-manylinux_2_35_x86_64.whl
| Download URL | tiny_solver-0.7.0-cp37-abi3-manylinux_2_35_x86_64.whl |
|---|---|
| Size | 3.6 MB |
| Tags | CPython 3.7 Linux glibc 2.35+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
bb3b4886e27eaa0dce79ab0f5c64577732f516b369737005aaa190918818ff2c
|
|
BLAKE2b-256 checksum How to use checksums |
a94ba1542c28dbaf84bb68dfb8e5272c806499f5a7c396be3b72a7a07161c8b6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/5.0.0 CPython/3.10.12
|
Release files / tiny_solver-0.7.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | tiny_solver-0.7.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 4.2 MB |
| Tags | CPython 3.7 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
a1c491a74978307b2f74da3685a610a5aa6ac63c1a219d22ba3c6f716cf4a973
|
|
BLAKE2b-256 checksum How to use checksums |
4c128f50cf53e86c46b02d20ae0e9dddcf376e5d3babb3362e2427656bff477a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/5.0.0 CPython/3.10.12
|
Release files / tiny_solver-0.7.0-cp37-abi3-macosx_11_0_arm64.whl
| Download URL | tiny_solver-0.7.0-cp37-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 2.9 MB |
| Tags | CPython 3.7 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
9898dae2bdf83eec9958c2caacef1c49d0f1fd3582cbcb27185170f9e194b91b
|
|
BLAKE2b-256 checksum How to use checksums |
431e387913676301a7efeb46af37ae62ef7139670e1095a3dcba037233613f58
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/5.1.1 CPython/3.12.6
|
Security for tiny-solver 0.7.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.