Rust-accelerated high-performance clustering algorithms.
Project description
Clustor
Clustor is a Rust-accelerated clustering toolkit with a Python-first API built on PyO3 and maturin. It delivers fast, minimal-dependency implementations of common clustering algorithms and cluster validation metrics for use inside production data pipelines.
Clustor focuses on unsupervised learning primitives. Use it alongside dataset balancing tools when you need reweighting or resampling.
[!CAUTION] Active development. APIs may evolve before a 1.0 release.
Features
- KMeans and MiniBatchKMeans with KMeans++ initialization,
n_init, Euclidean/Cosine metrics, optional normalization,sample_weight, and streamingpartial_fit. - BisectingKMeans for hierarchical top-down splitting.
- DBSCAN with noise labeling and core sample indices.
- OPTICS reachability ordering and core distances.
- Affinity Propagation for exemplar-based clustering.
- BIRCH streaming clustering using CF-tree summaries.
- GaussianMixture (EM, diagonal covariance):
predict_proba,score_samples,score,aic,bic,sample, and model selection metrics. - Cluster validation: Silhouette, Calinski–Harabasz, Davies–Bouldin.
- HAC linkage (dendrogram output) with SciPy-style linkage matrices.
Installation
Python (recommended)
Use a virtual environment, then install build tools and the package:
python -m venv .venv
. .venv/bin/activate
pip install -U pip
pip install -U maturin numpy
maturin develop --release
Local development
python -m venv .venv
. .venv/bin/activate
pip install -U pip
pip install -U maturin numpy pytest pre-commit
pre-commit run --all-files
maturin develop --release
pytest -q
Quick usage
import numpy as np
import clustor
X = np.vstack([np.random.randn(200, 2), np.random.randn(200, 2) + 6])
km = clustor.KMeans(n_clusters=2, n_init=10, random_state=0)
result = km.fit(X)
print(result["inertia"])
op = clustor.OPTICS(min_samples=10, max_eps=1.0)
res = op.fit(X)
print(res["reachability"].shape, res["ordering"].shape)
ap = clustor.AffinityPropagation(damping=0.7)
res = ap.fit(X)
print("clusters:", len(res["exemplars"]), "converged:", res["converged"])
br = clustor.Birch(threshold=0.7, branching_factor=30, n_clusters=2)
res = br.fit(X)
print(res["centers"].shape)
Z = clustor.hac_dendrogram(X, method="average", metric="euclidean")
print(Z.shape) # (n-1, 4)
Advanced usage
Streaming MiniBatchKMeans
mb = clustor.MiniBatchKMeans(n_clusters=2, batch_size=2, max_steps=20, random_state=0)
mb.fit(X[:3])
mb.partial_fit(X[3:])
print(mb.predict(X))
Output:
[0 0 0 1 1 1]
GaussianMixture model selection metrics
gm = clustor.GaussianMixture(2, max_iter=50, tol=1e-4, random_state=0)
gm.fit(X)
print(gm.score_samples(X))
print(gm.score(X))
print(gm.aic(X))
print(gm.bic(X))
Output:
[-1.526949 -2.276946 -2.276946 -1.526949 -2.276946 -2.276946]
-2.026946850203142
42.3233622024377
40.4491974254902
Examples with outputs
The following examples use a fixed dataset and deterministic seeds to keep outputs stable.
import numpy as np
import clustor
np.set_printoptions(precision=6, suppress=True)
X = np.array(
[
[0.0, 0.0],
[0.0, 1.0],
[1.0, 0.0],
[10.0, 10.0],
[10.0, 11.0],
[11.0, 10.0],
],
dtype=np.float64,
)
KMeans
km = clustor.KMeans(n_clusters=2, n_init=1, max_iter=50, random_state=0)
km_out = km.fit(X)
print(km_out["centers"])
print(km_out["labels"])
Output:
[[10.333333 10.333333]
[ 0.333333 0.333333]]
[1 1 1 0 0 0]
MiniBatchKMeans
mb = clustor.MiniBatchKMeans(n_clusters=2, batch_size=3, max_steps=200, random_state=0)
mb_out = mb.fit(X)
print(mb_out["centers"])
print(mb.predict(X))
Output:
[[10.374126 10.300699]
[ 0.33121 0.321656]]
[1 1 1 0 0 0]
BisectingKMeans
bk = clustor.BisectingKMeans(n_clusters=2, n_init=1, max_iter=50, random_state=0)
bk_out = bk.fit(X)
print(bk_out["centers"])
print(bk.predict(X))
Output:
[[10.333333 10.333333]
[ 0.333333 0.333333]]
[1 1 1 0 0 0]
DBSCAN
db = clustor.DBSCAN(eps=1.6, min_samples=2)
db_out = db.fit(X)
print(db_out["labels"])
print(db_out["core_sample_indices"])
Output:
[0 0 0 1 1 1]
[0 1 2 3 4 5]
OPTICS
opt = clustor.OPTICS(min_samples=2, max_eps=2.0)
opt_out = opt.fit(X)
print(opt_out["ordering"])
print(opt_out["reachability"])
print(opt_out["core_distances"])
print(opt_out["predecessor"])
Output:
[0 2 1 3 5 4]
[inf 1. 1. inf 1. 1.]
[1. 1. 1. 1. 1. 1.]
[-1 0 0 -1 3 3]
Affinity Propagation
ap = clustor.AffinityPropagation(damping=0.6, max_iter=200, convergence_iter=15)
ap_out = ap.fit(X)
print(ap_out["exemplars"])
print(ap_out["labels"])
print(ap_out["converged"])
Output:
[0 3]
[0 0 0 1 1 1]
True
Birch
br = clustor.Birch(threshold=1.5, branching_factor=10, n_clusters=2)
br_out = br.fit(X)
print(br_out["centers"])
print(br_out["labels"])
print(br_out["n_subclusters"])
Output:
[[10.333333 10.333333]
[ 0.333333 0.333333]]
[1 1 1 0 0 0]
2
GaussianMixture
gm = clustor.GaussianMixture(2, max_iter=50, tol=1e-4, random_state=0)
gm_out = gm.fit(X)
print(gm_out["weights"])
print(gm_out["means"])
print(gm_out["covars"])
print(gm_out["converged"])
Output:
[0.5 0.5]
[[10.333333 10.333333]
[ 0.333333 0.333333]]
[[0.222223 0.222223]
[0.222223 0.222223]]
True
Validation metrics
labels = km_out["labels"]
print(clustor.silhouette_score(X, labels))
print(clustor.calinski_harabasz_score(X, labels))
print(clustor.davies_bouldin_score(X, labels))
Output:
0.9196222281154851
450.00000000000017
0.09249505911485287
HAC linkage
Z = clustor.hac_dendrogram(X, method="average", metric="euclidean")
print(Z)
Output:
[[ 0. 1. 1. 2. ]
[ 3. 4. 1. 2. ]
[ 6. 2. 1.207107 3. ]
[ 7. 5. 1.207107 3. ]
[ 8. 9. 14.165681 6. ]]
API overview
Estimators
KMeans,MiniBatchKMeans,BisectingKMeansDBSCANOPTICSAffinityPropagationBirchGaussianMixture
All estimators accept NumPy arrays and return NumPy arrays for outputs. Methods that accept
sample_weight validate length consistency with the input data.
Functional APIs
kmeans,bisecting_kmeans,dbscan,gaussian_mixtureoptics,affinity_propagation,birch,hac_dendrogram
Metrics
silhouette_score,calinski_harabasz_score,davies_bouldin_score
Data handling and performance
- Inputs are converted to contiguous
float64NumPy arrays for predictable performance. - Heavy computation runs outside the Python GIL for improved multi-threaded throughput when Python threads are present.
- Algorithms are implemented in Rust with minimal dependencies to keep builds lightweight.
Example notebooks
Each notebook is executed with deterministic inputs and includes narrative context plus outputs.
examples/01_kmeans_family.ipynb: KMeans, MiniBatchKMeans, and BisectingKMeans.examples/02_density_clustering.ipynb: DBSCAN and OPTICS.examples/03_affinity_birch.ipynb: Affinity Propagation and Birch.examples/04_gaussian_mixture_metrics.ipynb: GaussianMixture and validation metrics.examples/05_hac_linkage.ipynb: HAC linkage matrices.
Production readiness
- Deterministic results when
random_stateis provided, including in the notebooks. - Strict input validation for shape mismatches, empty datasets, and invalid cluster counts.
- GIL-free Rust kernels for improved parallel throughput in Python pipelines.
- Typed Python API surface (
py.typed) with docstrings that include args/returns/examples.
Edge cases and validation
- Estimators raise
ValueErrorfor empty inputs, invalid shapes, or non-positiven_clusters. - Weight-aware estimators validate that
sample_weighthas the same length asX. MiniBatchKMeans.partial_fitrequires a priorfitcall and consistent feature dimensions.- Validation metrics ignore noise labels (
-1) and require at least two non-noise clusters; they raiseValueErrorwhen the input data or label configuration is invalid.
Testing and quality
- Rust tests:
cargo test - Python tests:
pytest - Linting and formatting:
pre-commit run --all-files
Citation
If you use clustor in your work and wish to refer to it, please use the following BibTeX entry.
@software{clustor,
author = {Soumyadip Sarkar},
title = {Clustor: Rust-accelerated High-Performance Clustering Algorithms},
year = {2026},
url = {https://github.com/alphavelocity/clustor}
}
License
This project is licensed under the Apache License - see the LICENSE file for details.
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 Distribution
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 clustor-0.1.0.tar.gz.
File metadata
- Download URL: clustor-0.1.0.tar.gz
- Upload date:
- Size: 143.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af37dd8996e25973fffa6ef4e8956cf0fdc13c2a5598bf5e41ceb4390643d1af
|
|
| MD5 |
4f3a92297636236e5fb6827d7082360d
|
|
| BLAKE2b-256 |
006f0d0ec2f1600f5fc18b5ac76ebaf4a61315140001bcbf0f38e340560e408d
|
File details
Details for the file clustor-0.1.0-cp312-cp312-win_amd64.whl.
File metadata
- Download URL: clustor-0.1.0-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 352.6 kB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c70b946e85940fba6efbbbc2f3cfef3eb1ac966d28c447b569f4aa1c5b43033d
|
|
| MD5 |
c875b14a037fd0b8fd456d65b2be2833
|
|
| BLAKE2b-256 |
771b168997222b9c11264c224e6f4c5d3f94f8b447238c95df5347640ec3d308
|