BETULA
Fast, streamable data clustering in Rust — an improved implementation of the BIRCH algorithm with better cluster features.
What is BETULA?
BETULA introduces improved Clustering Feature (CF) trees that avoid the catastrophic cancellation present in the original BIRCH algorithm. The key contribution is a replacement cluster feature that:
- Is numerically stable (no catastrophic cancellation)
- Is not much more expensive to maintain
- Makes many computations simpler and more efficient
- Can be used in other BIRCH-derived algorithms (streaming, k-means, GMM, hierarchical clustering)
This crate is a Rust implementation based on ELKI's BETULA for the Java reference.
Reference: Lang & Schubert, "BETULA: Fast clustering of large data with improved BIRCH CF-Trees", Information Systems 108 (2022), DOI: 10.1016/J.IS.2021.101918
Installation
Add to your Cargo.toml:
[dependencies]
betula = "0.1"
Quick Start
use betula::cf_tree::CFTree;
use betula::cluster_feature::VII;
use betula::distance::CentroidEuclideanDistance;
// Create a CF-Tree with Euclidean distance
let mut tree = CFTree::new(
CentroidEuclideanDistance::new(), // distance function
CentroidEuclideanDistance::new(), // absorption function
32, // node capacity
2, // dimensionality
1000, // max leaf entries
0.0, // threshold (auto-estimated)
);
// Insert points
for point in &[
vec![1.0, 2.0],
vec![1.1, 2.1],
vec![10.0, 20.0],
vec![10.1, 20.1],
] {
tree.insert(point);
}
// Access cluster statistics
for (id, cf) in tree.leaf_entries().iter().enumerate() {
println!(
"Cluster {}: {} points, centroid={:?}, variance={:.4}",
id,
cf.size(),
cf.centroid(),
cf.ssd() / cf.size() as f64,
);
}
CF-Tree
The core data structure is a CFTree<F, CF, D, A> parameterized by:
| Parameter | Description |
|---|---|
F |
Float type (e.g. f64) |
CF |
Cluster feature type — VII, VVI, or VVV |
D |
Distance function for tree routing |
A |
Absorption function for leaf assignment |
Cluster Features
| Feature | Stores | Use case |
|---|---|---|
VII |
Scalar SSD + centroid | Simple clustering, most common |
VVI |
Per-dimension SSD + centroid | When per-dimension variance matters |
VVV |
Full cross-product matrix + centroid | When covariance is needed |
Parameters
- capacity: Node capacity — controls tree depth. Lower values give deeper trees; higher values give shallower trees. Recommended: 32–64.
- maxleaves: Maximum leaf entries — triggers tree rebuilds when exceeded.
- threshold: Leaf entry size limit — automatically estimated on rebuild. A good threshold avoids rebuilds; starting with
0is fine.
Note: The Python bindings (
betulars) provide default values for these parameters (capacity=32,maxleaves=1000,threshold=0.0). The Rust API requires all parameters explicitly.
Insertion API
insert(x)— validated insertion (checks dimensionality)insert_unchecked(x)— unsafe fast path (caller guaranteesx.len() >= dim)
Distance Measures
Six distance functions are available, all implementing the CFDistance trait:
| Distance | Description |
|---|---|
CentroidEuclideanDistance |
Squared Euclidean distance between centroids |
CentroidManhattanDistance |
Manhattan distance between centroids |
AverageInterclusterDistance |
Average squared distance to cluster points (Zhang "D2") |
AverageIntraclusterDistance |
Average pairwise distance within clusters (Lang & Schubert "D3") |
VarianceIncreaseDistance |
SSD increase from adding/merging (Zhang "D4") |
RadiusDistance |
Average radius of the resulting cluster |
CLI Benchmark Tool
A benchmark binary is included for performance testing and comparison:
cargo build --release
./target/release/betula \
--input data.npy \
--output results.json \
--capacity 32 \
--maxleaves 1000 \
--distance euclidean
Output: JSON with metadata, timing, per-cluster statistics (centroid, size, variance).
Python Bindings
BETULA can be used from Python via the betulars package, built with pyo3 and maturin.
Installation
From source:
pip install maturin
maturin develop --features python
Or build a wheel:
maturin build --features python
pip install target/wheels/betulars-*.whl
Quick Start
import numpy as np
import betulars
# High-level: build a model from data
data = np.array([[1.0, 2.0], [1.1, 2.1], [10.0, 20.0], [10.1, 20.1]])
model = betulars.Betula(
data=data,
capacity=32,
maxleaves=1000,
threshold=0.0,
distance="euclidean",
absorption="euclidean",
feature="vii", # or "vvi" or "vvv"
)
print(f"Clusters: {model.num_clusters}")
print(f"Variance: {model.overall_variance:.4f}")
for cf in model.leaf_clusters:
print(f" Cluster: {cf.size} points, centroid={cf.centroid}, variance={cf.variance:.4f}")
Incremental Insertion
import numpy as np
import betulars
# Lower-level: insert points one at a time
tree = betulars.CFTree(dim=2, capacity=32, maxleaves=1000, threshold=0.0, feature="vii")
for point in np.array([[1.0, 2.0], [1.1, 2.1], [10.0, 20.0]]):
tree.insert(point)
print(f"Clusters: {tree.num_clusters}")
for cf in tree.leaf_clusters:
print(f" {cf.size} points, centroid={cf.centroid}")
Supported Distance Measures
| Name | Description |
|---|---|
euclidean |
Squared Euclidean distance between centroids |
manhattan |
Manhattan distance between centroids |
avgintercluster |
Average squared distance to cluster points |
avgintracluster |
Average pairwise distance within clusters |
varianceincrease |
SSD increase from adding/merging |
radius |
Average radius of the resulting cluster |
Cluster Feature Types
| Feature | Stores | Use case |
|---|---|---|
vii |
Scalar SSD + centroid | Simple clustering, most common |
vvi |
Per-dimension SSD + centroid | When per-dimension variance matters |
vvv |
Full cross-product matrix + centroid | When covariance is needed |
API Reference
Betula
High-level wrapper. Builds a CF-Tree from data in one call.
Betula(data, capacity=32, maxleaves=1000, threshold=0.0, distance="euclidean", absorption="euclidean", feature="vii")data— 2D numpy array, shape(n_points, n_dims), dtypefloat64
.leaf_clusters— list ofClusterFeatureobjects.num_clusters— number of leaf clusters.rebuild_count— number of tree rebuilds.overall_variance— total SSD / total points
CFTree
Incremental CF-Tree. Insert points one at a time.
CFTree(dim, capacity=32, maxleaves=1000, threshold=0.0, feature="vii").insert(point)— insert a data point (1D numpy array or sequence).leaf_clusters— list ofClusterFeatureobjects.num_clusters— number of leaf clusters.rebuild_count— number of tree rebuilds.dim— dimensionality
ClusterFeature
Read-only cluster statistics.
.size— number of points.centroid— numpy 1D array.ssd— sum of squared deviations.ssd_per_dim— numpy 1D array of per-dimension SSDs.covariance— numpy 2D array (or None for vii/vvi).variance— ssd / size
Python Version Support
Python 3.8 and later (via abi3 compatibility).
Roadmap
The following features are planned for future releases:
- K-means clustering — Refine CF-Tree leaf clusters with k-means for a fast k-means approximation.
- Gaussian Mixture Modelling — Fit GMMs to leaf clusters using the full covariance information from
VVVcluster features. - Parallel tree building — Multi-threaded tree construction for improved performance on large datasets.
- Hierarchical agglomerative clustering — Bottom-up merging of leaf clusters to produce a full hierarchy / dendrogram.
License
Dual licensed under MIT or Apache-2.0.
Metadata
Release files for betulars 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| betulars-0.1.0.tar.gz | 62.5 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| betulars-0.1.0-cp314-cp314t-win_amd64.whl | CPython 3.14 | CPython 3.14 free-threading | Windows x86-64 | Details |
| betulars-0.1.0-cp314-cp314t-manylinux_2_28_x86_64.whl | CPython 3.14 | CPython 3.14 free-threading | Linux glibc 2.28+ x86-64 | Details |
| betulars-0.1.0-cp314-cp314t-manylinux_2_28_aarch64.whl | CPython 3.14 | CPython 3.14 free-threading | Linux glibc 2.28+ ARM64 | Details |
| betulars-0.1.0-cp314-cp314t-macosx_11_0_arm64.whl | CPython 3.14 | CPython 3.14 free-threading | macOS 11.0+ ARM64 | Details |
| betulars-0.1.0-cp39-abi3-win_amd64.whl | CPython 3.9 | abi3 | Windows x86-64 | Details |
| betulars-0.1.0-cp39-abi3-manylinux_2_28_x86_64.whl | CPython 3.9 | abi3 | Linux glibc 2.28+ x86-64 | Details |
| betulars-0.1.0-cp39-abi3-manylinux_2_28_aarch64.whl | CPython 3.9 | abi3 | Linux glibc 2.28+ ARM64 | Details |
| betulars-0.1.0-cp39-abi3-macosx_11_0_arm64.whl | CPython 3.9 | abi3 | macOS 11.0+ ARM64 | Details |
Total release size: 14.5 MB
Release files / betulars-0.1.0.tar.gz
| Download URL | betulars-0.1.0.tar.gz |
|---|---|
| Size | 62.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e770e377479f4c6d5aafffffc7c6d60d6a58db7fbdb40883af92bb31d6abd64c
|
|
BLAKE2b-256 checksum How to use checksums |
1f0f2428577431ab1226ec86fa352ae2c7b55a3f4a443d4075f511ded9078f60
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 16, 2026.
Transparency logRelease files / betulars-0.1.0-cp314-cp314t-win_amd64.whl
| Download URL | betulars-0.1.0-cp314-cp314t-win_amd64.whl |
|---|---|
| Size | 2.5 MB |
| Tags | CPython 3.14 CPython 3.14 free-threading Windows x86-64 |
|
SHA-256 checksum How to use checksums |
1870396614f1ad044fb87d1fe1d69c90a92a959bbd08686b3fddb904f115cabe
|
|
BLAKE2b-256 checksum How to use checksums |
bdb48b88102888f9ec4876b46816a7dee62e5dfc1bbd8ea63cb563d464e5ebe3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 16, 2026.
Transparency logRelease files / betulars-0.1.0-cp314-cp314t-manylinux_2_28_x86_64.whl
| Download URL | betulars-0.1.0-cp314-cp314t-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 2.3 MB |
| Tags | CPython 3.14 CPython 3.14 free-threading Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
468b9573f76821ada9dfe0a57c869ceb82c196b4fd3e44b41ca439610b3507d8
|
|
BLAKE2b-256 checksum How to use checksums |
f6f0fb669c049411e1ce6248dcf8c45662ae80a8ffa94f1b18c0875552a8f43e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 16, 2026.
Transparency logRelease files / betulars-0.1.0-cp314-cp314t-manylinux_2_28_aarch64.whl
| Download URL | betulars-0.1.0-cp314-cp314t-manylinux_2_28_aarch64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.14 CPython 3.14 free-threading Linux glibc 2.28+ ARM64 |
|
SHA-256 checksum How to use checksums |
99bd1711a54a3d241cc7fa91035499af0fb68c8fadf7162e0d430835877b2d3e
|
|
BLAKE2b-256 checksum How to use checksums |
b7db29b8da0dfb8ec6c89752951aaa501d9b4caa8b884893818d880248da0359
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 16, 2026.
Transparency logRelease files / betulars-0.1.0-cp314-cp314t-macosx_11_0_arm64.whl
| Download URL | betulars-0.1.0-cp314-cp314t-macosx_11_0_arm64.whl |
|---|---|
| Size | 784.4 kB |
| Tags | CPython 3.14 CPython 3.14 free-threading macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
0313d105ac8eb900770444a0ea61a3f7edeb74efb192f9c03ddc4a710d10345e
|
|
BLAKE2b-256 checksum How to use checksums |
9b18d637b61acb20231e29b58cdc68dee76703b4548912c02ced8bb3772eeeef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 16, 2026.
Transparency logRelease files / betulars-0.1.0-cp39-abi3-win_amd64.whl
| Download URL | betulars-0.1.0-cp39-abi3-win_amd64.whl |
|---|---|
| Size | 2.5 MB |
| Tags | CPython 3.9 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
63ddda2c9273b95b5bc95f4f8d1aaad0f1aa0b8b6abf4c7e9ba61ff9dcb4cd91
|
|
BLAKE2b-256 checksum How to use checksums |
d7d72563ea8559e12e498218ddec6cb4ef6de6756cc00986ea70714b052ecce7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 16, 2026.
Transparency logRelease files / betulars-0.1.0-cp39-abi3-manylinux_2_28_x86_64.whl
| Download URL | betulars-0.1.0-cp39-abi3-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 2.3 MB |
| Tags | CPython 3.9 Linux glibc 2.28+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
08dc609fcdb1ecccefe80c373d082baf7500de08782f76f9e5440b12a94b34cd
|
|
BLAKE2b-256 checksum How to use checksums |
f756105eb3cd2070fa8929df6976657efd6f63281d1080e59d681d5e877e0555
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 16, 2026.
Transparency logRelease files / betulars-0.1.0-cp39-abi3-manylinux_2_28_aarch64.whl
| Download URL | betulars-0.1.0-cp39-abi3-manylinux_2_28_aarch64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.9 Linux glibc 2.28+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
89d147bacc78f2671a99478bb7dd94b0e93146953426f31fef55c9e7e541fa2e
|
|
BLAKE2b-256 checksum How to use checksums |
f912361af6b405ff0ae935b31eb372528af01683b7399e6ddbb589d49d7bd67d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 16, 2026.
Transparency logRelease files / betulars-0.1.0-cp39-abi3-macosx_11_0_arm64.whl
| Download URL | betulars-0.1.0-cp39-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 790.4 kB |
| Tags | CPython 3.9 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
56f0bab00b9d3c21e226b63692c7ea76de4114e12b00b76bba0ed9485990b92d
|
|
BLAKE2b-256 checksum How to use checksums |
891669809f6b6347767dc79e0c14df43d279746b0de47bba78ddf3922f6ab362
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 16, 2026.
Transparency log