This release is a pre-release and may not be stable for production use.
intelliant
Clustering by ant colony optimization on a k-nearest-neighbour graph.
intelliant-coreis an earlier incarnation of this project, not a component of it. It is superseded and should not be installed; the repository its metadata points at no longer exists. Installintelliant.
Overview
Most clustering algorithms draw boundaries in feature space. This one does not. It turns the data into a k-nearest-neighbour similarity graph, releases a colony of ants onto it, and reads the clusters out of the pheromone trails they leave behind: dense regions accumulate pheromone, sparse ones do not.
Because everything after the first step happens on the graph, the algorithm does not care how many dimensions the input had. Two features and 768 look the same to the ants.
Alpha. The public API still changes between versions, and the parameter ranges are being calibrated. This is research software, not a production-ready package.
Features
- Works on a graph, not on coordinates. Any symmetric metric, any dimensionality.
- Three separate stages. Graph, pheromone field, clusters - each is its own object, and the state between them is inspectable and editable. You can threshold the same pheromone field a dozen ways without recomputing it.
- Sparse and compiled. scipy CSR throughout, ant steps in Numba.
- Two-stage noise absorption. Pheromone waves first, centroid fallback second, so isolated points are not simply discarded.
- Typed. Ships
py.typed; pyright-clean.
Installation
pip install intelliant
Python 3.14 or newer. With uv:
uv add intelliant
Usage
import numpy as np
from sklearn.datasets import make_blobs
from sklearn.metrics import adjusted_rand_score
from intelliant import CoreClusterer, GraphBuilder, PheromoneExtractor, find_threshold
X, y = make_blobs(n_samples=1000, centers=7, cluster_std=0.6, random_state=42)
# 1. embeddings -> KNN similarity graph
graph = GraphBuilder(n_neighbors=15, metric="cosine", mutual=True).build(X)
# 2. graph -> pheromone field
aco = PheromoneExtractor(
n_ants=len(X), n_iterations=20, path_length=10,
beta=2.0, alpha=1.0,
evaporation_rate=0.07, evaporation_schedule="step",
pheromone_deposit=1.0, initial_pheromone=1.0,
tau_min=0.01, tau_max=10.0,
random_state=42,
)
aco.fit(graph)
# 3. pheromone field -> clusters
cutoff = find_threshold(aco.pheromone_matrix_.data, method="otsu")
labels = CoreClusterer(
min_cluster_size=15, max_iterations=20,
gap_ratio=3.0, max_gap_rank=3, batch_size=1000,
).fit_predict(aco.pheromone_matrix_, threshold_value=cutoff.value, X=X)
print(adjusted_rand_score(y, labels)) # 0.807 on the author's machine
Every stage is seeded, so the run is reproducible - but the exact figure moves with numba, BLAS and scipy versions. Treat it as "around 0.8", not as a value to assert against.
The stages are deliberately not fused into a single fit. Everything between
them - graph_, pheromone_matrix_, cores_, labels_pheromone_ - is
public, and re-running only the last stage with a different threshold is
cheap.
Configuration
Parameters that shape the result have no defaults. Passing them is not optional, and every constructor is keyword-only.
That is unusual, and deliberate: calibration is still in progress, so a default would be a value nobody has justified, applied silently. One of the former defaults sat exactly on the evaporation rate that measurement showed to fragment clusters. Explicit parameters make a run reproducible from its call site.
Parameters that do not shape the result - verbose, random_state,
warmup, knn_method, the use_* heuristic switches - keep their defaults.
Where to start
The absence of defaults is not a reason to guess. These are the values from the example above - a starting point that produces sensible clusters on well-separated data, not a recommendation that holds across datasets. Establishing which values do hold is exactly what calibration is for.
| Stage | Starting values |
|---|---|
GraphBuilder |
n_neighbors=15, metric="cosine", mutual=True |
PheromoneExtractor |
n_iterations=20, path_length=10, beta=2.0, alpha=1.0, evaporation_rate=0.07, evaporation_schedule="step", pheromone_deposit=1.0, initial_pheromone=1.0, tau_min=0.01, tau_max=10.0 |
CoreClusterer |
max_iterations=20, gap_ratio=3.0, max_gap_rank=3 |
Set random_state and change one parameter at a time. n_ants scales with
the data - the example uses len(X).
Two that are easy to get wrong:
n_neighborsbounds everything downstream. No threshold can separate two clusters that the KNN graph already merged into one component. When results disappoint, look at the graph before touching ACO parameters.evaporation_schedulechanges whatevaporation_ratemeans. Under"step"the field decays once per ant step, so the effective per-iteration decay is1 - (1 - rate) ** path_length- atrate=0.07andpath_length=10that is 0.516, not 0.07. No value from the ACO literature transfers to this schedule."iteration"is the classical behaviour. Which is better here is being measured.
Project status
Under active development as research work by a single maintainer. The library itself is complete and tested; what remains is calibration - establishing which parameter values hold across datasets, and on which the algorithm breaks. Until that settles, expect the API to move between versions.
The previous version was published as
intelliant-core with a
single-class API. It is superseded and should not be installed.
Citation
If the library is used in research, cite it through the "Cite this repository" button on GitHub, or from CITATION.cff directly. The algorithm builds on Ant System (Dorigo, Maniezzo and Colorni, 1996) and the MAX-MIN variant (Stutzle and Hoos, 2000); both are listed there with DOIs.
Contributing
Issues and questions are welcome. Pull requests target dev; the setup, the
verify chain and the commit rules are in CONTRIBUTING.md.
Security policy: SECURITY.md.
License
MIT - see LICENSE.
Release files for intelliant 0.2.0a1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| intelliant-0.2.0a1.tar.gz | 29.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| intelliant-0.2.0a1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 61.2 kB
Release files / intelliant-0.2.0a1.tar.gz
| Download URL | intelliant-0.2.0a1.tar.gz |
|---|---|
| Size | 29.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
60ca4345602f38b3bf84807a035a11e441707284c1dacba133d057b7c97ccc61
|
|
BLAKE2b-256 checksum How to use checksums |
14713746e1f85232348a4753e9378ff299f09d892f287c7a78ce30097a0fe148
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
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 Jul 27, 2026.
Transparency logRelease files / intelliant-0.2.0a1-py3-none-any.whl
| Download URL | intelliant-0.2.0a1-py3-none-any.whl |
|---|---|
| Size | 31.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a34363bc26c710efb56a22cfe852666ddd8e1bbae30b2d8eb5fac0749ea2d2d7
|
|
BLAKE2b-256 checksum How to use checksums |
1bab3ed5b12981f26341e9c5b8c8cf60b14660ded8ef4bdeb98b5307873a7aae
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
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 Jul 27, 2026.
Transparency log