Skip to content

Commit df1e236

Browse files
committed
Release v0.2.6
1 parent efaeae9 commit df1e236

3 files changed

Lines changed: 69 additions & 14 deletions

File tree

RELEASE_NOTES.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,42 @@
11
# Release Notes
22

3+
## deglib v0.2.6
4+
5+
### Overview
6+
deglib v0.2.6 adds a second search strategy alongside the existing relative-epsilon search: **`ef` fixed-pool search**, now selectable through a single `eps_or_ef` query parameter. The new `ef` mode supports candidate filtering and a distance-computation budget. `Searcher::optimize()` gained K-Means entry-point selection and prefetch auto-tuning, and a set of graph-layout and SIMD improvements makes both build and search faster.
7+
8+
---
9+
10+
### 🚀 Key Features & Improvements
11+
12+
#### `ef` Fixed-Pool Search (new)
13+
* **Second exploration strategy:** In addition to the existing relative-epsilon (`eps`) search, queries can now run a fixed candidate-pool (`ef`) best-first search.
14+
* **Single `eps_or_ef` parameter:** One argument selects the mode — values $\ge 1.0$ are treated as a fixed pool size (`ef`), values $< 1.0$ run the relative-epsilon search. Applies to the C++ `Searcher` and the Python bindings.
15+
* **Candidate filtering:** `ef` search accepts a filter predicate; filtered candidates guide exploration but never occupy the result set, so the search radius is not prematurely collapsed.
16+
* **Distance-computation budget:** `ef` search can cap the number of distance evaluations per query (`max_distance_computation_count`) for predictable worst-case latency.
17+
18+
#### Searcher Tuning (`Searcher::optimize()`)
19+
* **K-Means entry points:** Clusters graph features to pick better search entry points, improving recall at a given effort.
20+
* **Prefetch auto-tuning:** Automatically tunes memory-prefetch parameters for the target machine.
21+
22+
#### Performance
23+
* **Faster distance kernels:** Vectorized SIMD tail handling across the FP32/FP16/Int8/UInt8 distance headers, plus feature and neighbor prefetching during graph traversal.
24+
* **Cache-friendly graph layout:** `ReadOnlyGraph` now stores features in a contiguous, aligned layout.
25+
26+
---
27+
28+
### ⚠️ Breaking Changes & Migration Guide
29+
30+
* **`Searcher` search parameter:** `search()` / `search_batch()` (C++ and Python) now take `eps_or_ef` in place of `eps`. Existing relative-epsilon callers keep the same behavior by passing a value $< 1.0$.
31+
* **Graph creation & loading API:** `create_empty`, `create_dynamic_empty`, and `create_random_graph` moved to the `deglib` namespace, and `create_builder` / `load_readonly_graph` / `load_dynamic_graph` / `load_mutable_graph` are exposed from `deglib.h`. Update call sites to the new locations.
32+
* **EVP quantization:** `EvpQuantizer` is now a stateful object shared by database and queries; the `quantize_evp_*` free functions were removed. Use the quantizer instance directly.
33+
34+
---
35+
36+
### 🛠️ Bug Fixes
37+
38+
* **Dynamic graph deletions:** Removing vertices from `SizeBoundedGraph` now keeps internal indices contiguous (swap-with-last compaction), fixing sliding-window graph extensions and `ReadOnlyGraph` serialization after deletions.
39+
340
## deglib v0.2.5
441

542
### Overview

python/setup.py

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,40 @@ def get_version(rel_path):
3939
raise RuntimeError("Unable to find version string.")
4040

4141

42+
def copy_cpp_sources(src: str = os.path.join("..", "cpp"), dst: str = "lib") -> None:
43+
"""Copies the sibling ../cpp C++ sources into lib/ so standalone/containerized builds find them."""
44+
ignore_dirs = shutil.ignore_patterns("external", "cmake-build*", "build", "benchmark", ".venv", ".git*")
45+
if os.path.exists(src):
46+
if os.path.exists(dst):
47+
shutil.rmtree(dst, ignore_errors=True)
48+
print(f"[setup.py] Copying {src} -> {dst}")
49+
shutil.copytree(src, dst, dirs_exist_ok=True, ignore=ignore_dirs)
50+
print("[setup.py] Files copied successfully.")
51+
elif not os.path.exists(dst) or not any(Path(dst).iterdir()):
52+
raise FileNotFoundError(f"Source directory '{src}' does not exist and '{dst}' is not populated.")
53+
54+
55+
class CopyBuildFiles(Command):
56+
"""Populates lib/ from ../cpp before cibuildwheel ships only python/ into build containers."""
57+
58+
description = "Copy the C++ sources from ../cpp into lib/"
59+
user_options = []
60+
61+
def initialize_options(self):
62+
pass
63+
64+
def finalize_options(self):
65+
pass
66+
67+
def run(self):
68+
copy_cpp_sources()
69+
70+
4271
class CopySDist(sdist_class):
4372
"""Packages the C++ sources into lib/ when creating a standalone source distribution (PyPI sdist)."""
4473

4574
def run(self):
46-
ignore_dirs = shutil.ignore_patterns("external", "cmake-build*", "build", "benchmark", ".venv", ".git*")
47-
src = os.path.join("..", "cpp")
48-
dst = "lib"
49-
50-
if os.path.exists(src):
51-
if os.path.exists(dst):
52-
shutil.rmtree(dst, ignore_errors=True)
53-
print(f"[setup.py] Packaging: Copying {src} -> {dst}")
54-
shutil.copytree(src, dst, dirs_exist_ok=True, ignore=ignore_dirs)
55-
print("[setup.py] Files copied successfully.")
56-
elif not os.path.exists(dst) or not any(Path(dst).iterdir()):
57-
raise FileNotFoundError(f"Source directory '{src}' does not exist and '{dst}' is not populated.")
58-
75+
copy_cpp_sources()
5976
super().run()
6077

6178

@@ -195,6 +212,7 @@ def build_extension(self, ext: CMakeExtension) -> None:
195212
version=get_version(os.path.join("src", "deglib", "__init__.py")),
196213
ext_modules=[CMakeExtension("deglib_cpp")],
197214
cmdclass={
215+
"copy_build_files": CopyBuildFiles,
198216
"sdist": CopySDist,
199217
"build_ext": CMakeBuild,
200218
},

python/src/deglib/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
)
2020
from .distances import FloatSpace, Metric
2121

22-
__version__ = "0.2.5"
22+
__version__ = "0.2.6"
2323

2424
__all__ = [
2525
"DynamicExplorationGraph",

0 commit comments

Comments
 (0)