44 #include <unordered_set>
68 template <
typename _T>
75 using DataDist = std::pair<const _T*, double>;
76 struct DataDistCompare
78 bool operator()(
const DataDist& d0,
const DataDist& d1)
80 return d0.second < d1.second;
83 using NearQueue = std::priority_queue<DataDist, std::vector<DataDist>, DataDistCompare>;
88 using NodeDist = std::pair<Node*, double>;
89 struct NodeDistCompare
91 bool operator()(
const NodeDist& n0,
const NodeDist& n1)
const
93 return (n0.second - n0.first->maxRadius_) > (n1.second - n1.first->maxRadius_);
96 using NodeQueue = std::priority_queue<NodeDist, std::vector<NodeDist>, NodeDistCompare>;
101 unsigned int maxNumPtsPerLeaf = 50,
unsigned int removedCacheSize = 500,
102 bool rebalancing =
false)
108 ,
rebuildSize_(rebalancing ? maxNumPtsPerLeaf * degree : std::numeric_limits<std::size_t>::max())
136 if (
rebuildSize_ != std::numeric_limits<std::size_t>::max())
145 void add(
const _T& data)
override
159 void add(
const std::vector<_T>& data)
override
163 else if (!data.empty())
166 for (
unsigned int i = 1; i < data.size(); ++i)
168 size_ += data.size();
193 const _T*
d = nbh_queue.top().first;
211 if (!nbh_queue.empty())
212 return *nbh_queue.top().first;
214 throw moveit::Exception(
"No elements found in nearest neighbors data structure");
218 void nearestK(
const _T& data, std::size_t k, std::vector<_T>& nbh)
const override
232 void nearestR(
const _T& data,
double radius, std::vector<_T>& nbh)
const override
243 std::size_t
size()
const override
248 void list(std::vector<_T>& data)
const override
251 data.reserve(
size());
264 out <<
"Elements marked for removal:\n";
265 for (
typename std::unordered_set<const _T*>::const_iterator it = gnat.
removed_.begin();
278 std::unordered_set<const _T*> tmp;
283 for (
typename std::unordered_set<const _T*>::iterator it = tmp.begin(); it != tmp.end(); ++it)
286 for (i = 0; i < lst.size(); ++i)
292 std::cout <<
"***** FAIL!! ******\n" << *
this <<
'\n';
293 for (
unsigned int j = 0; j < lst.size(); ++j)
294 std::cout << lst[j] <<
'\t';
297 assert(i != lst.size());
303 if (lst.size() !=
size_)
304 std::cout <<
"#########################################\n" << *
this <<
'\n';
305 assert(lst.size() ==
size_);
326 NodeQueue node_queue;
330 tree_->
nearestK(*
this, data, k, nbhQueue, node_queue, is_pivot);
331 while (!node_queue.empty())
333 dist = nbhQueue.top().second;
334 node_dist = node_queue.top();
336 if (nbhQueue.size() == k && (node_dist.second > node_dist.first->maxRadius_ + dist ||
337 node_dist.second < node_dist.first->minRadius_ - dist))
339 node_dist.first->nearestK(*
this, data, k, nbhQueue, node_queue, is_pivot);
346 double dist = radius;
347 NodeQueue node_queue;
352 while (!node_queue.empty())
354 node_dist = node_queue.top();
356 if (node_dist.second > node_dist.first->maxRadius_ + dist || node_dist.second < node_dist.first->minRadius_ - dist)
358 node_dist.first->nearestR(*
this, data, radius, nbhQueue, node_queue);
365 typename std::vector<_T>::reverse_iterator it;
366 nbh.resize(nbhQueue.size());
367 for (it = nbh.rbegin(); it != nbh.rend(); it++, nbhQueue.pop())
368 *it = *nbhQueue.top().first;
377 Node(
int degree,
int capacity, _T pivot)
379 ,
pivot_(std::move(pivot))
380 ,
minRadius_(std::numeric_limits<double>::infinity())
386 data_.reserve(capacity + 1);
391 for (
unsigned int i = 0; i <
children_.size(); ++i)
411 activity_ = std::max(-32, activity_ - 1);
429 data_.push_back(data);
446 std::vector<double> dist(
children_.size());
450 for (
unsigned int i = 1; i <
children_.size(); ++i)
456 for (
unsigned int i = 0; i <
children_.size(); ++i)
458 children_[min_ind]->updateRadius(min_dist);
465 unsigned int sz =
data_.size();
474 std::vector<unsigned int> pivots;
478 for (
unsigned int& pivot : pivots)
481 for (
unsigned int j = 0; j <
data_.size(); ++j)
484 for (
unsigned int i = 1; i <
degree_; ++i)
485 if (dists(j, i) < dists(j, k))
493 for (
unsigned int i = 0; i <
degree_; ++i)
497 for (
unsigned int i = 0; i <
degree_; ++i)
511 for (
unsigned int i = 0; i <
degree_; ++i)
517 bool insertNeighborK(NearQueue& nbh, std::size_t k,
const _T& data,
const _T& key,
double dist)
const
521 nbh.push(std::make_pair(&data, dist));
524 if (dist < nbh.top().second || (dist < std::numeric_limits<double>::epsilon() && data == key))
527 nbh.push(std::make_pair(&data, dist));
538 void nearestK(
const GNAT& gnat,
const _T& data, std::size_t k, NearQueue& nbh, NodeQueue& nodeQueue,
541 for (
unsigned int i = 0; i <
data_.size(); ++i)
551 std::vector<double> dist_to_pivot(
children_.size());
552 std::vector<int> permutation(
children_.size());
553 for (
unsigned int i = 0; i < permutation.size(); ++i)
555 std::random_shuffle(permutation.begin(), permutation.end());
557 for (
unsigned int i = 0; i <
children_.size(); ++i)
558 if (permutation[i] >= 0)
561 dist_to_pivot[permutation[i]] = gnat.
distFun_(data, child->
pivot_);
566 dist = nbh.top().second;
567 for (
unsigned int j = 0; j <
children_.size(); ++j)
568 if (permutation[j] >= 0 && i != j &&
569 (dist_to_pivot[permutation[i]] - dist > child->
maxRange_[permutation[j]] ||
570 dist_to_pivot[permutation[i]] + dist < child->
minRange_[permutation[j]]))
575 dist = nbh.top().second;
576 for (
unsigned int i = 0; i <
children_.size(); ++i)
577 if (permutation[i] >= 0)
580 if (nbh.size() < k || (dist_to_pivot[permutation[i]] - dist <= child->
maxRadius_ &&
581 dist_to_pivot[permutation[i]] + dist >= child->
minRadius_))
582 nodeQueue.push(std::make_pair(child, dist_to_pivot[permutation[i]]));
590 nbh.push(std::make_pair(&data, dist));
595 void nearestR(
const GNAT& gnat,
const _T& data,
double r, NearQueue& nbh, NodeQueue& nodeQueue)
const
599 for (
unsigned int i = 0; i <
data_.size(); ++i)
605 std::vector<double> dist_to_pivot(
children_.size());
606 std::vector<int> permutation(
children_.size());
607 for (
unsigned int i = 0; i < permutation.size(); ++i)
609 std::random_shuffle(permutation.begin(), permutation.end());
611 for (
unsigned int i = 0; i <
children_.size(); ++i)
612 if (permutation[i] >= 0)
617 for (
unsigned int j = 0; j <
children_.size(); ++j)
618 if (permutation[j] >= 0 && i != j &&
619 (dist_to_pivot[i] - dist > child->
maxRange_[permutation[j]] ||
620 dist_to_pivot[i] + dist < child->
minRange_[permutation[j]]))
624 for (
unsigned int i = 0; i <
children_.size(); ++i)
625 if (permutation[i] >= 0)
628 if (dist_to_pivot[i] - dist <= child->
maxRadius_ && dist_to_pivot[i] + dist >= child->
minRadius_)
629 nodeQueue.push(std::make_pair(child, dist_to_pivot[i]));
634 void list(
const GNAT& gnat, std::vector<_T>& data)
const
638 for (
unsigned int i = 0; i <
data_.size(); ++i)
640 data.push_back(
data_[i]);
641 for (
unsigned int i = 0; i <
children_.size(); ++i)
647 out <<
"\ndegree:\t" << node.
degree_;
650 out <<
"\nminRange:\t";
651 for (
unsigned int i = 0; i < node.
minRange_.size(); ++i)
653 out <<
"\nmaxRange: ";
654 for (
unsigned int i = 0; i < node.
maxRange_.size(); ++i)
656 out <<
"\npivot:\t" << node.
pivot_;
658 for (
unsigned int i = 0; i < node.
data_.size(); ++i)
659 out << node.
data_[i] <<
'\t';
660 out <<
"\nthis:\t" << &node;
661 out <<
"\nchildren:\n";
662 for (
unsigned int i = 0; i < node.
children_.size(); ++i)
665 for (
unsigned int i = 0; i < node.
children_.size(); ++i)
An instance of this class can be used to greedily select a given number of representatives from a set...
Eigen::MatrixXd Matrix
A matrix type for storing distances between points and centers.
bool insertNeighborK(NearQueue &nbh, std::size_t k, const _T &data, const _T &key, double dist) const
std::vector< double > maxRange_
void nearestR(const GNAT &gnat, const _T &data, double r, NearQueue &nbh, NodeQueue &nodeQueue) const
void updateRadius(double dist)
void list(const GNAT &gnat, std::vector< _T > &data) const
void updateRange(unsigned int i, double dist)
Node(int degree, int capacity, _T pivot)
friend std::ostream & operator<<(std::ostream &out, const Node &node)
std::vector< Node * > children_
bool needToSplit(const GNAT &gnat) const
std::vector< double > minRange_
void insertNeighborR(NearQueue &nbh, double r, const _T &data, double dist) const
void add(GNAT &gnat, const _T &data)
void nearestK(const GNAT &gnat, const _T &data, std::size_t k, NearQueue &nbh, NodeQueue &nodeQueue, bool &isPivot) const
Geometric Near-neighbor Access Tree (GNAT), a data structure for nearest neighbor search.
friend std::ostream & operator<<(std::ostream &out, const NearestNeighborsGNAT< _T > &gnat)
std::size_t removedCacheSize_
std::size_t size() const override
Get the number of elements in the datastructure.
void list(std::vector< _T > &data) const override
Get all the elements in the datastructure.
~NearestNeighborsGNAT() override
void setDistanceFunction(const typename NearestNeighbors< _T >::DistanceFunction &distFun) override
void rebuildDataStructure()
bool remove(const _T &data) override
Remove an element from the datastructure.
void nearestR(const _T &data, double radius, std::vector< _T > &nbh) const override
Get the nearest neighbors of a point, within a specified radius.
void add(const _T &data) override
Add an element to the datastructure.
void clear() override
Clear the datastructure.
void postprocessNearest(NearQueue &nbhQueue, std::vector< _T > &nbh) const
unsigned int maxNumPtsPerLeaf_
void nearestRInternal(const _T &data, double radius, NearQueue &nbhQueue) const
std::unordered_set< const _T * > removed_
GreedyKCenters< _T > pivotSelector_
NearestNeighborsGNAT(unsigned int degree=8, unsigned int minDegree=4, unsigned int maxDegree=12, unsigned int maxNumPtsPerLeaf=50, unsigned int removedCacheSize=500, bool rebalancing=false)
void add(const std::vector< _T > &data) override
Add a vector of points.
bool reportsSortedResults() const override
Return true if the solutions reported by this data structure are sorted, when calling nearestK / near...
bool nearestKInternal(const _T &data, std::size_t k, NearQueue &nbhQueue) const
void nearestK(const _T &data, std::size_t k, std::vector< _T > &nbh) const override
Get the k-nearest neighbors of a point.
_T nearest(const _T &data) const override
Get the nearest neighbor of a point.
bool isRemoved(const _T &data) const
Abstract representation of a container that can perform nearest neighbors queries.
virtual void add(const _T &data)=0
Add an element to the datastructure.
std::function< double(const _T &, const _T &)> DistanceFunction
The definition of a distance function.
virtual void setDistanceFunction(const DistanceFunction &distFun)
Set the distance function to use.
DistanceFunction distFun_
The used distance function.
This may be thrown if unrecoverable errors occur.