Skip to content

Commit 97598a6

Browse files
committed
Bug fix for Index::size() when points are removed.
Index::size() should not include the number of points removed from the index.
1 parent 00059a0 commit 97598a6

File tree

7 files changed

+125
-33
lines changed

7 files changed

+125
-33
lines changed

src/cpp/flann/algorithms/nn_index.h

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,13 @@ class NNIndex : public IndexBase
7676
typedef typename Distance::ElementType ElementType;
7777
typedef typename Distance::ResultType DistanceType;
7878

79-
NNIndex(Distance d) : distance_(d), last_id_(0), size_(0), veclen_(0), data_ptr_(NULL), removed_(false)
79+
NNIndex(Distance d) : distance_(d), last_id_(0), size_(0), veclen_(0),
80+
removed_(false), removed_count_(0), data_ptr_(NULL)
8081
{
8182
}
8283

8384
NNIndex(const IndexParams& params, Distance d) : distance_(d), last_id_(0), size_(0), veclen_(0),
84-
index_params_(params), data_ptr_(NULL), removed_(false)
85+
index_params_(params), removed_(false), removed_count_(0), data_ptr_(NULL)
8586
{
8687
}
8788

@@ -91,11 +92,12 @@ class NNIndex : public IndexBase
9192
size_(other.size_),
9293
veclen_(other.veclen_),
9394
index_params_(other.index_params_),
95+
removed_(other.removed_),
9496
removed_points_(other.removed_points_),
97+
removed_count_(other.removed_count_),
9598
ids_(other.ids_),
9699
points_(other.points_),
97-
data_ptr_(NULL),
98-
removed_(other.removed_)
100+
data_ptr_(NULL)
99101
{
100102
if (other.data_ptr_) {
101103
data_ptr_ = new ElementType[size_*veclen_];
@@ -155,13 +157,14 @@ class NNIndex : public IndexBase
155157
removed_points_.resize(size_);
156158
removed_points_.reset();
157159
last_id_ = size_;
160+
removed_ = true;
158161
}
159162

160163
size_t point_index = id_to_index(id);
161-
if (point_index!=size_t(-1)) {
164+
if (point_index!=size_t(-1) && !removed_points_.test(point_index)) {
162165
removed_points_.set(point_index);
166+
removed_count_++;
163167
}
164-
removed_ = true;
165168
}
166169

167170

@@ -186,7 +189,7 @@ class NNIndex : public IndexBase
186189
*/
187190
inline size_t size() const
188191
{
189-
return size_;
192+
return size_ - removed_count_;
190193
}
191194

192195
/**
@@ -500,7 +503,7 @@ class NNIndex : public IndexBase
500503
}
501504
else {
502505
// explicitly indicated to use unbounded radius result set
503-
// or we know there'll be enough room for resulting indices and dists
506+
// and we know there'll be enough room for resulting indices and dists
504507
if (params.max_neighbors<0 && (num_neighbors>=size())) {
505508
#pragma omp parallel num_threads(params.cores)
506509
{
@@ -694,7 +697,7 @@ class NNIndex : public IndexBase
694697
else {
695698
// binary search
696699
size_t start = 0;
697-
size_t end = size();
700+
size_t end = ids_.size();
698701

699702
while (start<end) {
700703
size_t mid = (start+end)/2;
@@ -732,6 +735,7 @@ class NNIndex : public IndexBase
732735
ids_.clear();
733736
removed_points_.clear();
734737
removed_ = false;
738+
removed_count_ = 0;
735739

736740
points_.resize(size_);
737741
for (size_t i=0;i<size_;++i) {
@@ -775,6 +779,7 @@ class NNIndex : public IndexBase
775779
ids_.resize(last_idx);
776780
removed_points_.resize(last_idx);
777781
size_ = last_idx;
782+
removed_count_ = 0;
778783
}
779784

780785
void swap(NNIndex& other)
@@ -784,11 +789,12 @@ class NNIndex : public IndexBase
784789
std::swap(size_, other.size_);
785790
std::swap(veclen_, other.veclen_);
786791
std::swap(index_params_, other.index_params_);
792+
std::swap(removed_, other.removed_);
787793
std::swap(removed_points_, other.removed_points_);
794+
std::swap(removed_count_, other.removed_count_);
788795
std::swap(ids_, other.ids_);
789796
std::swap(points_, other.points_);
790797
std::swap(data_ptr_, other.data_ptr_);
791-
std::swap(removed_, other.removed_);
792798
}
793799

794800
protected:
@@ -821,11 +827,21 @@ class NNIndex : public IndexBase
821827
*/
822828
IndexParams index_params_;
823829

830+
/**
831+
* Flag indicating if at least a point was removed from the index
832+
*/
833+
bool removed_;
834+
824835
/**
825836
* Array used to mark points removed from the index
826837
*/
827838
DynamicBitset removed_points_;
828839

840+
/**
841+
* Number of points removed from the index
842+
*/
843+
size_t removed_count_;
844+
829845
/**
830846
* Array of point IDs, returned by nearest-neighbour operations
831847
*/
@@ -841,10 +857,6 @@ class NNIndex : public IndexBase
841857
*/
842858
ElementType* data_ptr_;
843859

844-
/**
845-
* Flag indicating if at least a point was removed from the index
846-
*/
847-
bool removed_;
848860

849861
};
850862

test/flann_hierarchical_test.cpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -142,15 +142,27 @@ TEST_F(HierarchicalIndex_Brief100K, TestRemove)
142142
}
143143
}
144144
}
145-
for (std::set<int>::iterator it = neighbors.begin(); it!=neighbors.end();++it) {
146-
index.removePoint(*it);
147-
}
148145

149-
// also remove 10% of the initial points
150-
size_t offset = data.rows/10;
151-
for (size_t i=0;i<offset;++i) {
152-
index.removePoint(i);
153-
}
146+
flann::DynamicBitset removed(data.rows);
147+
148+
for (std::set<int>::iterator it = neighbors.begin(); it!=neighbors.end();++it) {
149+
index.removePoint(*it);
150+
removed.set(*it);
151+
}
152+
153+
// also remove 10% of the initial points
154+
size_t offset = data.rows/10;
155+
for (size_t i=0;i<offset;++i) {
156+
index.removePoint(i);
157+
removed.set(i);
158+
}
159+
160+
size_t new_size = 0;
161+
for (size_t i=0;i<removed.size();++i) {
162+
if (!removed.test(i)) ++new_size;
163+
}
164+
165+
EXPECT_EQ(index.size(), new_size);
154166

155167
start_timer("Searching KNN after remove points...");
156168
index.knnSearch(query, indices, dists, k_nn_, flann::SearchParams(2000) );
@@ -166,6 +178,8 @@ TEST_F(HierarchicalIndex_Brief100K, TestRemove)
166178
// rebuild index
167179
index.buildIndex();
168180

181+
EXPECT_EQ(index.size(), new_size);
182+
169183
start_timer("Searching KNN after remove points and rebuild index...");
170184
index.knnSearch(query, indices, dists, k_nn_, flann::SearchParams(2000) );
171185
printf("done (%g seconds)\n", stop_timer());

test/flann_kdtree_single_test.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,20 @@ TEST_F(KDTreeSingle, TestRemove)
9595
}
9696
}
9797
}
98-
for (std::set<int>::iterator it = neighbors.begin(); it!=neighbors.end();++it) {
99-
index.removePoint(*it);
100-
}
98+
flann::DynamicBitset removed(data.rows);
99+
100+
for (std::set<int>::iterator it = neighbors.begin(); it!=neighbors.end();++it) {
101+
index.removePoint(*it);
102+
removed.set(*it);
103+
}
104+
105+
size_t new_size = 0;
106+
for (size_t i=0;i<removed.size();++i) {
107+
if (!removed.test(i)) ++new_size;
108+
}
109+
110+
EXPECT_EQ(index.size(), new_size);
111+
101112

102113
start_timer("Searching KNN after remove points...");
103114
index.knnSearch(query, indices, dists, knn, flann::SearchParams(-1) );
@@ -112,6 +123,8 @@ TEST_F(KDTreeSingle, TestRemove)
112123
// rebuild index
113124
index.buildIndex();
114125

126+
EXPECT_EQ(index.size(), new_size);
127+
115128
start_timer("Searching KNN after remove points and rebuild index...");
116129
index.knnSearch(query, indices, dists, knn, flann::SearchParams(-1) );
117130
printf("done (%g seconds)\n", stop_timer());

test/flann_kdtree_test.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,28 @@ TEST_F(KDTree_SIFT10K, TestRemove)
110110
}
111111
}
112112
}
113+
114+
flann::DynamicBitset removed(data.rows);
115+
113116
for (std::set<int>::iterator it = neighbors.begin(); it!=neighbors.end();++it) {
114117
index.removePoint(*it);
118+
removed.set(*it);
115119
}
116120

117121
// also remove 10% of the initial points
118122
size_t offset = data.rows/10;
119123
for (size_t i=0;i<offset;++i) {
120124
index.removePoint(i);
125+
removed.set(i);
126+
}
127+
128+
size_t new_size = 0;
129+
for (size_t i=0;i<removed.size();++i) {
130+
if (!removed.test(i)) ++new_size;
121131
}
122132

133+
EXPECT_EQ(index.size(), new_size);
134+
123135
start_timer("Searching KNN after remove points...");
124136
index.knnSearch(query, indices, dists, knn, flann::SearchParams(128) );
125137
printf("done (%g seconds)\n", stop_timer());
@@ -135,6 +147,8 @@ TEST_F(KDTree_SIFT10K, TestRemove)
135147
// rebuild index
136148
index.buildIndex();
137149

150+
EXPECT_EQ(index.size(), new_size);
151+
138152
start_timer("Searching KNN after remove points and rebuild index...");
139153
index.knnSearch(query, indices, dists, knn, flann::SearchParams(128) );
140154
printf("done (%g seconds)\n", stop_timer());

test/flann_kmeans_test.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,16 +98,27 @@ TEST_F(KMeans_SIFT10K, TestRemove)
9898
}
9999
}
100100
}
101+
flann::DynamicBitset removed(data.rows);
102+
101103
for (std::set<int>::iterator it = neighbors.begin(); it!=neighbors.end();++it) {
102104
index.removePoint(*it);
105+
removed.set(*it);
103106
}
104107

105108
// also remove 10% of the initial points
106109
size_t offset = data.rows/10;
107110
for (size_t i=0;i<offset;++i) {
108111
index.removePoint(i);
112+
removed.set(i);
113+
}
114+
115+
size_t new_size = 0;
116+
for (size_t i=0;i<removed.size();++i) {
117+
if (!removed.test(i)) ++new_size;
109118
}
110119

120+
EXPECT_EQ(index.size(), new_size);
121+
111122
start_timer("Searching KNN after remove points...");
112123
index.knnSearch(query, indices, dists, knn, flann::SearchParams(128) );
113124
printf("done (%g seconds)\n", stop_timer());
@@ -122,6 +133,8 @@ TEST_F(KMeans_SIFT10K, TestRemove)
122133
// rebuild index
123134
index.buildIndex();
124135

136+
EXPECT_EQ(index.size(), new_size);
137+
125138
start_timer("Searching KNN after remove points and rebuild index...");
126139
index.knnSearch(query, indices, dists, knn, flann::SearchParams(128) );
127140
printf("done (%g seconds)\n", stop_timer());

test/flann_linear_test.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,27 @@ TEST_F(Linear_SIFT10K, TestRemove)
5555
}
5656
}
5757
}
58+
flann::DynamicBitset removed(data.rows);
59+
5860
for (std::set<int>::iterator it = neighbors.begin(); it!=neighbors.end();++it) {
5961
index.removePoint(*it);
62+
removed.set(*it);
6063
}
6164

6265
// also remove 10% of the initial points
6366
size_t offset = data.rows/10;
6467
for (size_t i=0;i<offset;++i) {
6568
index.removePoint(i);
69+
removed.set(i);
70+
}
71+
72+
size_t new_size = 0;
73+
for (size_t i=0;i<removed.size();++i) {
74+
if (!removed.test(i)) ++new_size;
6675
}
6776

77+
EXPECT_EQ(index.size(), new_size);
78+
6879
start_timer("Searching KNN after remove points...");
6980
index.knnSearch(query, indices, dists, 5, flann::SearchParams(128) );
7081
printf("done (%g seconds)\n", stop_timer());
@@ -79,6 +90,8 @@ TEST_F(Linear_SIFT10K, TestRemove)
7990
// rebuild index
8091
index.buildIndex();
8192

93+
EXPECT_EQ(index.size(), new_size);
94+
8295
start_timer("Searching KNN after remove points and rebuild index...");
8396
index.knnSearch(query, indices, dists, knn, flann::SearchParams(128) );
8497
printf("done (%g seconds)\n", stop_timer());

test/flann_lsh_test.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -145,15 +145,26 @@ TEST_F(LshIndex_Brief100K, TestRemove)
145145
}
146146
}
147147
}
148-
for (std::set<int>::iterator it = neighbors.begin(); it!=neighbors.end();++it) {
149-
index.removePoint(*it);
150-
}
148+
flann::DynamicBitset removed(data.rows);
151149

152-
// also remove 10% of the initial points
153-
size_t offset = data.rows/10;
154-
for (size_t i=0;i<offset;++i) {
155-
index.removePoint(i);
156-
}
150+
for (std::set<int>::iterator it = neighbors.begin(); it!=neighbors.end();++it) {
151+
index.removePoint(*it);
152+
removed.set(*it);
153+
}
154+
155+
// also remove 10% of the initial points
156+
size_t offset = data.rows/10;
157+
for (size_t i=0;i<offset;++i) {
158+
index.removePoint(i);
159+
removed.set(i);
160+
}
161+
162+
size_t new_size = 0;
163+
for (size_t i=0;i<removed.size();++i) {
164+
if (!removed.test(i)) ++new_size;
165+
}
166+
167+
EXPECT_EQ(index.size(), new_size);
157168

158169
start_timer("Searching KNN after remove points...");
159170
index.knnSearch(query, indices, dists, k_nn_, flann::SearchParams(-1) );
@@ -169,6 +180,8 @@ TEST_F(LshIndex_Brief100K, TestRemove)
169180
// rebuild index
170181
index.buildIndex();
171182

183+
EXPECT_EQ(index.size(), new_size);
184+
172185
start_timer("Searching KNN after remove points and rebuild index...");
173186
index.knnSearch(query, indices, dists, k_nn_, flann::SearchParams(128) );
174187
printf("done (%g seconds)\n", stop_timer());

0 commit comments

Comments
 (0)