Skip to content

Commit 4208e42

Browse files
committed
first commit
1 parent c3ba913 commit 4208e42

14 files changed

Lines changed: 916 additions & 12 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,5 @@ ENV/
8080
.Python
8181
build/
8282
*.pyc
83+
84+
.ruff_cache

Cargo.lock

Lines changed: 97 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ name = "fastlap"
99
crate-type = ["cdylib"]
1010

1111
[dependencies]
12-
pyo3 = "0.25.0"
12+
pyo3 = { version = "0.25.0", features = ["extension-module", "anyhow", "auto-initialize"] }
13+
numpy = "0.25"

README.md

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,46 @@
1+
12
# fastlap
2-
Python's LAP library written in Rust.
3+
4+
**Python’s LAP (Linear Assignment Problem) solver — written in Rust for performance.**
5+
6+
`fastlap` provides a blazing-fast implementation of common assignment algorithms such as:
7+
8+
- Jonker-Volgenant (LAPJV)
9+
- Hungarian (a.k.a. Munkres)
10+
11+
Built with [Rust](https://www.rust-lang.org/) and exposed to Python via [PyO3](https://pyo3.rs), this library offers performance and interoperability in one package.
12+
13+
14+
## ✨ Features
15+
16+
- ✅ Fast and memory-safe implementation in Rust
17+
- ✅ Python bindings via PyO3
18+
- ✅ Supports both `lapjv` and `hungarian` algorithms
19+
- ✅ Can be used in native Rust projects or as a Python package
20+
21+
22+
## 📖 Algorithms
23+
24+
* **LAPJV** – Efficient dual-based shortest augmenting path algorithm (Jonker & Volgenant, 1987)
25+
* **Hungarian** – Classic method with row/column reduction and assignment phases
26+
27+
## Roadmap
28+
29+
- [ ] Release first version
30+
- [ ] Add more algorithms
31+
- [ ] Add more features
32+
- [ ] Add more examples
33+
- [ ] Add more tests
34+
- [ ] Add more benchmarks
35+
36+
37+
## 📚 References
38+
39+
* Jonker, R., & Volgenant, A. (1987). *A shortest augmenting path algorithm for dense and sparse linear assignment problems*. Computing, 38(4), 325–340.
40+
* Munkres, J. (1957). *Algorithms for the Assignment and Transportation Problems*. Journal of the Society for Industrial and Applied Mathematics.
41+
42+
43+
## 📃 License
44+
45+
MIT License © 2025
46+

pyproject.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,12 @@ classifiers = [
1111
"Programming Language :: Python :: Implementation :: PyPy",
1212
]
1313
dynamic = ["version"]
14+
dependencies = [
15+
"lap>=0.4.0",
16+
"maturin>=1.8.7",
17+
"numpy>=1.20,<2.0",
18+
"pytest>=7.0",
19+
"scipy>=1.8",
20+
]
1421
[tool.maturin]
1522
features = ["pyo3/extension-module"]

python/fastlaps.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import time
2+
import fastlap
3+
import numpy as np
4+
from scipy.optimize import linear_sum_assignment
5+
import lap
6+
7+
8+
if __name__ == "__main__":
9+
# Quick example for a 3x3 matrix
10+
matrix = np.random.rand(4, 5)
11+
for algo in ["lapjv", "hungarian"]:
12+
print(f"\nAlgorithm: {algo}")
13+
start = time.time()
14+
fastlap_cost, fastlap_rows, fastlap_cols = fastlap.solve_lap(matrix, algo)
15+
fastlap_end = time.time()
16+
print(f"fastlap.{algo}: Time={fastlap_end - start:.8f}s")
17+
print(
18+
f"fastlap.{algo}: Cost={fastlap_cost}, Rows={fastlap_rows}, Cols={fastlap_cols}"
19+
)
20+
if algo == "hungarian":
21+
start = time.time()
22+
scipy_rows, scipy_cols = linear_sum_assignment(matrix)
23+
scipy_cost = matrix[scipy_rows, scipy_cols].sum()
24+
scipy_end = time.time()
25+
print(
26+
f"scipy.optimize.linear_sum_assignment: Time={scipy_end - start:.8f}s"
27+
)
28+
print(
29+
f"scipy.optimize.linear_sum_assignment: Cost={scipy_cost}, Rows={list(scipy_rows)}, Cols={list(scipy_cols)}"
30+
)
31+
if algo == "lapjv":
32+
start = time.time()
33+
lap_cost, lap_rows, lap_cols = lap.lapjv(matrix, extend_cost=True)
34+
lap_end = time.time()
35+
print(f"lap.lapjv: Time={lap_end - start:.8f}s")
36+
print(f"lap.lapjv: Cost={lap_cost}, Rows={lap_rows}, Cols={lap_cols}")
37+
38+
"""
39+
First release:
40+
41+
Algorithm: lapjv
42+
fastlap.lapjv: Time=0.00017548s
43+
fastlap.lapjv: Cost=inf, Rows=[2, 0, 1, 4, 3], Cols=[1, 2, 0, 4, 3]
44+
lap.lapjv: Time=0.00013208s
45+
lap.lapjv: Cost=0.6229432588732741, Rows=[2 0 1 4], Cols=[ 1 2 0 -1 3]
46+
47+
Algorithm: hungarian
48+
fastlap.hungarian: Time=0.00000453s
49+
fastlap.hungarian: Cost=0.7465856501551806, Rows=[2, 0, 1, 3], Cols=[1, 2, 0, 3, 18446744073709551615]
50+
scipy.optimize.linear_sum_assignment: Time=0.00001287s
51+
scipy.optimize.linear_sum_assignment: Cost=0.6229432588732741, Rows=[0, 1, 2, 3], Cols=[2, 0, 1, 4]
52+
"""

python/init_test.py

Lines changed: 0 additions & 4 deletions
This file was deleted.

python/lapjv.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import lap
2+
import numpy as np
3+
import time
4+
5+
6+
if __name__ == "__main__":
7+
array = np.random.rand(4, 5)
8+
start = time.time()
9+
result = lap.lapjv(array, extend_cost=True)
10+
end = time.time()
11+
print(f"lapjv: Time={end - start:.8f}s")
12+
print(result)

0 commit comments

Comments
 (0)