forked from facebookresearch/faiss
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathIndexHNSW.h
200 lines (159 loc) · 5.53 KB
/
IndexHNSW.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
// -*- c++ -*-
#pragma once
#include <vector>
#include <faiss/IndexFlat.h>
#include <faiss/IndexPQ.h>
#include <faiss/IndexScalarQuantizer.h>
#include <faiss/impl/HNSW.h>
#include <faiss/utils/utils.h>
namespace faiss {
struct IndexHNSW;
/** The HNSW index is a normal random-access index with a HNSW
* link structure built on top */
struct IndexHNSW : Index {
typedef HNSW::storage_idx_t storage_idx_t;
// the link structure
HNSW hnsw;
// the sequential storage
bool own_fields = false;
Index* storage = nullptr;
// When set to false, level 0 in the knn graph is not initialized.
// This option is used by GpuIndexCagra::copyTo(IndexHNSWCagra*)
// as level 0 knn graph is copied over from the index built by
// GpuIndexCagra.
bool init_level0 = true;
// When set to true, all neighbors in level 0 are filled up
// to the maximum size allowed (2 * M). This option is used by
// IndexHHNSWCagra to create a full base layer graph that is
// used when GpuIndexCagra::copyFrom(IndexHNSWCagra*) is invoked.
bool keep_max_size_level0 = false;
explicit IndexHNSW(int d = 0, int M = 32, MetricType metric = METRIC_L2);
explicit IndexHNSW(Index* storage, int M = 32);
~IndexHNSW() override;
void add(idx_t n, const float* x) override;
/// Trains the storage if needed
void train(idx_t n, const float* x) override;
/// entry point for search
void search(
idx_t n,
const float* x,
idx_t k,
float* distances,
idx_t* labels,
const SearchParameters* params = nullptr) const override;
void range_search(
idx_t n,
const float* x,
float radius,
RangeSearchResult* result,
const SearchParameters* params = nullptr) const override;
void reconstruct(idx_t key, float* recons) const override;
void reset() override;
void shrink_level_0_neighbors(int size);
/** Perform search only on level 0, given the starting points for
* each vertex.
*
* @param search_type 1:perform one search per nprobe, 2: enqueue
* all entry points
*/
void search_level_0(
idx_t n,
const float* x,
idx_t k,
const storage_idx_t* nearest,
const float* nearest_d,
float* distances,
idx_t* labels,
int nprobe = 1,
int search_type = 1,
const SearchParameters* params = nullptr) const;
/// alternative graph building
void init_level_0_from_knngraph(int k, const float* D, const idx_t* I);
/// alternative graph building
void init_level_0_from_entry_points(
int npt,
const storage_idx_t* points,
const storage_idx_t* nearests);
// reorder links from nearest to farthest
void reorder_links();
void link_singletons();
void permute_entries(const idx_t* perm);
DistanceComputer* get_distance_computer() const override;
};
/** Flat index topped with with a HNSW structure to access elements
* more efficiently.
*/
struct IndexHNSWFlat : IndexHNSW {
IndexHNSWFlat();
IndexHNSWFlat(int d, int M, MetricType metric = METRIC_L2);
};
/** PQ index topped with with a HNSW structure to access elements
* more efficiently.
*/
struct IndexHNSWPQ : IndexHNSW {
IndexHNSWPQ();
IndexHNSWPQ(
int d,
int pq_m,
int M,
int pq_nbits = 8,
MetricType metric = METRIC_L2);
void train(idx_t n, const float* x) override;
};
/** SQ index topped with with a HNSW structure to access elements
* more efficiently.
*/
struct IndexHNSWSQ : IndexHNSW {
IndexHNSWSQ();
IndexHNSWSQ(
int d,
ScalarQuantizer::QuantizerType qtype,
int M,
MetricType metric = METRIC_L2);
};
/** 2-level code structure with fast random access
*/
struct IndexHNSW2Level : IndexHNSW {
IndexHNSW2Level();
IndexHNSW2Level(Index* quantizer, size_t nlist, int m_pq, int M);
void flip_to_ivf();
/// entry point for search
void search(
idx_t n,
const float* x,
idx_t k,
float* distances,
idx_t* labels,
const SearchParameters* params = nullptr) const override;
};
struct IndexHNSWCagra : IndexHNSW {
IndexHNSWCagra();
IndexHNSWCagra(int d, int M, MetricType metric = METRIC_L2);
/// When set to true, the index is immutable.
/// This option is used to copy the knn graph from GpuIndexCagra
/// to the base level of IndexHNSWCagra without adding upper levels.
/// Doing so enables to search the HNSW index, but removes the
/// ability to add vectors.
bool base_level_only = false;
/// When `base_level_only` is set to `True`, the search function
/// searches only the base level knn graph of the HNSW index.
/// This parameter selects the entry point by randomly selecting
/// some points and using the best one.
int num_base_level_search_entrypoints = 32;
void add(idx_t n, const float* x) override;
/// entry point for search
void search(
idx_t n,
const float* x,
idx_t k,
float* distances,
idx_t* labels,
const SearchParameters* params = nullptr) const override;
};
} // namespace faiss