- HNSW graph — hierarchical navigable small-world graph per Malkov & Yashunin (2016), built incrementally at insert time
- Standard knobs —
m,ef_construction,ef_search,filter_widen, and a fixedseedfor reproducibility - Insert / search / delete — beam-search top-
k; tombstone deletion (graph-repair compaction is a tracked post-freeze optimisation) - Deterministic — a seeded SplitMix64 (no
randdep); same insert order + seed ⇒ byte-identical graph and identical results - Filtered traversal — metadata filtering via
iqdb-filter, with the beam widened byfilter_widento mitigate post-filter under-return - One ordering invariant — all metric math via
iqdb-distance;DotProductnegated soHit.distanceis smaller-is-nearer across all five metrics
Installation
[]
= "1.0"
Quick start
use Arc;
use ;
use ;
use ;
// Default operating point (m=16, ef_construction=200, ef_search=64), or tune it:
let cfg = default.with_ef_search;
let mut idx = new?;
idx.insert?;
idx.insert?;
idx.insert?;
let hits = idx.search?;
assert_eq!; // nearest to the origin
Filtered search
Attach an iqdb-filter predicate to the query. Only records whose metadata
satisfies it are returned — evaluated during traversal, with the beam widened by
filter_widen so a selective filter still fills k:
use Arc;
use ;
use ;
use ;
let mut idx = new?;
let red: Metadata =
.into_iter.collect;
let blue: Metadata =
.into_iter.collect;
idx.insert?;
idx.insert?;
let params = SearchParams ;
let hits = idx.search?;
assert!; // id 2 is nearer, but blue
Tuning
The defaults (m = 16, ef_construction = 200, ef_search = 64) are the
SIFT-calibrated operating point. Override any field with the with_* builders;
larger m / ef_construction raise recall and build cost, larger ef_search
raises recall and per-query cost:
use HnswConfig;
let cfg = default
.with_m // denser graph: higher recall, more memory
.with_ef_construction // more thorough build
.with_ef_search; // wider query beam: higher recall, slower search
Status
v1.0.0 is stable: the multi-layer graph, insert with the Alg 4 neighbour heuristic, beam search, tombstone delete, and iqdb-filter traversal all ship, wired to the stable (1.0) iQDB spine. Correctness is pinned by a headline recall@10 ≥ 0.95 gate across all five metrics, measured against the exact iqdb-flat ground truth, plus determinism, contract, edge, layer-distribution, and tombstone suites. Zero unsafe (#![forbid(unsafe_code)]). The public API is frozen until 2.0 — only additive, non-breaking changes from here. A real-data SIFT/GIST recall diagnostic (tests/sift_recall.rs) and a criterion latency/recall bench ship alongside. See the API reference and the ROADMAP.
Where It Fits
iqdb-hnsw is the flagship Phase-3 index. It builds on:
iqdb-types— core typesiqdb-distance— distance kernelsiqdb-index— implements the traitiqdb-filter— filter during graph traversal
and is consumed by iqdb for approximate search and by iqdb-build for bulk graph construction. Persistence is the separate iqdb-persist crate's job.
Standards
Built to the iQDB Rust standard. See REPS.md (Rust Efficiency & Performance Standards) and dev/DIRECTIVES.md for the engineering law and the definition of done. Before a PR: cargo fmt --all, cargo clippy --all-targets --all-features -- -D warnings, and cargo test --all-features must be clean.