Source code for knncolle.hnsw

from .classes import Parameters, GenericIndex
from typing import Literal, Optional, Tuple

from . import lib_knncolle as lib
from .classes import Parameters, GenericIndex, Builder
from .define_builder import define_builder


[docs] class HnswParameters(Parameters): """Parameters for the hierarchical navigable small worlds (HNSW) algorithm, see `here <https://github.com/nmslib/hnswlib>`_ for details. """
[docs] def __init__( self, num_links: int = 16, ef_construction: int = 200, ef_search: int = 10, distance: Literal["Euclidean", "Manhattan", "Cosine"] = "Euclidean", ): """ Args: num_links: Number of bi-directional links to create per observation during index construction. Larger values improve accuracy at the expense of speed and memory usage. ef_construction: Size of the dynamic list for index generation. Larger values improve the quality of the index at the expense of time. ef_search Size of the dynamic list for neighbor searching. Larger values improve accuracy at the expense of a slower search. distance: Distance metric for index construction and search. """ self.num_links = num_links self.ef_construction = ef_construction self.ef_search = ef_search self.distance = distance
@property def distance(self) -> str: """Distance metric, see :meth:`~__init__()`.""" return self._distance @distance.setter def distance(self, distance: str): """ Args: distance: Distance metric, see :meth:`~__init__()`. """ if distance not in ["Euclidean", "Manhattan", "Cosine"]: raise ValueError("unsupported 'distance'") self._distance = distance @property def num_links(self) -> int: """Number of links, see :meth:`~__init__()`.""" return self._num_links @num_links.setter def num_links(self, num_links: int): """ Args: num_links: Number of links, see :meth:`~__init__()`. """ if num_links < 1: raise ValueError("'num_links' should be a positive integer") self._num_links = num_links @property def ef_construction(self) -> int: """Size of the dynamic list during index construction, see :meth:`~__init__()`.""" return self._ef_construction @ef_construction.setter def ef_construction(self, ef_construction: int): """ Args: ef_construction: Size of the dynamic list during index construction, see :meth:`~__init__()`. """ if ef_construction < 1: raise ValueError("'ef_construction' should be a positive integer") self._ef_construction = ef_construction @property def ef_search(self) -> int: """Size of the dynamic list during search, see :meth:`~__init__()`.""" return self._ef_search @ef_search.setter def ef_search(self, ef_search: int): """ Args: ef_search: Size of the dynamic list during search, see :meth:`~__init__()`. """ if ef_search < 1: raise ValueError("'ef_search' should be a positive integer") self._ef_search = ef_search
[docs] class HnswIndex(GenericIndex): """A prebuilt index for the hierarchical navigable small worlds (HNSW) algorithm, created by :py:func:`~knncolle.define_builder.define_builder` with a :py:class:`~knncolle.hnsw.HnswParameters` object. """
[docs] def __init__(self, ptr): """ Args: ptr: Address of a ``knncolle_py::WrappedPrebuilt`` containing a HNSW search index, allocated in C++. """ super().__init__(ptr)
@define_builder.register def _define_builder_hnsw(x: HnswParameters) -> Tuple: return (Builder(lib.create_hnsw_builder(x.num_links, x.ef_construction, x.ef_search, x.distance)), HnswIndex)