hnsw.c
hnsw.c - HNSW Vector Search
A minimalist C library and CLI for fixed-dimension vector indexing with Approximate Nearest Neighbor search using a Hierarchical Navigable Small World (HNSW) graph.
CLI
Run a nearest neighbor search over a vector dataset.
Dataset format
Each line in the input file must contain:
<id> <v1> <v2> ... <vN>
Example (3D vectors):
item_1 1.0 0.0 0.0
item_2 0.0 1.0 0.0
item_3 0.0 0.0 1.0
Examples
Basic search:
./bin/x86_64/linux/hnsw --dim 3 --input vectors.txt --query "1 0 0"
Using a different metric and limiting results:
./bin/x86_64/linux/hnsw --dim 3 --input vectors.txt --query "1 0 0" --metric cosine --top 5
Applying a threshold:
./bin/x86_64/linux/hnsw --dim 3 --input vectors.txt --query "1 0 0" --threshold 0.8
Pipe query vector through standard input:
echo "1 0 0" | ./bin/x86_64/linux/hnsw --dim 3 --input vectors.txt
Parameters
| Flag | Description |
|---|---|
--dim, -d | Vector dimension |
--input, -i | Input dataset file |
--query, -q | Query vector |
--metric, -m | Metric (l2, cosine, ip) |
--top, -k | Number of results |
--threshold, -t | Threshold filter |
--help, -h | Show help |
--version, -v | Show version |
Output
Results are printed as:
<id>: <score>
Metrics
Available metrics:
l2: squared Euclidean distancecosine: cosine distanceip: inner product similarity
l2 uses squared Euclidean distance:
d(a, b) = sum((a[i] - b[i])^2)
Note: no square root is applied. Rankings are identical to Euclidean distance.
Public API
#include "hnsw.h"
kc_hnsw_t *hnsw = kc_hnsw_open(dimension, KC_HNSW_METRIC_COSINE);
kc_hnsw_add(hnsw, "id_1", values);
kc_hnsw_build(hnsw);
kc_hnsw_search(hnsw, query, limit, threshold, results);
kc_hnsw_close(hnsw);
Lifecycle
kc_hnsw_open()allocates a new index.kc_hnsw_add()inserts vectors.kc_hnsw_build()constructs the HNSW graph.kc_hnsw_search()queries the index.kc_hnsw_close()releases all resources.
Build
Compiled artifacts are generated under bin/{arch}/{platform}/ for the host architecture running the build.
make clean && make
Multiarch Builds
The project is prepared to build artifacts for multiple architectures under bin/{arch}/{platform}/. A plain make builds only the current host architecture, while the targets below build the full matrix or a specific target.
make all
make x86_64/linux
make x86_64/windows
make i686/linux
make i686/windows
make aarch64/linux
make aarch64/android
make armv7/linux
make armv7/android
make armv7hf/linux
make riscv64/linux
make powerpc64le/linux
make mips/linux
make mipsel/linux
make mips64el/linux
make s390x/linux
make loongarch64/linux
License
This project is distributed under the GNU General Public License version 3 (GPLv3).
Repo
GitHub: kaisarcode/hnsw.c
