import type { Id } from '../../resources/ResourceInterface.ts';
/**
 * Represents a Hierarchical Navigable Small World (HNSW) index for approximate nearest neighbor search.
 * This implementation is based on hierarchical graph navigation to efficiently index and search high-dimensional vectors.
 * A HNSW is basically a multi-dimensional skip list. Each node has (potentially) higher levels that are used for quickly
 * traversing the graph get in the neighborhood of the node, and then lower levels are used to more accurately find the
 * closest neighbors.
 *
 * This implementation is based on the paper "Efficient and Robust Approximate Nearest Neighbor Search in High Dimensions"
 * (mostly influenced AI's contributions)
 */
export declare class HierarchicalNavigableSmallWorld {
    static useObjectStore: boolean;
    indexStore: any;
    M: number;
    efConstruction: number;
    efConstructionSearch: number;
    mL: number;
    optimizeRouting: number;
    nodesVisitedCount: number;
    idIncrementer: BigInt64Array | undefined;
    distance: (a: number[], b: number[]) => number;
    constructor(indexStore: any, options: any);
    index(primaryKey: Id, vector: number[], existingVector?: number[]): void;
    private getEntryPoint;
    /**
     * Search one layer of the skip-list using HNSW algorithm for creating a candidate list and navigating the graph
     * TODO: This should be async, but we can't really do that with lmdb-js's transaction system right now. Should be
     * doable with RocksDB. We could also create an async version for searching.
     * @param queryVector
     * @param entryPointId
     * @param entryPoint
     * @param ef
     * @param level
     * @param distanceFunction
     * @private
     */
    private searchLayer;
    /**
     * This the main entry from Harper's query functionality, where we actually search for an ordered list of nearest
     * neighbors, using the provided sort/order definition object and performing the multi-layer skip-list search.
     * This returns an iterable of the nearest neighbors to the provided target vector, with nearest ordered first.
     * @param target
     * @param value
     * @param descending
     * @param distance
     * @param comparator
     * @param context
     */
    search({ target, value, descending, distance, comparator, }: {
        target: number[];
        value: number;
        descending: boolean;
        distance: string;
        comparator: string;
    }): {
        key: string;
        distance: number;
    }[];
    private checkSymmetry;
    private addConnection;
    validateConnectivity(startLevel?: number): {
        isFullyConnected: boolean;
        averageConnections: number;
    };
    get totalNodes(): number;
    /**
     * This is used by the query planner to determine what order to apply conditions. It is our best guess at an estimated count.
     * This unit is typically the number of records that need to be accessed to satisfy the query. We know that we will visit
     * a minimum of efConstructionSearch nodes and a maximum of the total nodes (in absolute worst case).
     * The original paper described the complexity as polylogarithmic. From my testing, the
     * best and simplest guess at the number of nodes that need to be accessed is the geometric mean of the total number of nodes
     * and the efConstruction parameter (for search), which clearly constrains the estimate to the correct range and is
     * similar to polylogarithmic for realistic values.
     *
     * @returns
     */
    estimateCountAsSort(): number;
    /**
     * This is used to resolve the vector property, which should be resolved to the distance when used in a sort comparator
     * We also want to cache distance calculations so they can be accessed efficently later
     * @param vector
     * @param context
     * @param entry
     */
    propertyResolver(vector: number[], context: any, entry: any): any;
}
