15 #include <gtest/gtest.h>
17 #include <faiss/IndexIVF.h>
18 #include <faiss/AutoTune.h>
19 #include <faiss/index_io.h>
20 #include <faiss/IVFlib.h>
22 using namespace faiss;
47 std::vector<float> make_data(
size_t n)
49 std::vector <float> database (n * d);
50 for (
size_t i = 0; i < n * d; i++) {
51 database[i] = drand48();
56 std::unique_ptr<Index> make_trained_index(
const char *index_type)
58 auto index = std::unique_ptr<Index>(
index_factory(d, index_type));
59 auto xt = make_data(nt * d);
60 index->
train(nt, xt.data());
65 std::vector<idx_t> search_index(
Index *index,
const float *xq) {
67 std::vector<idx_t> I(k * nq);
68 std::vector<float> D(k * nq);
69 index->
search (nq, xq, k, D.data(), I.data());
83 void make_index_slices (
const Index* trained_index,
84 std::vector<std::unique_ptr<Index> > & sub_indexes) {
86 for (
int i = 0; i < total_size; i++) {
87 sub_indexes.emplace_back (clone_index (trained_index));
89 printf (
"preparing sub-index # %d\n", i);
91 Index * index = sub_indexes.back().get();
93 auto xb = make_data(nb * d);
94 std::vector<long> ids (nb);
95 for (
int j = 0; j < nb; j++) {
104 Index *make_merged_index(
105 const Index* trained_index,
106 const std::vector<std::unique_ptr<Index> > & sub_indexes,
109 Index * merged_index = clone_index (trained_index);
110 for (
int j = i - window_size + 1; j <= i; j++) {
111 if (j < 0 || j >= total_size)
continue;
112 std::unique_ptr<Index> sub_index (
113 clone_index (sub_indexes[j].
get()));
114 IndexIVF *ivf0 = ivflib::extract_index_ivf (merged_index);
115 IndexIVF *ivf1 = ivflib::extract_index_ivf (sub_index.get());
122 int test_sliding_window (
const char *index_key) {
124 std::unique_ptr<Index> trained_index = make_trained_index(index_key);
127 std::vector<std::unique_ptr<Index> > sub_indexes;
129 make_index_slices (trained_index.get(), sub_indexes);
132 std::unique_ptr<Index> index (clone_index (trained_index.get()));
135 auto xq = make_data (nq * d);
137 for (
int i = 0; i < total_size + window_size; i++) {
139 printf (
"doing step %d / %d\n", i, total_size + window_size);
142 window.step (i < total_size ? sub_indexes[i].
get() :
nullptr,
144 printf (
" current n_slice = %d\n", window.n_slice);
146 auto new_res = search_index (index.get(), xq.data());
148 std::unique_ptr<Index> merged_index (
149 make_merged_index (trained_index.get(), sub_indexes, i));
151 auto ref_res = search_index (merged_index.get(), xq.data ());
153 EXPECT_EQ (ref_res.size(), new_res.size());
155 EXPECT_EQ (ref_res, new_res);
161 int test_sliding_invlists (
const char *index_key) {
163 std::unique_ptr<Index> trained_index = make_trained_index(index_key);
166 std::vector<std::unique_ptr<Index> > sub_indexes;
168 make_index_slices (trained_index.get(), sub_indexes);
171 std::unique_ptr<Index> index (clone_index (trained_index.get()));
172 IndexIVF * index_ivf = ivflib::extract_index_ivf (index.get());
174 auto xq = make_data (nq * d);
176 for (
int i = 0; i < total_size + window_size; i++) {
178 printf (
"doing step %d / %d\n", i, total_size + window_size);
181 std::vector<const InvertedLists*> ils;
182 for (
int j = i - window_size + 1; j <= i; j++) {
183 if (j < 0 || j >= total_size)
continue;
184 ils.push_back (ivflib::extract_index_ivf (
185 sub_indexes[j].
get())->invlists);
187 if (ils.size() == 0)
continue;
195 printf (
" nb invlists = %ld\n", ils.size());
197 auto new_res = search_index (index.get(), xq.data());
199 std::unique_ptr<Index> merged_index (
200 make_merged_index (trained_index.get(), sub_indexes, i));
202 auto ref_res = search_index (merged_index.get(), xq.data ());
204 EXPECT_EQ (ref_res.size(), new_res.size());
207 for (
size_t j = 0; j < ref_res.size(); j++) {
208 if (ref_res[j] != new_res[j])
211 printf(
" nb differences: %ld / %ld\n",
212 ndiff, ref_res.size());
213 EXPECT_EQ (ref_res, new_res);
226 TEST(SlidingWindow, IVFFlat) {
227 test_sliding_window (
"IVF32,Flat");
230 TEST(SlidingWindow, PCAIVFFlat) {
231 test_sliding_window (
"PCA24,IVF32,Flat");
234 TEST(SlidingInvlists, IVFFlat) {
235 test_sliding_invlists (
"IVF32,Flat");
238 TEST(SlidingInvlists, PCAIVFFlat) {
239 test_sliding_invlists (
"PCA24,IVF32,Flat");
void train(idx_t n, const float *x) override
virtual void add_with_ids(idx_t n, const float *x, const long *xids)
long idx_t
all indices are this type
void replace_invlists(InvertedLists *il, bool own=false)
replace the inverted lists, old one is deallocated if own_invlists
idx_t ntotal
total nb of indexed vectors
virtual void search(idx_t n, const float *x, idx_t k, float *distances, idx_t *labels) const =0
virtual void set_index_parameter(Index *index, const std::string &name, double val) const
set one of the parameters
Index * index_factory(int d, const char *description_in, MetricType metric)
virtual void merge_from(IndexIVF &other, idx_t add_id)