31 #ifndef RTABMAP_FLANN_HIERARCHICAL_CLUSTERING_INDEX_H_ 32 #define RTABMAP_FLANN_HIERARCHICAL_CLUSTERING_INDEX_H_ 42 #define SIZE_MAX ((size_t) -1) 63 int trees = 4,
int leaf_max_size = 100)
67 (*this)[
"branching"] = branching;
69 (*this)[
"centers_init"] = centers_init;
71 (*this)[
"trees"] = trees;
73 (*this)[
"leaf_max_size"] = leaf_max_size;
85 template <
typename Distance>
101 : BaseClass(index_params,
d)
105 branching_ =
get_param(index_params_,
"branching",32);
107 trees_ =
get_param(index_params_,
"trees",4);
108 leaf_max_size_ =
get_param(index_params_,
"leaf_max_size",100);
122 Distance d = Distance())
123 : BaseClass(index_params,
d)
127 branching_ =
get_param(index_params_,
"branching",32);
129 trees_ =
get_param(index_params_,
"trees",4);
130 leaf_max_size_ =
get_param(index_params_,
"leaf_max_size",100);
134 setDataset(inputData);
136 chooseCenters_->setDataSize(veclen_);
141 memoryCounter_(other.memoryCounter_),
142 branching_(other.branching_),
143 trees_(other.trees_),
144 centers_init_(other.centers_init_),
145 leaf_max_size_(other.leaf_max_size_)
150 for (
size_t i=0;i<tree_roots_.size();++i) {
164 switch(centers_init_) {
178 throw FLANNException(
"Unknown algorithm for choosing initial centers.");
189 delete chooseCenters_;
204 return pool_.usedMemory+pool_.wastedMemory+memoryCounter_;
207 using BaseClass::buildIndex;
211 assert(points.
cols==veclen_);
212 size_t old_size = size_;
214 extendDataset(points);
216 if (rebuild_threshold>1 && size_at_build_*rebuild_threshold<size_) {
220 for (
size_t i=0;i<points.
rows;++i) {
221 for (
int j = 0; j < trees_; j++) {
222 addPointToTree(tree_roots_[j], old_size + i);
235 template<
typename Archive>
247 if (Archive::is_loading::value) {
248 tree_roots_.resize(trees_);
250 for (
size_t i=0;i<tree_roots_.size();++i) {
251 if (Archive::is_loading::value) {
252 tree_roots_[i] =
new(pool_)
Node();
254 ar & *tree_roots_[i];
257 if (Archive::is_loading::value) {
258 index_params_[
"algorithm"] = getType();
259 index_params_[
"branching"] = branching_;
260 index_params_[
"trees"] = trees_;
261 index_params_[
"centers_init"] = centers_init_;
262 index_params_[
"leaf_size"] = leaf_max_size_;
293 findNeighborsWithRemoved<true>(result, vec, searchParams);
296 findNeighborsWithRemoved<false>(result, vec, searchParams);
307 chooseCenters_->setDataSize(veclen_);
312 tree_roots_.resize(trees_);
313 std::vector<int> indices(size_);
314 for (
int i=0; i<trees_; ++i) {
315 for (
size_t j=0; j<size_; ++j) {
318 tree_roots_[i] =
new(pool_)
Node();
319 computeClustering(tree_roots_[i], &indices[0], size_);
333 template<
typename Archive>
337 Index* obj =
static_cast<Index*
>(ar.getObject());
342 if (Archive::is_loading::value) {
343 point = obj->points_[index];
378 for(
size_t i=0; i<childs.size(); i++){
386 template<
typename Archive>
390 Index* obj =
static_cast<Index*
>(ar.getObject());
392 if (Archive::is_loading::value) {
394 pivot = obj->points_[pivot_index];
399 if (Archive::is_saving::value) {
400 childs_size = childs.size();
404 if (childs_size==0) {
408 if (Archive::is_loading::value) {
409 childs.resize(childs_size);
411 for (
size_t i=0;i<childs_size;++i) {
412 if (Archive::is_loading::value) {
413 childs[i] =
new(obj->pool_)
Node();
437 for (
size_t i=0; i<tree_roots_.size(); ++i) {
438 tree_roots_[i]->~Node();
445 dst =
new(pool_)
Node();
449 if (src->
childs.size()==0) {
454 for (
size_t i=0;i<src->
childs.size();++i) {
462 void computeLabels(
int* indices,
int indices_length,
int* centers,
int centers_length,
int* labels, DistanceType& cost)
465 for (
int i=0; i<indices_length; ++i) {
466 ElementType* point = points_[indices[i]];
467 DistanceType dist = distance_(point, points_[centers[0]], veclen_);
469 for (
int j=1; j<centers_length; ++j) {
470 DistanceType new_dist = distance_(point, points_[centers[j]], veclen_);
492 if (indices_length < leaf_max_size_) {
493 node->
points.resize(indices_length);
494 for (
int i=0;i<indices_length;++i) {
495 node->
points[i].index = indices[i];
496 node->
points[i].point = points_[indices[i]];
502 std::vector<int> centers(branching_);
503 std::vector<int> labels(indices_length);
506 (*chooseCenters_)(branching_, indices, indices_length, ¢ers[0], centers_length);
508 if (centers_length<branching_) {
509 node->
points.resize(indices_length);
510 for (
int i=0;i<indices_length;++i) {
511 node->
points[i].index = indices[i];
512 node->
points[i].point = points_[indices[i]];
521 computeLabels(indices, indices_length, ¢ers[0], centers_length, &labels[0], cost);
523 node->
childs.resize(branching_);
526 for (
int i=0; i<branching_; ++i) {
527 for (
int j=0; j<indices_length; ++j) {
529 std::swap(indices[j],indices[end]);
530 std::swap(labels[j],labels[end]);
536 node->
childs[i]->pivot_index = centers[i];
537 node->
childs[i]->pivot = points_[centers[i]];
538 node->
childs[i]->points.clear();
539 computeClustering(node->
childs[i],indices+start, end-start);
545 template<
bool with_removed>
548 int maxChecks = searchParams.
checks;
555 for (
int i=0; i<trees_; ++i) {
556 findNN<with_removed>(tree_roots_[i], result, vec, checks, maxChecks, heap, checked);
560 while (heap->
popMin(branch) && (checks<maxChecks || !result.
full())) {
561 NodePtr node = branch.node;
562 findNN<with_removed>(node, result, vec, checks, maxChecks, heap, checked);
581 template<
bool with_removed>
585 if (node->
childs.empty()) {
586 if (checks>=maxChecks) {
587 if (result.
full())
return;
590 for (
size_t i=0; i<node->
points.size(); ++i) {
593 if (removed_points_.test(pointInfo.
index))
continue;
595 if (checked.
test(pointInfo.
index))
continue;
596 DistanceType dist = distance_(pointInfo.
point, vec, veclen_);
603 DistanceType* domain_distances =
new DistanceType[branching_];
605 domain_distances[best_index] = distance_(vec, node->
childs[best_index]->pivot, veclen_);
606 for (
int i=1; i<branching_; ++i) {
607 domain_distances[i] = distance_(vec, node->
childs[i]->pivot, veclen_);
608 if (domain_distances[i]<domain_distances[best_index]) {
612 for (
int i=0; i<branching_; ++i) {
614 heap->
insert(BranchSt(node->
childs[i],domain_distances[i]));
617 delete[] domain_distances;
618 findNN<with_removed>(node->
childs[best_index],result,vec, checks, maxChecks, heap, checked);
624 ElementType* point = points_[index];
626 if (node->
childs.empty()) {
628 pointInfo.
point = point;
629 pointInfo.
index = index;
630 node->
points.push_back(pointInfo);
632 if (node->
points.size()>=size_t(branching_)) {
633 std::vector<int> indices(node->
points.size());
635 for (
size_t i=0;i<node->
points.size();++i) {
636 indices[i] = node->
points[i].index;
638 computeClustering(node, &indices[0], indices.size());
644 ElementType* center = node->
childs[closest]->pivot;
645 DistanceType dist = distance_(center, point, veclen_);
646 for (
size_t i=1;i<size_t(branching_);++i) {
647 center = node->
childs[i]->pivot;
648 DistanceType crt_dist = distance_(center, point, veclen_);
654 addPointToTree(node->
childs[closest], index);
660 BaseClass::swap(other);
663 std::swap(pool_, other.
pool_);
666 std::swap(trees_, other.
trees_);
HierarchicalClusteringIndex & operator=(HierarchicalClusteringIndex other)
std::map< std::string, any > IndexParams
flann_centers_init_t centers_init_
T get_param(const IndexParams ¶ms, std::string name, const T &default_value)
void findNeighborsWithRemoved(ResultSet< DistanceType > &result, const ElementType *vec, const SearchParams &searchParams) const
void copyTree(NodePtr &dst, const NodePtr &src)
virtual ~HierarchicalClusteringIndex()
CenterChooser< Distance > * chooseCenters_
std::vector< Node * > childs
void loadIndex(FILE *stream)
HierarchicalClusteringIndex(const IndexParams &index_params=HierarchicalClusteringIndexParams(), Distance d=Distance())
void insert(const T &value)
Distance::ResultType DistanceType
#define USING_BASECLASS_SYMBOLS
void addPointToTree(NodePtr node, size_t index)
void findNeighbors(ResultSet< DistanceType > &result, const ElementType *vec, const SearchParams &searchParams) const
void swap(HierarchicalClusteringIndex &other)
void serialize(Archive &ar)
HierarchicalClusteringIndex(const HierarchicalClusteringIndex &other)
bool test(size_t index) const
HierarchicalClusteringIndex(const Matrix< ElementType > &inputData, const IndexParams &index_params=HierarchicalClusteringIndexParams(), Distance d=Distance())
void addPoints(const Matrix< ElementType > &points, float rebuild_threshold=2)
Incrementally add points to the index.
void serialize(Archive &ar)
void findNN(NodePtr node, ResultSet< DistanceType > &result, const ElementType *vec, int &checks, int maxChecks, Heap< BranchSt > *heap, DynamicBitset &checked) const
BranchStruct< NodePtr, DistanceType > BranchSt
void computeLabels(int *indices, int indices_length, int *centers, int centers_length, int *labels, DistanceType &cost)
void serialize(Archive &ar)
HierarchicalClusteringIndexParams(int branching=32, flann_centers_init_t centers_init=FLANN_CENTERS_RANDOM, int trees=4, int leaf_max_size=100)
std::vector< Node * > tree_roots_
virtual bool full() const =0
void saveIndex(FILE *stream)
flann_algorithm_t getType() const
static void freeIndex(sqlite3 *db, Index *p)
std::vector< PointInfo > points
BaseClass * clone() const
virtual void addPoint(DistanceType dist, size_t index)=0
NNIndex< Distance > BaseClass
Distance::ElementType ElementType
void computeClustering(NodePtr node, int *indices, int indices_length)