faiss 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +23 -21
  5. data/ext/faiss/extconf.rb +11 -0
  6. data/ext/faiss/index.cpp +4 -4
  7. data/ext/faiss/index_binary.cpp +6 -6
  8. data/ext/faiss/product_quantizer.cpp +4 -4
  9. data/lib/faiss/version.rb +1 -1
  10. data/vendor/faiss/faiss/AutoTune.cpp +13 -0
  11. data/vendor/faiss/faiss/Clustering.cpp +32 -0
  12. data/vendor/faiss/faiss/Clustering.h +14 -0
  13. data/vendor/faiss/faiss/IVFlib.cpp +101 -2
  14. data/vendor/faiss/faiss/IVFlib.h +26 -2
  15. data/vendor/faiss/faiss/Index.cpp +36 -3
  16. data/vendor/faiss/faiss/Index.h +43 -6
  17. data/vendor/faiss/faiss/Index2Layer.cpp +24 -93
  18. data/vendor/faiss/faiss/Index2Layer.h +8 -17
  19. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +610 -0
  20. data/vendor/faiss/faiss/IndexAdditiveQuantizer.h +253 -0
  21. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +299 -0
  22. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.h +199 -0
  23. data/vendor/faiss/faiss/IndexBinary.cpp +20 -4
  24. data/vendor/faiss/faiss/IndexBinary.h +18 -3
  25. data/vendor/faiss/faiss/IndexBinaryFlat.cpp +9 -2
  26. data/vendor/faiss/faiss/IndexBinaryFlat.h +4 -2
  27. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +4 -1
  28. data/vendor/faiss/faiss/IndexBinaryFromFloat.h +2 -1
  29. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +5 -1
  30. data/vendor/faiss/faiss/IndexBinaryHNSW.h +2 -1
  31. data/vendor/faiss/faiss/IndexBinaryHash.cpp +17 -4
  32. data/vendor/faiss/faiss/IndexBinaryHash.h +8 -4
  33. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +28 -13
  34. data/vendor/faiss/faiss/IndexBinaryIVF.h +10 -7
  35. data/vendor/faiss/faiss/IndexFastScan.cpp +626 -0
  36. data/vendor/faiss/faiss/IndexFastScan.h +145 -0
  37. data/vendor/faiss/faiss/IndexFlat.cpp +52 -69
  38. data/vendor/faiss/faiss/IndexFlat.h +16 -19
  39. data/vendor/faiss/faiss/IndexFlatCodes.cpp +101 -0
  40. data/vendor/faiss/faiss/IndexFlatCodes.h +59 -0
  41. data/vendor/faiss/faiss/IndexHNSW.cpp +66 -138
  42. data/vendor/faiss/faiss/IndexHNSW.h +4 -2
  43. data/vendor/faiss/faiss/IndexIDMap.cpp +247 -0
  44. data/vendor/faiss/faiss/IndexIDMap.h +107 -0
  45. data/vendor/faiss/faiss/IndexIVF.cpp +200 -40
  46. data/vendor/faiss/faiss/IndexIVF.h +59 -22
  47. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +393 -0
  48. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +183 -0
  49. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +590 -0
  50. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +171 -0
  51. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +1290 -0
  52. data/vendor/faiss/faiss/IndexIVFFastScan.h +213 -0
  53. data/vendor/faiss/faiss/IndexIVFFlat.cpp +43 -26
  54. data/vendor/faiss/faiss/IndexIVFFlat.h +4 -2
  55. data/vendor/faiss/faiss/IndexIVFPQ.cpp +238 -53
  56. data/vendor/faiss/faiss/IndexIVFPQ.h +6 -2
  57. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +23 -852
  58. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +7 -112
  59. data/vendor/faiss/faiss/IndexIVFPQR.cpp +3 -3
  60. data/vendor/faiss/faiss/IndexIVFPQR.h +1 -1
  61. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +63 -40
  62. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +23 -7
  63. data/vendor/faiss/faiss/IndexLSH.cpp +8 -32
  64. data/vendor/faiss/faiss/IndexLSH.h +4 -16
  65. data/vendor/faiss/faiss/IndexLattice.cpp +7 -1
  66. data/vendor/faiss/faiss/IndexLattice.h +3 -1
  67. data/vendor/faiss/faiss/IndexNNDescent.cpp +4 -5
  68. data/vendor/faiss/faiss/IndexNNDescent.h +2 -1
  69. data/vendor/faiss/faiss/IndexNSG.cpp +37 -5
  70. data/vendor/faiss/faiss/IndexNSG.h +25 -1
  71. data/vendor/faiss/faiss/IndexPQ.cpp +108 -120
  72. data/vendor/faiss/faiss/IndexPQ.h +21 -22
  73. data/vendor/faiss/faiss/IndexPQFastScan.cpp +15 -450
  74. data/vendor/faiss/faiss/IndexPQFastScan.h +15 -78
  75. data/vendor/faiss/faiss/IndexPreTransform.cpp +47 -8
  76. data/vendor/faiss/faiss/IndexPreTransform.h +15 -3
  77. data/vendor/faiss/faiss/IndexRefine.cpp +36 -4
  78. data/vendor/faiss/faiss/IndexRefine.h +14 -2
  79. data/vendor/faiss/faiss/IndexReplicas.cpp +4 -2
  80. data/vendor/faiss/faiss/IndexReplicas.h +2 -1
  81. data/vendor/faiss/faiss/IndexRowwiseMinMax.cpp +438 -0
  82. data/vendor/faiss/faiss/IndexRowwiseMinMax.h +92 -0
  83. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +28 -43
  84. data/vendor/faiss/faiss/IndexScalarQuantizer.h +8 -23
  85. data/vendor/faiss/faiss/IndexShards.cpp +4 -1
  86. data/vendor/faiss/faiss/IndexShards.h +2 -1
  87. data/vendor/faiss/faiss/MetaIndexes.cpp +5 -178
  88. data/vendor/faiss/faiss/MetaIndexes.h +3 -81
  89. data/vendor/faiss/faiss/VectorTransform.cpp +45 -1
  90. data/vendor/faiss/faiss/VectorTransform.h +25 -4
  91. data/vendor/faiss/faiss/clone_index.cpp +26 -3
  92. data/vendor/faiss/faiss/clone_index.h +3 -0
  93. data/vendor/faiss/faiss/cppcontrib/SaDecodeKernels.h +300 -0
  94. data/vendor/faiss/faiss/cppcontrib/detail/CoarseBitType.h +24 -0
  95. data/vendor/faiss/faiss/cppcontrib/detail/UintReader.h +195 -0
  96. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-avx2-inl.h +2058 -0
  97. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +408 -0
  98. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-neon-inl.h +2147 -0
  99. data/vendor/faiss/faiss/cppcontrib/sa_decode/MinMax-inl.h +460 -0
  100. data/vendor/faiss/faiss/cppcontrib/sa_decode/MinMaxFP16-inl.h +465 -0
  101. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-avx2-inl.h +1618 -0
  102. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-inl.h +251 -0
  103. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-neon-inl.h +1452 -0
  104. data/vendor/faiss/faiss/gpu/GpuAutoTune.cpp +1 -0
  105. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +2 -6
  106. data/vendor/faiss/faiss/gpu/GpuIcmEncoder.h +60 -0
  107. data/vendor/faiss/faiss/gpu/GpuIndex.h +28 -4
  108. data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +2 -1
  109. data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +10 -8
  110. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +75 -14
  111. data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +19 -32
  112. data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +22 -31
  113. data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +22 -28
  114. data/vendor/faiss/faiss/gpu/GpuResources.cpp +14 -0
  115. data/vendor/faiss/faiss/gpu/GpuResources.h +16 -3
  116. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +3 -3
  117. data/vendor/faiss/faiss/gpu/impl/IndexUtils.h +32 -0
  118. data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +1 -0
  119. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +311 -75
  120. data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +10 -0
  121. data/vendor/faiss/faiss/gpu/test/TestUtils.h +3 -0
  122. data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +2 -2
  123. data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +5 -4
  124. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +331 -29
  125. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +110 -19
  126. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +0 -54
  127. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +0 -76
  128. data/vendor/faiss/faiss/impl/DistanceComputer.h +64 -0
  129. data/vendor/faiss/faiss/impl/HNSW.cpp +133 -32
  130. data/vendor/faiss/faiss/impl/HNSW.h +19 -16
  131. data/vendor/faiss/faiss/impl/IDSelector.cpp +125 -0
  132. data/vendor/faiss/faiss/impl/IDSelector.h +135 -0
  133. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +378 -217
  134. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.h +106 -29
  135. data/vendor/faiss/faiss/impl/LookupTableScaler.h +77 -0
  136. data/vendor/faiss/faiss/impl/NNDescent.cpp +1 -0
  137. data/vendor/faiss/faiss/impl/NSG.cpp +1 -4
  138. data/vendor/faiss/faiss/impl/NSG.h +1 -1
  139. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +383 -0
  140. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.h +154 -0
  141. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +225 -145
  142. data/vendor/faiss/faiss/impl/ProductQuantizer.h +29 -10
  143. data/vendor/faiss/faiss/impl/Quantizer.h +43 -0
  144. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +521 -55
  145. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +94 -16
  146. data/vendor/faiss/faiss/impl/ResultHandler.h +96 -0
  147. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +108 -191
  148. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +18 -18
  149. data/vendor/faiss/faiss/impl/index_read.cpp +338 -24
  150. data/vendor/faiss/faiss/impl/index_write.cpp +300 -18
  151. data/vendor/faiss/faiss/impl/io.cpp +1 -1
  152. data/vendor/faiss/faiss/impl/io_macros.h +20 -0
  153. data/vendor/faiss/faiss/impl/kmeans1d.cpp +303 -0
  154. data/vendor/faiss/faiss/impl/kmeans1d.h +48 -0
  155. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +56 -16
  156. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +25 -8
  157. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +66 -25
  158. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +75 -27
  159. data/vendor/faiss/faiss/index_factory.cpp +772 -412
  160. data/vendor/faiss/faiss/index_factory.h +3 -0
  161. data/vendor/faiss/faiss/index_io.h +5 -0
  162. data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -0
  163. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +4 -1
  164. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +2 -1
  165. data/vendor/faiss/faiss/python/python_callbacks.cpp +27 -0
  166. data/vendor/faiss/faiss/python/python_callbacks.h +15 -0
  167. data/vendor/faiss/faiss/utils/Heap.h +31 -15
  168. data/vendor/faiss/faiss/utils/distances.cpp +384 -58
  169. data/vendor/faiss/faiss/utils/distances.h +149 -18
  170. data/vendor/faiss/faiss/utils/distances_simd.cpp +776 -6
  171. data/vendor/faiss/faiss/utils/extra_distances.cpp +12 -7
  172. data/vendor/faiss/faiss/utils/extra_distances.h +3 -1
  173. data/vendor/faiss/faiss/utils/fp16-fp16c.h +21 -0
  174. data/vendor/faiss/faiss/utils/fp16-inl.h +101 -0
  175. data/vendor/faiss/faiss/utils/fp16.h +11 -0
  176. data/vendor/faiss/faiss/utils/hamming-inl.h +54 -0
  177. data/vendor/faiss/faiss/utils/hamming.cpp +0 -48
  178. data/vendor/faiss/faiss/utils/ordered_key_value.h +10 -0
  179. data/vendor/faiss/faiss/utils/quantize_lut.cpp +62 -0
  180. data/vendor/faiss/faiss/utils/quantize_lut.h +20 -0
  181. data/vendor/faiss/faiss/utils/random.cpp +53 -0
  182. data/vendor/faiss/faiss/utils/random.h +5 -0
  183. data/vendor/faiss/faiss/utils/simdlib_avx2.h +4 -0
  184. data/vendor/faiss/faiss/utils/simdlib_emulated.h +6 -1
  185. data/vendor/faiss/faiss/utils/simdlib_neon.h +7 -2
  186. data/vendor/faiss/faiss/utils/utils.h +1 -1
  187. metadata +46 -5
  188. data/vendor/faiss/faiss/IndexResidual.cpp +0 -291
  189. data/vendor/faiss/faiss/IndexResidual.h +0 -152
@@ -0,0 +1,393 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #include <faiss/IndexIVFAdditiveQuantizer.h>
9
+
10
+ #include <algorithm>
11
+ #include <cmath>
12
+ #include <cstring>
13
+
14
+ #include <faiss/impl/FaissAssert.h>
15
+ #include <faiss/impl/ResidualQuantizer.h>
16
+ #include <faiss/impl/ResultHandler.h>
17
+ #include <faiss/utils/distances.h>
18
+ #include <faiss/utils/extra_distances.h>
19
+ #include <faiss/utils/utils.h>
20
+
21
+ namespace faiss {
22
+
23
+ /**************************************************************************************
24
+ * IndexIVFAdditiveQuantizer
25
+ **************************************************************************************/
26
+
27
+ IndexIVFAdditiveQuantizer::IndexIVFAdditiveQuantizer(
28
+ AdditiveQuantizer* aq,
29
+ Index* quantizer,
30
+ size_t d,
31
+ size_t nlist,
32
+ MetricType metric)
33
+ : IndexIVF(quantizer, d, nlist, 0, metric), aq(aq) {
34
+ by_residual = true;
35
+ }
36
+
37
+ IndexIVFAdditiveQuantizer::IndexIVFAdditiveQuantizer(AdditiveQuantizer* aq)
38
+ : IndexIVF(), aq(aq) {}
39
+
40
+ void IndexIVFAdditiveQuantizer::train_residual(idx_t n, const float* x) {
41
+ const float* x_in = x;
42
+
43
+ size_t max_train_points = 1024 * ((size_t)1 << aq->nbits[0]);
44
+ // we need more data to train LSQ
45
+ if (dynamic_cast<LocalSearchQuantizer*>(aq)) {
46
+ max_train_points = 1024 * aq->M * ((size_t)1 << aq->nbits[0]);
47
+ }
48
+
49
+ x = fvecs_maybe_subsample(
50
+ d, (size_t*)&n, max_train_points, x, verbose, 1234);
51
+ ScopeDeleter<float> del_x(x_in == x ? nullptr : x);
52
+
53
+ if (by_residual) {
54
+ std::vector<Index::idx_t> idx(n);
55
+ quantizer->assign(n, x, idx.data());
56
+
57
+ std::vector<float> residuals(n * d);
58
+ quantizer->compute_residual_n(n, x, residuals.data(), idx.data());
59
+
60
+ aq->train(n, residuals.data());
61
+ } else {
62
+ aq->train(n, x);
63
+ }
64
+ }
65
+
66
+ void IndexIVFAdditiveQuantizer::encode_vectors(
67
+ idx_t n,
68
+ const float* x,
69
+ const idx_t* list_nos,
70
+ uint8_t* codes,
71
+ bool include_listnos) const {
72
+ FAISS_THROW_IF_NOT(is_trained);
73
+
74
+ // first encode then possibly add listnos
75
+
76
+ if (by_residual) {
77
+ // subtract centroids
78
+ std::vector<float> residuals(n * d);
79
+
80
+ #pragma omp parallel for if (n > 10000)
81
+ for (idx_t i = 0; i < n; i++) {
82
+ quantizer->compute_residual(
83
+ x + i * d,
84
+ residuals.data() + i * d,
85
+ list_nos[i] >= 0 ? list_nos[i] : 0);
86
+ }
87
+ aq->compute_codes(residuals.data(), codes, n);
88
+ } else {
89
+ aq->compute_codes(x, codes, n);
90
+ }
91
+
92
+ if (include_listnos) {
93
+ // write back from the end, where there is enough space
94
+ size_t coarse_size = coarse_code_size();
95
+ for (idx_t i = n - 1; i >= 0; i--) {
96
+ uint8_t* code = codes + i * (code_size + coarse_size);
97
+ memmove(code + coarse_size, codes + i * code_size, code_size);
98
+ encode_listno(list_nos[i], code);
99
+ }
100
+ }
101
+ }
102
+
103
+ void IndexIVFAdditiveQuantizer::sa_decode(
104
+ idx_t n,
105
+ const uint8_t* codes,
106
+ float* x) const {
107
+ const size_t coarse_size = coarse_code_size();
108
+
109
+ #pragma omp parallel if (n > 1000)
110
+ {
111
+ std::vector<float> residual(d);
112
+
113
+ #pragma omp for
114
+ for (idx_t i = 0; i < n; i++) {
115
+ const uint8_t* code = codes + i * (code_size + coarse_size);
116
+ int64_t list_no = decode_listno(code);
117
+ float* xi = x + i * d;
118
+ aq->decode(code + coarse_size, xi, 1);
119
+ if (by_residual) {
120
+ quantizer->reconstruct(list_no, residual.data());
121
+ for (size_t j = 0; j < d; j++) {
122
+ xi[j] += residual[j];
123
+ }
124
+ }
125
+ }
126
+ }
127
+ }
128
+
129
+ IndexIVFAdditiveQuantizer::~IndexIVFAdditiveQuantizer() {}
130
+
131
+ /*********************************************
132
+ * AQInvertedListScanner
133
+ *********************************************/
134
+
135
+ namespace {
136
+
137
+ using Search_type_t = AdditiveQuantizer::Search_type_t;
138
+
139
+ struct AQInvertedListScanner : InvertedListScanner {
140
+ const IndexIVFAdditiveQuantizer& ia;
141
+ const AdditiveQuantizer& aq;
142
+ std::vector<float> tmp;
143
+
144
+ AQInvertedListScanner(const IndexIVFAdditiveQuantizer& ia, bool store_pairs)
145
+ : ia(ia), aq(*ia.aq) {
146
+ this->store_pairs = store_pairs;
147
+ this->code_size = ia.code_size;
148
+ keep_max = ia.metric_type == METRIC_INNER_PRODUCT;
149
+ tmp.resize(ia.d);
150
+ }
151
+
152
+ const float* q0;
153
+
154
+ /// from now on we handle this query.
155
+ void set_query(const float* query_vector) override {
156
+ q0 = query_vector;
157
+ }
158
+
159
+ const float* q;
160
+ /// following codes come from this inverted list
161
+ void set_list(idx_t list_no, float coarse_dis) override {
162
+ if (ia.metric_type == METRIC_L2 && ia.by_residual) {
163
+ ia.quantizer->compute_residual(q0, tmp.data(), list_no);
164
+ q = tmp.data();
165
+ } else {
166
+ q = q0;
167
+ }
168
+ }
169
+
170
+ ~AQInvertedListScanner() {}
171
+ };
172
+
173
+ template <bool is_IP>
174
+ struct AQInvertedListScannerDecompress : AQInvertedListScanner {
175
+ AQInvertedListScannerDecompress(
176
+ const IndexIVFAdditiveQuantizer& ia,
177
+ bool store_pairs)
178
+ : AQInvertedListScanner(ia, store_pairs) {}
179
+
180
+ float coarse_dis = 0;
181
+
182
+ /// following codes come from this inverted list
183
+ void set_list(idx_t list_no, float coarse_dis) override {
184
+ AQInvertedListScanner::set_list(list_no, coarse_dis);
185
+ if (ia.by_residual) {
186
+ this->coarse_dis = coarse_dis;
187
+ }
188
+ }
189
+
190
+ /// compute a single query-to-code distance
191
+ float distance_to_code(const uint8_t* code) const final {
192
+ std::vector<float> b(aq.d);
193
+ aq.decode(code, b.data(), 1);
194
+ FAISS_ASSERT(q);
195
+ FAISS_ASSERT(b.data());
196
+
197
+ return is_IP ? coarse_dis + fvec_inner_product(q, b.data(), aq.d)
198
+ : fvec_L2sqr(q, b.data(), aq.d);
199
+ }
200
+
201
+ ~AQInvertedListScannerDecompress() override {}
202
+ };
203
+
204
+ template <bool is_IP, Search_type_t search_type>
205
+ struct AQInvertedListScannerLUT : AQInvertedListScanner {
206
+ std::vector<float> LUT, tmp;
207
+ float distance_bias;
208
+
209
+ AQInvertedListScannerLUT(
210
+ const IndexIVFAdditiveQuantizer& ia,
211
+ bool store_pairs)
212
+ : AQInvertedListScanner(ia, store_pairs) {
213
+ LUT.resize(aq.total_codebook_size);
214
+ tmp.resize(ia.d);
215
+ distance_bias = 0;
216
+ }
217
+
218
+ /// from now on we handle this query.
219
+ void set_query(const float* query_vector) override {
220
+ AQInvertedListScanner::set_query(query_vector);
221
+ if (!is_IP && !ia.by_residual) {
222
+ distance_bias = fvec_norm_L2sqr(query_vector, ia.d);
223
+ }
224
+ }
225
+
226
+ /// following codes come from this inverted list
227
+ void set_list(idx_t list_no, float coarse_dis) override {
228
+ AQInvertedListScanner::set_list(list_no, coarse_dis);
229
+ // TODO find a way to provide the nprobes together to do a matmul
230
+ // + precompute tables
231
+ aq.compute_LUT(1, q, LUT.data());
232
+
233
+ if (ia.by_residual) {
234
+ distance_bias = coarse_dis;
235
+ }
236
+ }
237
+
238
+ /// compute a single query-to-code distance
239
+ float distance_to_code(const uint8_t* code) const final {
240
+ return distance_bias +
241
+ aq.compute_1_distance_LUT<is_IP, search_type>(code, LUT.data());
242
+ }
243
+
244
+ ~AQInvertedListScannerLUT() override {}
245
+ };
246
+
247
+ } // anonymous namespace
248
+
249
+ InvertedListScanner* IndexIVFAdditiveQuantizer::get_InvertedListScanner(
250
+ bool store_pairs,
251
+ const IDSelector* sel) const {
252
+ FAISS_THROW_IF_NOT(!sel);
253
+ if (metric_type == METRIC_INNER_PRODUCT) {
254
+ if (aq->search_type == AdditiveQuantizer::ST_decompress) {
255
+ return new AQInvertedListScannerDecompress<true>(
256
+ *this, store_pairs);
257
+ } else {
258
+ return new AQInvertedListScannerLUT<
259
+ true,
260
+ AdditiveQuantizer::ST_LUT_nonorm>(*this, store_pairs);
261
+ }
262
+ } else {
263
+ switch (aq->search_type) {
264
+ case AdditiveQuantizer::ST_decompress:
265
+ return new AQInvertedListScannerDecompress<false>(
266
+ *this, store_pairs);
267
+ #define A(st) \
268
+ case AdditiveQuantizer::st: \
269
+ return new AQInvertedListScannerLUT<false, AdditiveQuantizer::st>( \
270
+ *this, store_pairs);
271
+ A(ST_LUT_nonorm)
272
+ // A(ST_norm_from_LUT)
273
+ A(ST_norm_float)
274
+ A(ST_norm_qint8)
275
+ A(ST_norm_qint4)
276
+ A(ST_norm_cqint4)
277
+ case AdditiveQuantizer::ST_norm_lsq2x4:
278
+ case AdditiveQuantizer::ST_norm_rq2x4:
279
+ A(ST_norm_cqint8)
280
+ #undef A
281
+ default:
282
+ FAISS_THROW_FMT(
283
+ "search type %d not supported", aq->search_type);
284
+ }
285
+ }
286
+ }
287
+
288
+ /**************************************************************************************
289
+ * IndexIVFResidualQuantizer
290
+ **************************************************************************************/
291
+
292
+ IndexIVFResidualQuantizer::IndexIVFResidualQuantizer(
293
+ Index* quantizer,
294
+ size_t d,
295
+ size_t nlist,
296
+ const std::vector<size_t>& nbits,
297
+ MetricType metric,
298
+ Search_type_t search_type)
299
+ : IndexIVFAdditiveQuantizer(&rq, quantizer, d, nlist, metric),
300
+ rq(d, nbits, search_type) {
301
+ code_size = invlists->code_size = rq.code_size;
302
+ }
303
+
304
+ IndexIVFResidualQuantizer::IndexIVFResidualQuantizer()
305
+ : IndexIVFAdditiveQuantizer(&rq) {}
306
+
307
+ IndexIVFResidualQuantizer::IndexIVFResidualQuantizer(
308
+ Index* quantizer,
309
+ size_t d,
310
+ size_t nlist,
311
+ size_t M, /* number of subquantizers */
312
+ size_t nbits, /* number of bit per subvector index */
313
+ MetricType metric,
314
+ Search_type_t search_type)
315
+ : IndexIVFResidualQuantizer(
316
+ quantizer,
317
+ d,
318
+ nlist,
319
+ std::vector<size_t>(M, nbits),
320
+ metric,
321
+ search_type) {}
322
+
323
+ IndexIVFResidualQuantizer::~IndexIVFResidualQuantizer() {}
324
+
325
+ /**************************************************************************************
326
+ * IndexIVFLocalSearchQuantizer
327
+ **************************************************************************************/
328
+
329
+ IndexIVFLocalSearchQuantizer::IndexIVFLocalSearchQuantizer(
330
+ Index* quantizer,
331
+ size_t d,
332
+ size_t nlist,
333
+ size_t M, /* number of subquantizers */
334
+ size_t nbits, /* number of bit per subvector index */
335
+ MetricType metric,
336
+ Search_type_t search_type)
337
+ : IndexIVFAdditiveQuantizer(&lsq, quantizer, d, nlist, metric),
338
+ lsq(d, M, nbits, search_type) {
339
+ code_size = invlists->code_size = lsq.code_size;
340
+ }
341
+
342
+ IndexIVFLocalSearchQuantizer::IndexIVFLocalSearchQuantizer()
343
+ : IndexIVFAdditiveQuantizer(&lsq) {}
344
+
345
+ IndexIVFLocalSearchQuantizer::~IndexIVFLocalSearchQuantizer() {}
346
+
347
+ /**************************************************************************************
348
+ * IndexIVFProductResidualQuantizer
349
+ **************************************************************************************/
350
+
351
+ IndexIVFProductResidualQuantizer::IndexIVFProductResidualQuantizer(
352
+ Index* quantizer,
353
+ size_t d,
354
+ size_t nlist,
355
+ size_t nsplits,
356
+ size_t Msub,
357
+ size_t nbits,
358
+ MetricType metric,
359
+ Search_type_t search_type)
360
+ : IndexIVFAdditiveQuantizer(&prq, quantizer, d, nlist, metric),
361
+ prq(d, nsplits, Msub, nbits, search_type) {
362
+ code_size = invlists->code_size = prq.code_size;
363
+ }
364
+
365
+ IndexIVFProductResidualQuantizer::IndexIVFProductResidualQuantizer()
366
+ : IndexIVFAdditiveQuantizer(&prq) {}
367
+
368
+ IndexIVFProductResidualQuantizer::~IndexIVFProductResidualQuantizer() {}
369
+
370
+ /**************************************************************************************
371
+ * IndexIVFProductLocalSearchQuantizer
372
+ **************************************************************************************/
373
+
374
+ IndexIVFProductLocalSearchQuantizer::IndexIVFProductLocalSearchQuantizer(
375
+ Index* quantizer,
376
+ size_t d,
377
+ size_t nlist,
378
+ size_t nsplits,
379
+ size_t Msub,
380
+ size_t nbits,
381
+ MetricType metric,
382
+ Search_type_t search_type)
383
+ : IndexIVFAdditiveQuantizer(&plsq, quantizer, d, nlist, metric),
384
+ plsq(d, nsplits, Msub, nbits, search_type) {
385
+ code_size = invlists->code_size = plsq.code_size;
386
+ }
387
+
388
+ IndexIVFProductLocalSearchQuantizer::IndexIVFProductLocalSearchQuantizer()
389
+ : IndexIVFAdditiveQuantizer(&plsq) {}
390
+
391
+ IndexIVFProductLocalSearchQuantizer::~IndexIVFProductLocalSearchQuantizer() {}
392
+
393
+ } // namespace faiss
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #ifndef FAISS_INDEX_IVF_ADDITIVE_QUANTIZER_H
9
+ #define FAISS_INDEX_IVF_ADDITIVE_QUANTIZER_H
10
+
11
+ #include <faiss/impl/AdditiveQuantizer.h>
12
+
13
+ #include <cstdint>
14
+ #include <vector>
15
+
16
+ #include <faiss/IndexIVF.h>
17
+ #include <faiss/impl/LocalSearchQuantizer.h>
18
+ #include <faiss/impl/ProductAdditiveQuantizer.h>
19
+ #include <faiss/impl/ResidualQuantizer.h>
20
+ #include <faiss/impl/platform_macros.h>
21
+
22
+ namespace faiss {
23
+
24
+ /// Abstract class for IVF additive quantizers.
25
+ /// The search functions are in common.
26
+ struct IndexIVFAdditiveQuantizer : IndexIVF {
27
+ // the quantizer
28
+ AdditiveQuantizer* aq;
29
+ bool by_residual = true;
30
+ int use_precomputed_table = 0; // for future use
31
+
32
+ using Search_type_t = AdditiveQuantizer::Search_type_t;
33
+
34
+ IndexIVFAdditiveQuantizer(
35
+ AdditiveQuantizer* aq,
36
+ Index* quantizer,
37
+ size_t d,
38
+ size_t nlist,
39
+ MetricType metric = METRIC_L2);
40
+
41
+ explicit IndexIVFAdditiveQuantizer(AdditiveQuantizer* aq);
42
+
43
+ void train_residual(idx_t n, const float* x) override;
44
+
45
+ void encode_vectors(
46
+ idx_t n,
47
+ const float* x,
48
+ const idx_t* list_nos,
49
+ uint8_t* codes,
50
+ bool include_listnos = false) const override;
51
+
52
+ InvertedListScanner* get_InvertedListScanner(
53
+ bool store_pairs,
54
+ const IDSelector* sel) const override;
55
+
56
+ void sa_decode(idx_t n, const uint8_t* codes, float* x) const override;
57
+
58
+ ~IndexIVFAdditiveQuantizer() override;
59
+ };
60
+
61
+ /** IndexIVF based on a residual quantizer. Stored vectors are
62
+ * approximated by residual quantization codes.
63
+ */
64
+ struct IndexIVFResidualQuantizer : IndexIVFAdditiveQuantizer {
65
+ /// The residual quantizer used to encode the vectors
66
+ ResidualQuantizer rq;
67
+
68
+ /** Constructor.
69
+ *
70
+ * @param d dimensionality of the input vectors
71
+ * @param M number of subquantizers
72
+ * @param nbits number of bit per subvector index
73
+ */
74
+ IndexIVFResidualQuantizer(
75
+ Index* quantizer,
76
+ size_t d,
77
+ size_t nlist,
78
+ const std::vector<size_t>& nbits,
79
+ MetricType metric = METRIC_L2,
80
+ Search_type_t search_type = AdditiveQuantizer::ST_decompress);
81
+
82
+ IndexIVFResidualQuantizer(
83
+ Index* quantizer,
84
+ size_t d,
85
+ size_t nlist,
86
+ size_t M, /* number of subquantizers */
87
+ size_t nbits, /* number of bit per subvector index */
88
+ MetricType metric = METRIC_L2,
89
+ Search_type_t search_type = AdditiveQuantizer::ST_decompress);
90
+
91
+ IndexIVFResidualQuantizer();
92
+
93
+ virtual ~IndexIVFResidualQuantizer();
94
+ };
95
+
96
+ /** IndexIVF based on a residual quantizer. Stored vectors are
97
+ * approximated by residual quantization codes.
98
+ */
99
+ struct IndexIVFLocalSearchQuantizer : IndexIVFAdditiveQuantizer {
100
+ /// The LSQ quantizer used to encode the vectors
101
+ LocalSearchQuantizer lsq;
102
+
103
+ /** Constructor.
104
+ *
105
+ * @param d dimensionality of the input vectors
106
+ * @param M number of subquantizers
107
+ * @param nbits number of bit per subvector index
108
+ */
109
+ IndexIVFLocalSearchQuantizer(
110
+ Index* quantizer,
111
+ size_t d,
112
+ size_t nlist,
113
+ size_t M, /* number of subquantizers */
114
+ size_t nbits, /* number of bit per subvector index */
115
+ MetricType metric = METRIC_L2,
116
+ Search_type_t search_type = AdditiveQuantizer::ST_decompress);
117
+
118
+ IndexIVFLocalSearchQuantizer();
119
+
120
+ virtual ~IndexIVFLocalSearchQuantizer();
121
+ };
122
+
123
+ /** IndexIVF based on a product residual quantizer. Stored vectors are
124
+ * approximated by product residual quantization codes.
125
+ */
126
+ struct IndexIVFProductResidualQuantizer : IndexIVFAdditiveQuantizer {
127
+ /// The product residual quantizer used to encode the vectors
128
+ ProductResidualQuantizer prq;
129
+
130
+ /** Constructor.
131
+ *
132
+ * @param d dimensionality of the input vectors
133
+ * @param nsplits number of residual quantizers
134
+ * @param Msub number of subquantizers per RQ
135
+ * @param nbits number of bit per subvector index
136
+ */
137
+ IndexIVFProductResidualQuantizer(
138
+ Index* quantizer,
139
+ size_t d,
140
+ size_t nlist,
141
+ size_t nsplits,
142
+ size_t Msub,
143
+ size_t nbits,
144
+ MetricType metric = METRIC_L2,
145
+ Search_type_t search_type = AdditiveQuantizer::ST_decompress);
146
+
147
+ IndexIVFProductResidualQuantizer();
148
+
149
+ virtual ~IndexIVFProductResidualQuantizer();
150
+ };
151
+
152
+ /** IndexIVF based on a product local search quantizer. Stored vectors are
153
+ * approximated by product local search quantization codes.
154
+ */
155
+ struct IndexIVFProductLocalSearchQuantizer : IndexIVFAdditiveQuantizer {
156
+ /// The product local search quantizer used to encode the vectors
157
+ ProductLocalSearchQuantizer plsq;
158
+
159
+ /** Constructor.
160
+ *
161
+ * @param d dimensionality of the input vectors
162
+ * @param nsplits number of local search quantizers
163
+ * @param Msub number of subquantizers per LSQ
164
+ * @param nbits number of bit per subvector index
165
+ */
166
+ IndexIVFProductLocalSearchQuantizer(
167
+ Index* quantizer,
168
+ size_t d,
169
+ size_t nlist,
170
+ size_t nsplits,
171
+ size_t Msub,
172
+ size_t nbits,
173
+ MetricType metric = METRIC_L2,
174
+ Search_type_t search_type = AdditiveQuantizer::ST_decompress);
175
+
176
+ IndexIVFProductLocalSearchQuantizer();
177
+
178
+ virtual ~IndexIVFProductLocalSearchQuantizer();
179
+ };
180
+
181
+ } // namespace faiss
182
+
183
+ #endif