Removed backup files
This commit is contained in:
@@ -1,214 +0,0 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: ball_pivoter.h
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 04/28/2007 04:15:36 PM EDT
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Nikolaos Vasiloglou (NV), nvasil@ieee.org
|
||||
* Company: Georgia Tech Fastlab-ESP Lab
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
#ifdef BALL_PIVOTER_H_
|
||||
#define BALL_PIVOTER_H_
|
||||
|
||||
#include "loki/Typelist.h"
|
||||
#include "fastlib/fastlib.h"
|
||||
#include "dataset/binary_dataset.h"
|
||||
#include "hyper_ball.h"
|
||||
|
||||
template<typename TYPELIST, bool diagnostic>
|
||||
class BallPivoter {
|
||||
public:
|
||||
typedef Loki::TL::TypeAt<TYPELIST, 0>::Result Precision_t;
|
||||
typedef Loki::TL::TypeAt<TYPELIST, 1>::Result Allocator_t;
|
||||
typedef Loki::TL::TypeAt<TYPELIST, 2>::Result Metric_t;
|
||||
typedef HyperBall<TYPELIST, diagnostic> HyperBall_t;
|
||||
FORBID_COPY(HyperBallPivoter)
|
||||
struct PivotInfo {
|
||||
public:
|
||||
void Init(index_t start, index_t num_of_points, HyperBall_t &box) {
|
||||
box_.Copy(box_);
|
||||
start_=start;
|
||||
num_of_points_=num_of_points;
|
||||
}
|
||||
HyperBall_t box_;
|
||||
Loki::NullType statistics_;
|
||||
index_t start_;
|
||||
index_t num_of_points_;
|
||||
};
|
||||
Init(BinaryDataset<Precision_t> *data) {
|
||||
data_=data;
|
||||
}
|
||||
|
||||
pair<PivotInfo*, PivotInfo*> operator()(PivotInfo *pivot) {
|
||||
index_t left_start = pivot->start_;
|
||||
index_t right_start = pivot->start_ + pivot->num_of_points_-1;
|
||||
int32 dimension = data_->get_dimension();
|
||||
Array_t pivot_left = pivot->box_.get_pivot_left();
|
||||
Array_t pivot_right = pivot->box_.get_pivot_right();
|
||||
Precision_t *point_left = data->At(left_start);
|
||||
Precision_t *point_right = data->At(right_start);
|
||||
index_t left_points=0;
|
||||
index_t right_points=0;
|
||||
HyperBall_t ball_left, ball_right;
|
||||
ball_left.Init(dimension);
|
||||
ball_right.Init(dimension);
|
||||
|
||||
while (true) {
|
||||
while (left_points < pivot->num_of_points_ &&
|
||||
IsInLeftPivot(point_left, ball_left, ball_right, dimension)) {
|
||||
UpdateHyperBall(point_left, ball_left);
|
||||
left_points++;
|
||||
point_left = data->At(left_start+left_points);
|
||||
}
|
||||
if (point_left > point_right || left_points == pivot->num_of_points_) {
|
||||
break;
|
||||
}
|
||||
while (right_points < pivot->num_of_points_ &&
|
||||
!IsInLeftPivot(point_right, ball_left, ball_right, dimension)) {
|
||||
UpdateHyperBall(point_right, ball_right);
|
||||
right_points++;
|
||||
point_right = data->At(right_start - right_points);
|
||||
}
|
||||
if (point_left > point_right || right_points == pivot->num_of_points_) {
|
||||
break;
|
||||
}
|
||||
data->Swap(left_start+left_points, right_start - right_points);
|
||||
}
|
||||
DEBUG_ASSERT(left_points>0);
|
||||
DEBUG_ASSERT(right_points>0);
|
||||
DEBUG_ASSERT(left_points+right_points == right_start - left_start+1);
|
||||
NormalizeHyperBall(ball_left, left_points);
|
||||
NormalizeHyperBall(ball_right, right_points);
|
||||
FindPivotPoints(data, ball_left, left_start, left_points);
|
||||
FindPivotPoints(data, ball_right, left_start+left_points, right_points);
|
||||
|
||||
PivotInfo* node_pv_left = new PivotInfo();
|
||||
node_pv_left->Init(left_start, left_points, ball_left);
|
||||
PivotInfo* node_pv_right = new PivotInfo();
|
||||
node_pv_right->Init(left_start+left_points, right_points, ball_right);
|
||||
|
||||
return make_pair(node_pv_left, node_pv_right);
|
||||
|
||||
}
|
||||
|
||||
PivotInfo *operator()(index_t num_of_points) {
|
||||
// make the parent
|
||||
HyperBall_t ball;
|
||||
ball.Init(data_->get_dimension());
|
||||
for(index_t i=0; i<num_of_points; i++) {
|
||||
UpdateHyperBall(data->At(i), ball);
|
||||
}
|
||||
NormalizeHyperBall(ball, num_of_points);
|
||||
FindPivotPoints(ball, 0, num_of_points);
|
||||
PivotInfo *pv = new PivoInfo();
|
||||
pv->Init(0, num_of_points, ball);
|
||||
return pv;
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
BinaryDataset<Precision_t> *data_;
|
||||
void FindPivotPoints(HyperBall_t &ball,
|
||||
index_t start,
|
||||
index_t num_of_points) {
|
||||
DEBUG_ASSERT(num_of_points>0);
|
||||
Precision_t radious=0;
|
||||
Precision_t max_distance=0;
|
||||
index_t furthest_point_index = 0;
|
||||
int32 dimension = data->get_dimension();
|
||||
index_t random_index = index_t(num_of_points*1.0
|
||||
*rand()/RAND_MAX)+start;
|
||||
for(index_t i=start; i< start+num_of_points; i++) {
|
||||
Precision_t distance1 = Metric_t::Distance(pivot.center_,
|
||||
data->At(i), dimension);
|
||||
Precision_t distance = Metric_t::Distance(data->At(random_index),
|
||||
data->At(i), dimension);
|
||||
if (distance1 > radious) {
|
||||
radious = distance1;
|
||||
}
|
||||
if (distance>max_distance) {
|
||||
furthest_point_index=i;
|
||||
max_distance=distance;
|
||||
}
|
||||
}
|
||||
ball.set_radious(radious);
|
||||
ball.get_pivot_left().Copy(data->At(furthest_point_index), dimension);
|
||||
max_distance = 0;
|
||||
|
||||
for(index_t i=start; i< start+num_of_points; i++) {
|
||||
Precision_t distance = Metric_t::Distance(pivot.left_,
|
||||
data->At(i),
|
||||
dimension);
|
||||
if (distance > max_distance) {
|
||||
furthest_point_index = i;
|
||||
max_distance=distance;
|
||||
}
|
||||
}
|
||||
ball.get_pivot_right().Copy(data->At(furthest_point_index), dimension);
|
||||
DEBUG_ASSERT(Metric_t::Distance(pivot.left_, pivot.right_, dimension)>0);
|
||||
|
||||
}
|
||||
|
||||
template<typename POINTTYPE>
|
||||
void UpdateHyperBall(POINTTYPE point,
|
||||
HyperBall_T &ball) {
|
||||
Metric_t::Addition(ball.get_center(), ball.get_center(),
|
||||
point, data.get_dimension());
|
||||
}
|
||||
|
||||
__TEMPLATE__
|
||||
void __PivotPolicy__::NormalizeHyperBall(HyperBall_t &ball,
|
||||
index_t num_of_points) {
|
||||
Metric_t::Scale(ball.get_center(), ball.get_center(),
|
||||
1.0/num_of_points, data->get_dimension());
|
||||
|
||||
}
|
||||
|
||||
template<typename POINTTYPE>
|
||||
pair<Array_t, Precision_t> FindFurthestPoint(POINTTYPE point,
|
||||
index_t start,
|
||||
index_t num_of_points) {
|
||||
Precision_t radious=0;
|
||||
index_t furthest_point_index;
|
||||
Array_t furthest_point(dimension);
|
||||
for(index_t i=start; i<start+num_of_points; i++) {
|
||||
Precision_t distance = Metric_t::Distance(point, data->At(i), dimension);
|
||||
if (distance > radious) {
|
||||
radious = distance;
|
||||
furthest_point_index = i;
|
||||
}
|
||||
}
|
||||
furthest_point.DeepCopy(data->At(furthest_point_index), dimension);
|
||||
return make_pair(furthest_point, radious);
|
||||
}
|
||||
|
||||
__TEMPLATE__
|
||||
template<typename POINTTYPE>
|
||||
bool __PivotPolicy__::IsInLeftPivot(Precision_t *point, POINTTYPE left,
|
||||
POINTTYPE right,
|
||||
int32 dimension) {
|
||||
Precision_t left_distance = Metric_t::Distance(point, left, dimension);
|
||||
Precision_t right_distance = Metric_t::Distance(point, right, dimension);
|
||||
if (left_distance < right_distance) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // BALL_PIVOTER
|
||||
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: tree.h
|
||||
*
|
||||
* Description: A generic multidimensional binary tree. Currently tested under
|
||||
* kd-nodes and ball-nodes
|
||||
*
|
||||
* Version: 2.0
|
||||
* Created: 02/09/2007 08:25:15 PM EST
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Nikolaos Vasiloglou (NV), nvasil@ieee.org
|
||||
* Company: This material is property of Georgia Tech Fastlab-ESP Lab,
|
||||
* and it is not for distribution
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef BINARY_TREE_H_
|
||||
#define BINARY_TREE_H_
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include "fastlib/fastlib.h"
|
||||
#include "node.h"
|
||||
#include "show_progress.h"
|
||||
using namespace std;
|
||||
template<typename TYPELIST, bool diagnostic>
|
||||
class BinaryTree {
|
||||
public:
|
||||
typedef typename TYPELIST::Precision_t Precision_t;
|
||||
typedef typename TYPELIST::Allocator_t Allocator_t;
|
||||
typedef typename TYPELIST::Metric_t Metric_t;
|
||||
typedef typename TYPELIST::BoundingBox_t BoundingBox_t;
|
||||
typedef typename TYPELIST::NodeCachedStatistics_t NodeCachedStatistics_t;
|
||||
typedef typename TYPELIST::PointIdDiscriminator_t PointIdDiscriminator_t;
|
||||
typedef typename TYPELIST::Pivot_t Pivot_t;
|
||||
typedef typename Allocator_t::template ArrayPtr<Precision_t> Array_t;
|
||||
typedef Node<TYPELIST, diagnostic> Node_t;
|
||||
typedef typename Allocator_t::template Ptr<Node_t> NodePtr_t;
|
||||
typedef typename Allocator_t::template Ptr<NodePtr_t> NodePtrPtr_t;
|
||||
typedef Point<Precision_t, Allocator_t> Point_t;
|
||||
typedef typename Node_t::NNResult Result_t;
|
||||
typedef BinaryTree<TYPELIST, diagnostic> BinaryTree_t;
|
||||
typedef typename Pivot_t::PivotInfo PivotInfo_t;
|
||||
// For testing purposes only
|
||||
template<typename, bool >friend class BinaryTreeTest;
|
||||
|
||||
class OutPutAllocator {
|
||||
public:
|
||||
OutPutAllocator() {
|
||||
num_=0;
|
||||
}
|
||||
void set_ptr(Result_t *ptr) {
|
||||
ptr_=ptr;
|
||||
}
|
||||
Result_t *get_ptr() {
|
||||
return ptr_;
|
||||
}
|
||||
Result_t *Allocate(int32 num_of_points, int32 knns) {
|
||||
Result_t *result=ptr_+num_;
|
||||
num_+=knns*num_of_points;
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
Result_t *ptr_;
|
||||
index_t num_;
|
||||
};
|
||||
BinaryTree();
|
||||
~BinaryTree();
|
||||
void Init(BinaryDataset<Precision_t> *data);
|
||||
void Destruct() {}
|
||||
// Call this function to build Depth first a tree
|
||||
void BuildDepthFirst();
|
||||
void BuildDepthFirst(NodePtr_t &ptr, PivotInfo_t *pivot);
|
||||
void BuildBreadthFirst();
|
||||
void BuildBreadthFirst(
|
||||
list<pair<NodePtrPtr_t, PivotInfo_t *> > &fifo);
|
||||
// Builds tree k depth first. It builds all the subtrees depth first up to k level
|
||||
void BuildKDepthFirst();
|
||||
template<typename POINTTYPE, typename NEIGHBORTYPE>
|
||||
void NearestNeighbor(POINTTYPE test_point,
|
||||
vector<pair<Precision_t, Point_t> > *nearest_point,
|
||||
NEIGHBORTYPE range);
|
||||
|
||||
// This is the core function doing the recursion, Use that only if you want
|
||||
// to start the search from a particular node and not the parent
|
||||
template<typename POINTTYPE, typename NEIGHBORTYPE>
|
||||
void NearestNeighbor(NodePtr_t ptr,
|
||||
POINTTYPE &test_point,
|
||||
vector<pair<Precision_t, Point_t> > *nearest_point,
|
||||
NEIGHBORTYPE range,
|
||||
bool &found);
|
||||
|
||||
// This is the duall tree nearest neighbors method, again it works
|
||||
// for all cases k nearest/ range nearest
|
||||
template<typename NEIGHBORTYPE>
|
||||
void AllNearestNeighbors(NodePtr_t query,
|
||||
NEIGHBORTYPE range);
|
||||
template<typename NEIGHBORTYPE>
|
||||
void AllNearestNeighbors(NodePtr_t query,
|
||||
NodePtr_t reference,
|
||||
NEIGHBORTYPE range,
|
||||
Precision_t distance);
|
||||
void InitAllKNearestNeighborOutput(string file, int32 knns);
|
||||
void CloseAllKNearestNeighborOutput(int32 knns);
|
||||
void InitAllKNearestNeighborOutput(NodePtr_t ptr,
|
||||
int32 knns);
|
||||
void InitAllRangeNearestNeighborOutput(string file);
|
||||
void InitAllRangeNearestNeighborOutput(NodePtr_t ptr,
|
||||
FILE *fp);
|
||||
void CloseAllRangeNearestNeighborOutput();
|
||||
|
||||
// Print the tree depth first
|
||||
void Print();
|
||||
void RecursivePrint(NodePtr_t ptr);
|
||||
// Resets the counters of the tree that keep the statistics of search
|
||||
void ResetCounters() {
|
||||
computations_.Reset();
|
||||
}
|
||||
string Statistics();
|
||||
string Computations();
|
||||
void set_log_file(const string &log_file);
|
||||
int32 get_current_level() {
|
||||
return current_level_;
|
||||
};
|
||||
uint64 get_num_of_points(){
|
||||
return num_of_points_;
|
||||
}
|
||||
NodePtr_t get_parent() {
|
||||
return parent_;
|
||||
}
|
||||
void set_discriminator(PointIdDiscriminator_t *disc) {
|
||||
discriminator_.reset(disc);
|
||||
}
|
||||
void set_max_points_on_leaf(index_t max_points_on_leaf) {
|
||||
max_points_on_leaf_=max_points_on_leaf;
|
||||
}
|
||||
index_t get_max_points_on_leaf() {
|
||||
return max_points_on_leaf_;
|
||||
}
|
||||
private:
|
||||
// Maximum number of points on a leaf
|
||||
index_t max_points_on_leaf_;
|
||||
// Parent/Root
|
||||
NodePtr_t parent_;
|
||||
// Source of data
|
||||
BinaryDataset<Precision_t> *data_;
|
||||
// Total number of points on the tree
|
||||
index_t num_of_points_;
|
||||
// Number of Leafs on the tree
|
||||
index_t num_of_leafs_;
|
||||
// Number of nodes (incuding leafs)
|
||||
index_t node_id_;
|
||||
// Current level of tree while we build it
|
||||
index_t current_level_;
|
||||
// Maximum depth of the tree
|
||||
index_t max_depth_;
|
||||
// Minimum depth of the tree
|
||||
index_t min_depth_;
|
||||
// Dimensionality of points
|
||||
int32 dimension_;
|
||||
// Total number of points visited during search
|
||||
index_t total_nodes_visited_;
|
||||
// Structure for keeping statistics on the comparisons and distances computed
|
||||
// during search
|
||||
ComputationsCounter<diagnostic> computations_;
|
||||
// total number of nodes visited
|
||||
index_t total_points_visited_;
|
||||
// used for visualization of progress during tree build
|
||||
ShowProgress progress_;
|
||||
bool log_progress_;
|
||||
// Output file for All nearest neighbors
|
||||
OutPutAllocator all_nn_out_;
|
||||
FILE *log_file_ptr_;
|
||||
string log_file_;
|
||||
// This is usefull for our timit experiments
|
||||
PointIdDiscriminator_t discriminator_;
|
||||
// Does all the partitioning for the tree
|
||||
Pivot_t pivoter_;
|
||||
};
|
||||
#include "binary_tree_impl.h"
|
||||
#endif /*BINARY_TREE_H_*/
|
||||
@@ -1,525 +0,0 @@
|
||||
#ifndef BINARY_TREE_IMPL_H_
|
||||
#define BINARY_TREE_IMPL_H_
|
||||
|
||||
#define TEMPLATE__ \
|
||||
template<typename TYPELIST, bool diagnostic>
|
||||
#define TREE__ BinaryTree<TYPELIST, diagnostic>
|
||||
|
||||
// Straight forward implemantation of the algorithms as described in Andrew Moore's
|
||||
// paper. For more information regarding traits of nearest neighbors look at
|
||||
// traits_nearest_neighbor.h file
|
||||
|
||||
TEMPLATE__
|
||||
void TREE__::Init(BinaryDataset<Precision_t> *data) {
|
||||
data_ = data;
|
||||
dimension_ = data->get_dimension();
|
||||
num_of_points_ = data->get_num_of_points();
|
||||
node_id_=0;
|
||||
num_of_leafs_=0;
|
||||
current_level_=0;
|
||||
max_depth_ = 0;
|
||||
min_depth_ = numeric_limits<index_t>::max();
|
||||
max_points_on_leaf_ = 30;
|
||||
log_progress_=true;
|
||||
pivoter_.Init(data_);
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
TREE__::~BinaryTree(){
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void TREE__::BuildBreadthFirst() {
|
||||
|
||||
progress_.Reset();
|
||||
total_points_visited_ = 0;
|
||||
list<pair<NodePtrPtr_t, PivotInfo_t *> > fifo;
|
||||
PivotInfo_t *pivot = pivoter_(num_of_points_);
|
||||
parent_.Reset(new Node_t());
|
||||
parent_->Init(pivot->box_,
|
||||
pivot->statistics_,
|
||||
node_id_,
|
||||
pivot->num_of_points_);
|
||||
node_id_++;
|
||||
pair<PivotInfo_t*, PivotInfo_t*> pivot_pair;
|
||||
pivot_pair = pivoter_(pivot);
|
||||
delete pivot;
|
||||
|
||||
fifo.push_front(make_pair(parent_->get_left().Reference(), pivot_pair.first));
|
||||
fifo.push_front(make_pair(parent_->get_right().Reference(), pivot_pair.second));
|
||||
current_level_ =1;
|
||||
BuildBreadthFirst(fifo);
|
||||
if (log_progress_==true) {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void TREE__::BuildBreadthFirst(
|
||||
list<pair<typename TREE__::NodePtrPtr_t,
|
||||
typename TREE__::PivotInfo_t *> > &fifo) {
|
||||
|
||||
pair<PivotInfo_t*, PivotInfo_t*> pivot_pair;
|
||||
while (!fifo.empty()) {
|
||||
pair<NodePtrPtr_t, PivotInfo_t*> fifo_pair;
|
||||
fifo_pair = fifo.back();
|
||||
fifo.pop_back();
|
||||
if (fifo_pair.second->num_of_points_ > max_points_on_leaf_) {
|
||||
(*fifo_pair.first).Reset(new Node_t());
|
||||
(*fifo_pair.first)->Init(fifo_pair.second->box_,
|
||||
fifo_pair.second->statistics_,
|
||||
node_id_,
|
||||
fifo_pair.second->num_of_points_);
|
||||
|
||||
node_id_++;
|
||||
pivot_pair = pivoter_(fifo_pair.second);
|
||||
delete fifo_pair.second;
|
||||
fifo.push_front(make_pair((*fifo_pair.first)->get_left().Reference(),
|
||||
pivot_pair.first));
|
||||
fifo.push_front(make_pair((*fifo_pair.first)->get_right().Reference(),
|
||||
pivot_pair.second));
|
||||
} else {
|
||||
if (log_progress_==true) {
|
||||
total_points_visited_ += fifo_pair.second->num_of_points_;
|
||||
progress_.Show(total_points_visited_, get_num_of_points());
|
||||
}
|
||||
(*fifo_pair.first).Reset(new Node_t());
|
||||
(*fifo_pair.first)->Init(fifo_pair.second->box_,
|
||||
fifo_pair.second->statistics_,
|
||||
node_id_,
|
||||
fifo_pair.second->start_,
|
||||
fifo_pair.second->num_of_points_,
|
||||
dimension_,
|
||||
data_);
|
||||
|
||||
num_of_leafs_++;
|
||||
node_id_++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void TREE__::BuildDepthFirst() {
|
||||
total_points_visited_ = 0;
|
||||
min_depth_=numeric_limits<index_t>::max();
|
||||
max_depth_=0;
|
||||
current_level_=0;
|
||||
progress_.Reset();
|
||||
BuildDepthFirst(parent_, pivoter_(num_of_points_));
|
||||
if (log_progress_==true) {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void TREE__::BuildDepthFirst(typename TREE__::NodePtr_t &ptr,
|
||||
typename TREE__::PivotInfo_t *pivot_info) {
|
||||
|
||||
pair<PivotInfo_t *, PivotInfo_t *> pivot_pair;
|
||||
if (pivot_info->num_of_points_ > max_points_on_leaf_) {
|
||||
ptr.Reset(new Node_t());
|
||||
ptr->Init(pivot_info->box_,
|
||||
pivot_info->statistics_,
|
||||
node_id_,
|
||||
pivot_info->num_of_points_);
|
||||
node_id_++;
|
||||
pivot_pair = pivoter_(pivot_info);
|
||||
// There is a case where on all the points are the same
|
||||
// so pivoting returns 0 points on the left side
|
||||
// In that case we create a gigantic leaf
|
||||
if (pivot_pair.first->num_of_points_==0) {
|
||||
if (log_progress_==true) {
|
||||
total_points_visited_ +=pivot_pair.second->num_of_points_;
|
||||
progress_.Show(total_points_visited_, get_num_of_points());
|
||||
}
|
||||
if (current_level_ > max_depth_) {
|
||||
max_depth_=current_level_;
|
||||
}
|
||||
if (current_level_ < min_depth_) {
|
||||
min_depth_=current_level_;
|
||||
}
|
||||
ptr.Reset(new Node_t());
|
||||
ptr->Init(pivot_pair.second->box_,
|
||||
pivot_pair.second->statistics_,
|
||||
node_id_,
|
||||
pivot_pair.second->start_,
|
||||
pivot_pair.second->num_of_points_,
|
||||
dimension_,
|
||||
data_);
|
||||
|
||||
node_id_++;
|
||||
num_of_leafs_++;
|
||||
delete pivot_info;
|
||||
delete pivot_pair.first;
|
||||
delete pivot_pair.second;
|
||||
return;
|
||||
}
|
||||
delete pivot_info;
|
||||
current_level_++;
|
||||
BuildDepthFirst(ptr->get_left(), pivot_pair.first);
|
||||
BuildDepthFirst(ptr->get_right(), pivot_pair.second);
|
||||
current_level_--;
|
||||
} else {
|
||||
if (log_progress_==true) {
|
||||
total_points_visited_ += pivot_info->num_of_points_;
|
||||
progress_.Show(total_points_visited_, get_num_of_points());
|
||||
}
|
||||
if (current_level_ > max_depth_) {
|
||||
max_depth_=current_level_;
|
||||
}
|
||||
if (current_level_ < min_depth_) {
|
||||
min_depth_=current_level_;
|
||||
}
|
||||
ptr.Reset(new Node_t());
|
||||
ptr->Init(pivot_info->box_,
|
||||
pivot_info->statistics_,
|
||||
node_id_,
|
||||
pivot_info->start_,
|
||||
pivot_info->num_of_points_,
|
||||
dimension_,
|
||||
data_);
|
||||
|
||||
node_id_++;
|
||||
num_of_leafs_++;
|
||||
delete pivot_info;
|
||||
}
|
||||
}
|
||||
|
||||
// This function will return any of the nearest neighbors
|
||||
// k nearest, range nearest or just nearest
|
||||
TEMPLATE__
|
||||
template<typename POINTTYPE, typename NEIGHBORTYPE>
|
||||
void TREE__::NearestNeighbor(POINTTYPE test_point,
|
||||
vector<pair<typename TREE__::Precision_t,
|
||||
typename TREE__::Point_t> > *nearest_point,
|
||||
NEIGHBORTYPE range) {
|
||||
bool found = false;
|
||||
NearestNeighbor(parent_,
|
||||
test_point,
|
||||
nearest_point,
|
||||
range,
|
||||
found);
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
template<typename POINTTYPE, typename NEIGHBORTYPE>
|
||||
void TREE__::NearestNeighbor(NodePtr_t ptr,
|
||||
POINTTYPE &test_point,
|
||||
vector<pair<typename TREE__::Precision_t,
|
||||
typename TREE__::Point_t> > *nearest_point,
|
||||
NEIGHBORTYPE range,
|
||||
bool &found) {
|
||||
computations_.UpdateComparisons();
|
||||
Precision_t max_distance;
|
||||
if (Loki::TypeTraits<NEIGHBORTYPE>::isStdFloat==true) {
|
||||
max_distance=range;
|
||||
}
|
||||
if (!ptr->IsLeaf()){
|
||||
computations_.UpdateComparisons();
|
||||
pair<NodePtr_t, NodePtr_t> child_pair =
|
||||
ptr->ClosestChild(test_point, dimension_, computations_);
|
||||
|
||||
NearestNeighbor(child_pair.first, test_point, nearest_point,
|
||||
range, found);
|
||||
if (Loki::TypeTraits<NEIGHBORTYPE>::isStdFloat==false) {
|
||||
max_distance=nearest_point->back().first;
|
||||
}
|
||||
|
||||
if (child_pair.second->get_box().CrossesBoundaries(test_point,
|
||||
dimension_,
|
||||
max_distance,
|
||||
computations_)) {
|
||||
NearestNeighbor(child_pair.second,
|
||||
test_point,
|
||||
nearest_point,
|
||||
range, found);
|
||||
}
|
||||
|
||||
if (found == true) {
|
||||
return;
|
||||
} else {
|
||||
if (Loki::TypeTraits<NEIGHBORTYPE>::isStdFloat==false) {
|
||||
max_distance=nearest_point->back().first;
|
||||
}
|
||||
found = ptr->get_box().IsWithin(test_point,
|
||||
dimension_,
|
||||
max_distance,
|
||||
computations_)==0;
|
||||
if (found == true) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ptr->FindNearest(test_point, *nearest_point,
|
||||
range, dimension_,
|
||||
discriminator_,
|
||||
computations_);
|
||||
if (Loki::TypeTraits<NEIGHBORTYPE>::isStdFloat==false) {
|
||||
max_distance=nearest_point->back().first;
|
||||
}
|
||||
found = ptr->get_box().IsWithin(test_point, dimension_,
|
||||
max_distance,
|
||||
computations_);
|
||||
}
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
template<typename NEIGHBORTYPE>
|
||||
void TREE__::AllNearestNeighbors(typename TREE__::NodePtr_t query,
|
||||
NEIGHBORTYPE range) {
|
||||
ResetCounters();
|
||||
Precision_t distance = numeric_limits<Precision_t>::max();
|
||||
progress_.Reset();
|
||||
AllNearestNeighbors(query, parent_, range, distance);
|
||||
total_points_visited_=0;
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
template<typename NEIGHBORTYPE >
|
||||
void TREE__::AllNearestNeighbors(typename TREE__::NodePtr_t query,
|
||||
typename TREE__::NodePtr_t reference,
|
||||
NEIGHBORTYPE range,
|
||||
typename TREE__::Precision_t distance) {
|
||||
|
||||
if (distance > query->get_min_dist_so_far()) {
|
||||
return ;
|
||||
} else {
|
||||
if (query->IsLeaf() && reference->IsLeaf()) {
|
||||
Precision_t max_distance=numeric_limits<Precision_t>::max();
|
||||
reference->FindAllNearest(query,
|
||||
max_distance,
|
||||
range,
|
||||
dimension_,
|
||||
discriminator_,
|
||||
computations_);
|
||||
query->set_min_dist_so_far(max_distance);
|
||||
} else {
|
||||
if (query->IsLeaf() && !reference->IsLeaf()) {
|
||||
pair<pair<NodePtr_t, Precision_t>,
|
||||
pair<NodePtr_t, Precision_t> > closest_child;
|
||||
closest_child = query->ClosestNode(reference->get_left(),
|
||||
reference->get_right(),
|
||||
dimension_,
|
||||
computations_);
|
||||
AllNearestNeighbors(query,
|
||||
closest_child.first.first, // child
|
||||
range, // range
|
||||
closest_child.first.second // distance of query
|
||||
// from the reference child
|
||||
);
|
||||
AllNearestNeighbors(query, closest_child.second.first,
|
||||
range, closest_child.second.second);
|
||||
|
||||
} else {
|
||||
if (!query->IsLeaf() && reference->IsLeaf()) {
|
||||
pair<pair<NodePtr_t, Precision_t>,
|
||||
pair<NodePtr_t, Precision_t> > closest_child;
|
||||
closest_child = reference->ClosestNode(query->get_left(),
|
||||
query->get_right(),
|
||||
dimension_,
|
||||
computations_);
|
||||
|
||||
AllNearestNeighbors(closest_child.first.first,
|
||||
reference,
|
||||
range,
|
||||
closest_child.first.second);
|
||||
AllNearestNeighbors(closest_child.second.first,
|
||||
reference,
|
||||
range,
|
||||
closest_child.second.second);
|
||||
query->set_min_dist_so_far(
|
||||
std::min<Precision_t>(query->get_min_dist_so_far(),
|
||||
std::max<Precision_t>(query->get_left()->get_min_dist_so_far(),
|
||||
query->get_right()->get_min_dist_so_far())));
|
||||
} else {
|
||||
if (!query->IsLeaf() && !reference->IsLeaf()) {
|
||||
pair<pair<NodePtr_t, Precision_t>,
|
||||
pair<NodePtr_t, Precision_t> > closest_child;
|
||||
closest_child = query->get_left()->ClosestNode(
|
||||
reference->get_left(),
|
||||
reference->get_right(),
|
||||
dimension_,
|
||||
computations_);
|
||||
|
||||
AllNearestNeighbors(query->get_left(),
|
||||
closest_child.first.first,
|
||||
range,
|
||||
closest_child.first.second);
|
||||
AllNearestNeighbors(query->get_left(),
|
||||
closest_child.second.first,
|
||||
range,
|
||||
closest_child.second.second);
|
||||
closest_child = query->get_right()->ClosestNode(
|
||||
reference->get_left(),
|
||||
reference->get_right(),
|
||||
dimension_,
|
||||
computations_);
|
||||
AllNearestNeighbors(query->get_right(),
|
||||
closest_child.first.first,
|
||||
range,
|
||||
closest_child.first.second);
|
||||
AllNearestNeighbors(query->get_right(),
|
||||
closest_child.second.first,
|
||||
range,
|
||||
closest_child.second.second);
|
||||
query->set_min_dist_so_far(
|
||||
std::min<Precision_t>(query->get_min_dist_so_far(),
|
||||
std::max<Precision_t>(query->get_left()->get_min_dist_so_far(),
|
||||
query->get_right()->get_min_dist_so_far())));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void TREE__::InitAllKNearestNeighborOutput(string file,
|
||||
int32 knns) {
|
||||
FILE *fp=fopen(file.c_str(), "w");
|
||||
const int32 kChunk=8192;
|
||||
typename Node_t::NNResult *buffer;
|
||||
buffer=new typename Node_t::NNResult[kChunk*knns];
|
||||
for(index_t i=0; i<num_of_points_/kChunk; i++) {
|
||||
fwrite(buffer, sizeof(typename Node_t::NNResult),kChunk*knns, fp );
|
||||
}
|
||||
fwrite(buffer, sizeof(typename Node_t::NNResult),
|
||||
(num_of_points_%kChunk)*knns, fp );
|
||||
fclose(fp);
|
||||
delete []buffer;
|
||||
int fd=open(file.c_str(), O_RDWR);
|
||||
typename Node_t::NNResult *ptr =(typename Node_t::NNResult *)mmap(NULL,
|
||||
sizeof(typename Node_t::NNResult)*knns*num_of_points_,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (ptr==MAP_FAILED) {
|
||||
fprintf(stderr, "Unable to map file: %s", strerror(errno));
|
||||
assert(false);
|
||||
}
|
||||
close(fd);
|
||||
all_nn_out_.set_ptr(ptr);
|
||||
InitAllKNearestNeighborOutput(parent_, knns);
|
||||
}
|
||||
|
||||
|
||||
TEMPLATE__
|
||||
void TREE__::InitAllKNearestNeighborOutput(typename TREE__::NodePtr_t ptr,
|
||||
int32 knns) {
|
||||
if (ptr->IsLeaf()) {
|
||||
ptr->set_kneighbors(all_nn_out_.Allocate(ptr->get_num_of_points(), knns),
|
||||
knns);
|
||||
ptr->InitKNeighbors(knns);
|
||||
} else {
|
||||
InitAllKNearestNeighborOutput(ptr->get_left(), knns);
|
||||
InitAllKNearestNeighborOutput(ptr->get_right(), knns);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void TREE__::InitAllRangeNearestNeighborOutput(string file) {
|
||||
FILE *fp=fopen(file.c_str(), "w");
|
||||
if (fp==NULL) {
|
||||
FATAL("Cannot open %s, error: %s\n",
|
||||
file.c_str(),
|
||||
strerror(errno));
|
||||
}
|
||||
parent_->set_range_neighbors(fp);
|
||||
InitAllRangeNearestNeighborOutput(parent_, fp);
|
||||
}
|
||||
|
||||
|
||||
TEMPLATE__
|
||||
void TREE__::InitAllRangeNearestNeighborOutput(
|
||||
typename TREE__::NodePtr_t ptr,
|
||||
FILE *fp) {
|
||||
if (ptr->IsLeaf()) {
|
||||
ptr->set_range_neighbors(fp);
|
||||
} else {
|
||||
InitAllRangeNearestNeighborOutput(ptr->get_left(), fp);
|
||||
InitAllRangeNearestNeighborOutput(ptr->get_right(), fp);
|
||||
}
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void TREE__::CloseAllKNearestNeighborOutput(int32 knns) {
|
||||
if (munmap(all_nn_out_.get_ptr(),
|
||||
sizeof(typename Node_t::NNResult)*knns*num_of_points_)<0) {
|
||||
fprintf(stderr, "Failed to umap file: %s", strerror(errno));
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void TREE__::CloseAllRangeNearestNeighborOutput() {
|
||||
fclose(parent_->get_range_nn_fp());
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void TREE__::Print() {
|
||||
RecursivePrint(parent_);
|
||||
}
|
||||
|
||||
|
||||
TEMPLATE__
|
||||
void TREE__::RecursivePrint(typename TREE__::NodePtr_t ptr) {
|
||||
string str;
|
||||
if (ptr->IsLeaf()) {
|
||||
str = ptr->Print(dimension_);
|
||||
printf("%s\n", str.c_str());
|
||||
} else {
|
||||
str = ptr->Print(dimension_);
|
||||
printf("%s\n", str.c_str());
|
||||
RecursivePrint(ptr->get_left());
|
||||
RecursivePrint(ptr->get_right());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEMPLATE__
|
||||
string TREE__::Statistics() {
|
||||
char buff[4096];
|
||||
sprintf(buff, "Number of points : %llu,\n"
|
||||
"Number of dimensions : %i\n"
|
||||
"Number of nodes : %llu,\n"
|
||||
"Number of leafs : %llu,\n"
|
||||
"Max tree depth : %llu,\n"
|
||||
"Min tree depth : %llu,\n",
|
||||
(unsigned long long)num_of_points_,
|
||||
dimension_,
|
||||
(unsigned long long)node_id_,
|
||||
(unsigned long long)num_of_leafs_,
|
||||
(unsigned long long)max_depth_,
|
||||
(unsigned long long)min_depth_);
|
||||
return string(buff);
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
string TREE__::Computations() {
|
||||
char buff[4096];
|
||||
sprintf(buff,"number of comparisons: %llu\n"
|
||||
"number of distances: %llu\n",
|
||||
(unsigned long long)computations_.get_comparisons(),
|
||||
(unsigned long long)computations_.get_distances());
|
||||
return string(buff);
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void TREE__::set_log_file(const string &log_file) {
|
||||
if (log_file_ptr_ != stderr ) {
|
||||
if (fclose(log_file_ptr_)!= 0) {
|
||||
fprintf(stderr, "Cannot close file %s\n", log_file_.c_str());
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
log_file_ptr_ = fopen(log_file.c_str(), "wb");
|
||||
log_file_ = log_file;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#undef TREE__
|
||||
#undef TEMPLATE__
|
||||
#endif /*BINARY_TREE_IMPL_H_*/
|
||||
@@ -1,300 +0,0 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: binary_tree_unit.cc
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 04/27/2007 10:20:40 AM EDT
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Nikolaos Vasiloglou (NV), nvasil@ieee.org
|
||||
* Company: Georgia Tech Fastlab-ESP Lab
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <limits>
|
||||
#include "fastlib/fastlib.h"
|
||||
#include "u/nvasil/mmanager/memory_manager.h"
|
||||
#include "u/nvasil/test/test.h"
|
||||
#include "u/nvasil/dataset/binary_dataset.h"
|
||||
#include "tree_parameters_macro.h"
|
||||
#include "euclidean_metric.h"
|
||||
#include "null_statistics.h"
|
||||
#include "hyper_rectangle.h"
|
||||
#include "point_identity_discriminator.h"
|
||||
#include "kd_pivoter1.h"
|
||||
#include "binary_tree.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
template<typename TYPELIST, bool diagnostic>
|
||||
class BinaryTreeTest {
|
||||
public:
|
||||
typedef typename TYPELIST::Precision_t Precision_t;
|
||||
typedef typename TYPELIST::Allocator_t Allocator_t;
|
||||
typedef typename TYPELIST::Metric_t Metric_t;
|
||||
typedef typename TYPELIST::BoundingBox_t BoundingBox_t;
|
||||
typedef typename TYPELIST::NodeCachedStatistics_t NodeCachedStatistics_t;
|
||||
typedef typename TYPELIST::PointIdDiscriminator_t PointIdDiscriminator_t;
|
||||
typedef typename TYPELIST::Pivot_t Pivot_t;
|
||||
typedef Point<Precision_t, Allocator_t> Point_t;
|
||||
typedef BinaryTree<TYPELIST, diagnostic> BinaryTree_t;
|
||||
typedef typename BinaryTree_t::Node_t Node_t;
|
||||
BinaryTreeTest() {
|
||||
}
|
||||
void Init() {
|
||||
Allocator_t::allocator_ = new Allocator_t();
|
||||
Allocator_t::allocator_->Initialize();
|
||||
dimension_=2;
|
||||
num_of_points_=1000;
|
||||
data_file_="data";
|
||||
knns_=40;
|
||||
range_=0.2;
|
||||
result_file_="allnn";
|
||||
data_.Init(data_file_, num_of_points_, dimension_);
|
||||
for(index_t i=0; i<num_of_points_; i++) {
|
||||
for(index_t j=0; j<dimension_; j++) {
|
||||
data_.At(i,j)=Precision_t(rand())/RAND_MAX - 0.48;
|
||||
}
|
||||
data_.set_id(i,i);
|
||||
}
|
||||
tree_.Init(&data_);
|
||||
}
|
||||
void Destruct() {
|
||||
tree_.Destruct();
|
||||
data_.Destruct();
|
||||
unlink(data_file_.c_str());
|
||||
unlink(data_file_.append(".ind").c_str());
|
||||
unlink(result_file_.c_str());
|
||||
}
|
||||
void BuildDepthFirst(){
|
||||
printf("Testing BuildDepthFirst...\n");
|
||||
tree_.BuildDepthFirst();
|
||||
//tree_.Print();
|
||||
printf("%s\n", tree_.Statistics().c_str());
|
||||
}
|
||||
void BuildBreadthFirst() {
|
||||
printf("Testing BuildBreadthFirst...\n");
|
||||
tree_.BuildBreadthFirst();
|
||||
// tree_.Print();
|
||||
printf("%s\n", tree_.Statistics().c_str());
|
||||
}
|
||||
void kNearestNeighbor() {
|
||||
printf("Testing kNearestNeighbor...\n");
|
||||
tree_.BuildDepthFirst();
|
||||
//tree_.Print();
|
||||
vector<pair<Precision_t, Point_t> > nearest_tree;
|
||||
pair<Precision_t, index_t> nearest_naive[num_of_points_];
|
||||
for(index_t i=0; i<num_of_points_; i++) {
|
||||
nearest_tree.clear();
|
||||
tree_.NearestNeighbor(data_.get_point(i),
|
||||
&nearest_tree,
|
||||
knns_);
|
||||
Naive(i, nearest_naive);
|
||||
for(index_t j=0; j<knns_; j++) {
|
||||
TEST_DOUBLE_APPROX(nearest_naive[j+1].first,
|
||||
nearest_tree[j].first,
|
||||
numeric_limits<Precision_t>::epsilon());
|
||||
TEST_ASSERT(nearest_tree[j].second.get_id()==
|
||||
nearest_naive[j+1].second) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
void RangeNearestNeighbor() {
|
||||
printf("Testing RangeNearestNeighbor...\n");
|
||||
tree_.BuildBreadthFirst();
|
||||
//tree_.Print();
|
||||
vector<pair<Precision_t, Point_t> > nearest_tree;
|
||||
pair<Precision_t, index_t> nearest_naive[num_of_points_];
|
||||
for(index_t i=0; i<num_of_points_; i++) {
|
||||
nearest_tree.clear();
|
||||
tree_.NearestNeighbor(data_.get_point(i),
|
||||
&nearest_tree,
|
||||
range_);
|
||||
std::sort(nearest_tree.begin(), nearest_tree.end(),
|
||||
typename Node_t::PairComparator());
|
||||
Naive(i, nearest_naive);
|
||||
for(index_t j=0; j<(index_t)nearest_tree.size(); j++) {
|
||||
TEST_DOUBLE_APPROX(nearest_naive[j+1].first,
|
||||
nearest_tree[j].first,
|
||||
numeric_limits<Precision_t>::epsilon());
|
||||
TEST_ASSERT(nearest_tree[j].second.get_id()==
|
||||
nearest_naive[j+1].second) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
void AllKNearestNeighbors() {
|
||||
printf("Testing AllKNearestNeighbors...\n");
|
||||
tree_.BuildDepthFirst();
|
||||
// tree_.Print();
|
||||
tree_.InitAllKNearestNeighborOutput(result_file_,
|
||||
knns_);
|
||||
tree_.AllNearestNeighbors(tree_.parent_, knns_);
|
||||
tree_.CloseAllKNearestNeighborOutput(knns_);
|
||||
struct stat info;
|
||||
if (stat(result_file_.c_str(), &info)!=0) {
|
||||
FATAL("Error %s file %s\n",
|
||||
strerror(errno), data_file_.c_str());
|
||||
}
|
||||
uint64 map_size = info.st_size;
|
||||
|
||||
int fp=open(result_file_.c_str(), O_RDWR);
|
||||
typename Node_t::NNResult *res;
|
||||
res=(typename Node_t::NNResult *)mmap(NULL,
|
||||
map_size,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, fp,
|
||||
0);
|
||||
TEST_ASSERT(res!=MAP_FAILED);
|
||||
close(fp);
|
||||
std::sort(res, res+num_of_points_*knns_);
|
||||
pair<Precision_t, index_t> nearest_naive[num_of_points_];
|
||||
for(index_t i=0; i<num_of_points_; i++) {
|
||||
Naive(i, nearest_naive);
|
||||
for(index_t j=0; j<knns_; j++) {
|
||||
TEST_DOUBLE_APPROX(nearest_naive[j+1].first,
|
||||
res[data_.get_id(i)*knns_+j].distance_,
|
||||
numeric_limits<Precision_t>::epsilon());
|
||||
TEST_ASSERT(res[data_.get_id(i)*knns_+j].nearest_.get_id()==
|
||||
nearest_naive[j+1].second);
|
||||
}
|
||||
}
|
||||
munmap(res, map_size);
|
||||
}
|
||||
|
||||
void AllRangeNearestNeighbors() {
|
||||
printf("Testing AllRangeNearestNeighbors...\n");
|
||||
tree_.BuildBreadthFirst();
|
||||
//tree_.Print();
|
||||
tree_.InitAllRangeNearestNeighborOutput(result_file_);
|
||||
tree_.AllNearestNeighbors(tree_.parent_, range_);
|
||||
tree_.CloseAllRangeNearestNeighborOutput();
|
||||
struct stat info;
|
||||
if (stat(result_file_.c_str(), &info)!=0) {
|
||||
FATAL( "Error %s file %s\n",
|
||||
strerror(errno), data_file_.c_str());
|
||||
}
|
||||
uint64 map_size = info.st_size;
|
||||
|
||||
int fp=open(result_file_.c_str(), O_RDWR);
|
||||
typename Node_t::NNResult *res;
|
||||
res=(typename Node_t::NNResult *)mmap(NULL,
|
||||
map_size,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, fp,
|
||||
0);
|
||||
close(fp);
|
||||
TEST_ASSERT(res!=MAP_FAILED);
|
||||
std::sort(res, res+map_size/sizeof(typename Node_t::NNResult));
|
||||
pair<Precision_t, index_t> nearest_naive[num_of_points_];
|
||||
index_t i=0;
|
||||
while (i<num_of_points_) {
|
||||
Naive(i, nearest_naive);
|
||||
index_t j=0;
|
||||
while(res[j].point_id_<(index_t)data_.get_id(i)) {
|
||||
j++;
|
||||
}
|
||||
index_t k=1;
|
||||
while (nearest_naive[k].first<=range_) {
|
||||
TEST_DOUBLE_APPROX(nearest_naive[k].first,
|
||||
res[j].distance_,
|
||||
numeric_limits<Precision_t>::epsilon());
|
||||
j++;
|
||||
k++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
munmap(res, map_size);
|
||||
}
|
||||
|
||||
void TestAll() {
|
||||
Init();
|
||||
BuildDepthFirst();
|
||||
Destruct();
|
||||
Init();
|
||||
BuildBreadthFirst();
|
||||
Destruct();
|
||||
Init();
|
||||
kNearestNeighbor();
|
||||
Destruct();
|
||||
Init();
|
||||
RangeNearestNeighbor();
|
||||
Destruct();
|
||||
Init();
|
||||
AllKNearestNeighbors();
|
||||
Destruct();
|
||||
Init();
|
||||
AllRangeNearestNeighbors();
|
||||
Destruct();
|
||||
}
|
||||
|
||||
private:
|
||||
BinaryTree_t tree_;
|
||||
BinaryDataset<Precision_t> data_;
|
||||
string data_file_;
|
||||
string result_file_;
|
||||
int32 dimension_;
|
||||
index_t num_of_points_;
|
||||
index_t knns_;
|
||||
Precision_t range_;
|
||||
|
||||
void Naive(index_t query,
|
||||
pair<Precision_t, index_t> *result) {
|
||||
for(index_t i=0; i<num_of_points_; i++) {
|
||||
Precision_t dist=Metric_t::Distance(data_.At(i),
|
||||
data_.At(query),
|
||||
dimension_);
|
||||
result[i].first=dist;
|
||||
result[i].second=data_.get_id(i);
|
||||
}
|
||||
std::sort(result, result+num_of_points_);
|
||||
}
|
||||
|
||||
void Naive(Precision_t *query,
|
||||
pair<Precision_t, index_t> *result) {
|
||||
for(index_t i=0; i<num_of_points_; i++) {
|
||||
Precision_t dist=Metric_t::Distance(data_.At(i),
|
||||
query,
|
||||
dimension_);
|
||||
result[i].first=dist;
|
||||
result[i].second=data_.get_id(i);
|
||||
}
|
||||
std::sort(result, result+num_of_points_);
|
||||
}
|
||||
};
|
||||
|
||||
TREE_PARAMETERS(float32,
|
||||
MemoryManager<false>,
|
||||
EuclideanMetric,
|
||||
HyperRectangle,
|
||||
NullStatistics,
|
||||
SimpleDiscriminator,
|
||||
KdPivoter1,
|
||||
false)
|
||||
|
||||
/*struct BasicTypes {
|
||||
typedef float32 Precision_t;
|
||||
typedef MemoryManager<false> Allocator_t;
|
||||
typedef EuclideanMetric<float32> Metric_t;
|
||||
};
|
||||
struct Parameters {
|
||||
typedef float32 Precision_t;
|
||||
typedef MemoryManager<false> Allocator_t;
|
||||
typedef EuclideanMetric<float32> Metric_t;
|
||||
typedef HyperRectangle<BasicTypes, false> BoundingBox_t;
|
||||
typedef NullStatistics NodeCachedStatistics_t;
|
||||
typedef SimpleDiscriminator PointIdDiscriminator_t;
|
||||
typedef KdPivoter1<BasicTypes, false> Pivot_t;
|
||||
};
|
||||
*/
|
||||
typedef BinaryTreeTest<Parameters, false> BinaryTreeTest_t;
|
||||
int main(int argc, char *argv[]) {
|
||||
BinaryTreeTest_t test;
|
||||
test.TestAll();
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: metric.h
|
||||
*
|
||||
* Description: Definition of different metrics
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 02/11/2007 04:52:54 PM EST
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Nikolaos Vasiloglou (NV), nvasil@ieee.org
|
||||
* Company: Georgia Tech Fastlab-ESP Lab
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include "base/basic_types.h"
|
||||
template<typename PRECISION>
|
||||
class EuclideanMetric {
|
||||
public:
|
||||
template<typename POINTTYPE1, typename POINTTYPE2>
|
||||
static inline PRECISION Distance(POINTTYPE1 p1,
|
||||
POINTTYPE2 p2, int32 dimension) {
|
||||
// we need to do some type checking for the POINTTYPE
|
||||
PRECISION dist=0;
|
||||
for(int32 i=0; i<dimension; i++) {
|
||||
dist+=(p1[i]-p2[i])*(p1[i]-p2[i]);
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
|
||||
template<typename POINTTYPE1, typename POINTTYPE2, typename POINTTYPE3>
|
||||
static inline void Addition(POINTTYPE1 &result,
|
||||
POINTTYPE2 p1,
|
||||
POINTTYPE3 p2,
|
||||
int32 dimension) {
|
||||
for(int32 i=0; i<dimension; i++) {
|
||||
result[i] = p1[i]+p2[i];
|
||||
}
|
||||
}
|
||||
|
||||
template<typename POINTTYPE1, typename POINTTYPE2>
|
||||
static inline void Scale(POINTTYPE1 &result, POINTTYPE2 point,
|
||||
PRECISION scale_factor, int32 dimension) {
|
||||
for(int32 i=0; i<dimension; i++) {
|
||||
result[i]= point[i] * scale_factor;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: hyper_ball.h
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 02/11/2007 05:45:21 PM EST
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Nikolaos Vasiloglou (NV), nvasil@ieee.org
|
||||
* Company: Georgia Tech Fastlab-ESP Lab
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#ifndef HYPER_BALL_H_
|
||||
#define HYPER_BALL_H_
|
||||
#include <new>
|
||||
#include <math.h>
|
||||
#include <string>
|
||||
#include "loki/Typelist.h"
|
||||
#include "fastlib/fastlib.h"
|
||||
#include "computations_counter.h"
|
||||
|
||||
|
||||
template<typename TYPELIST, bool diagnostic>
|
||||
typename Precision_t, typename METRIC,
|
||||
Allocator_t, bool diagnostic>
|
||||
class HyperBall {
|
||||
public:
|
||||
typedef loki::TypeAt<TYPELIST, 0>::Result Precision_t;
|
||||
typedef loki::TypeAt<TYPELIST, 1>::Result Allocator_t;
|
||||
typedef loki::TypeAt<TYPELIST, 2>::Result Metric_t;
|
||||
typedef Allocator_t::template ArrayPtr<Precision_t> Array_t;
|
||||
typedef HyperBall<TYPELIST, diagnostic> HyperBall_t;
|
||||
friend class HyperBall<TYPELIST, diagnostic>;
|
||||
HyperBall();
|
||||
Init(int32 dimension);
|
||||
void Init(Array_t center, Precision_t radious,
|
||||
Array_t pivot_left, Array_t pivot_right);
|
||||
~HyperBall() {};
|
||||
static void *operator new(size_t size);
|
||||
static void operator delete(void *p);
|
||||
HyperBall_t &operator=(const HyperBall_t & other);
|
||||
void Copy(const HyperBall_t &other);
|
||||
void DeepCopy(const HyperBall_t &other, int32 dimension);
|
||||
template<typename POINTTYPE>
|
||||
bool IsWithin(POINTTYPE point, int32 dimension, Precision_t range,
|
||||
ComputationsCounter<diagnostic> &comp);
|
||||
Precision_t IsWithin(HyperBall_t &hr,
|
||||
int32 dimension,
|
||||
Precision_t range,
|
||||
ComputationsCounter<diagnostic> &comp);
|
||||
template<typename POINTTYPE>
|
||||
bool CrossesBoundaries(POINTTYPE point, int32 dimension, Precision_t range,
|
||||
ComputationsCounter<diagnostic> &comp);
|
||||
template<typename POINTTYPE1, typename POINTTYPE2>
|
||||
static Precision_t Distance(POINTTYPE1 point1, POINTTYPE2 point2, int32 dimension);
|
||||
static Precision_t Distance(HyperBall_t &hr1,
|
||||
HyperBall_t &hr2,
|
||||
int32 dimension,
|
||||
ComputationsCounter<diagnostic> &comp);
|
||||
static Precision_t Distance(HyperBall_t &hr1,
|
||||
HyperBall_t &hr2,
|
||||
Precision_t threshold_distance,
|
||||
int32 dimension,
|
||||
ComputationsCounter<diagnostic> &comp);
|
||||
template<typename POINTTYPE, typename NODETYPE>
|
||||
pair<Allocator_t::template Ptr<NODETYPE>,
|
||||
Allocator_t::template Ptr<NODETYPE> >
|
||||
ClosestChild(Allocator_t::template Ptr<NODETYPE> left,
|
||||
Allocator_t::template Ptr<NODETYPE> right,
|
||||
POINTTYPE point, int32 dimension,
|
||||
ComputationsCounter<diagnostic> &comp);
|
||||
string Print(int32 dimension);
|
||||
|
||||
private:
|
||||
Array_t center_;
|
||||
// This is the radious, not the square of the radious
|
||||
Precision_t radious_;
|
||||
Array_t pivot_left_;
|
||||
Array_t pivot_right_;
|
||||
};
|
||||
|
||||
#include "hyper_ball_impl.h"
|
||||
#endif // HYPER_BALL_H_
|
||||
@@ -1,217 +0,0 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: hyper_ball_impl.h
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 02/11/2007 07:08:40 PM EST
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Nikolaos Vasiloglou (NV), nvasil@ieee.org
|
||||
* Company: Georgia Tech Fastlab-ESP Lab
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
#ifndef HYPER_BALL_IMPL_H_
|
||||
#define HYPER_BALL_IMPL_H_
|
||||
#define __TEMPLATE__ \
|
||||
template<typename TYPELIST, bool diagnostic>
|
||||
#define __HYPERBALL__ \
|
||||
HyperBall<TYPELIST, diagnostic>
|
||||
|
||||
__TEMPLATE__
|
||||
__HYPERBALL__::HyperBall() {
|
||||
}
|
||||
|
||||
__TEMPLATE__
|
||||
void __HYPERBALL__::Init(int32 dimension) {
|
||||
center_.Reset(Allocator_t::calloc<Precision_t>(dimension, 0));
|
||||
pivot_left_.Reset(Allocator_t::calloc<Precision_t>(dimension, 0));
|
||||
pivot_right_.Reset(Allocator_t::calloc<Precision_t>(dimension, 0));
|
||||
}
|
||||
|
||||
__TEMPLATE__
|
||||
void __HYPERBALL__::Init(Array_t center, Precision_t radious,
|
||||
Array_t pivot_left, Array_t pivot_right) {
|
||||
center_=center ;
|
||||
radious_=radious;
|
||||
pivot_left_=pivot_left;
|
||||
pivot_right_=pivot_right;
|
||||
}
|
||||
|
||||
__TEMPLATE__
|
||||
static void *__HYPERBALL__::operator new(size_t size) {
|
||||
return Allocator_t::malloc(size);
|
||||
}
|
||||
|
||||
__TEMPLATE__
|
||||
static void __HYPERBALL__::operator delete(void *p) {
|
||||
}
|
||||
|
||||
__TEMPLATE__
|
||||
inline HyperBall<TYPELIST, diagnostic> &__HYPERBALL__::operator=(
|
||||
const HyperBall<TYPELIST, diagnostic> &other) {
|
||||
center_ = other.center_;
|
||||
radious_ = other.radious_;
|
||||
pivot_left_ = other.pivot_left_;
|
||||
pivot_right_ = other.pivot_right_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
__TEMPLATE__
|
||||
inline void __HYPERBALL__::Copy(const HyperBall_t &other) {
|
||||
center_ = other.center_;
|
||||
radious_ = other.radious_;
|
||||
pivot_left_ = other.pivot_left_;
|
||||
pivot_right_ = other.pivot_right_;
|
||||
}
|
||||
|
||||
__TEMPLATE__
|
||||
inline void __HYPERBALL__::DeepCopy(const HyperBall_t &other,
|
||||
int32 dimension) {
|
||||
center_.DeepCopy(other.center_, dimension);
|
||||
radious_ = other.radious_;
|
||||
pivot_left_.DeepCopy(other.pivot_left_, dimension);
|
||||
pivot_right_.DeepCopy(other.pivot_right_, dimension);
|
||||
}
|
||||
|
||||
|
||||
|
||||
__TEMPLATE__
|
||||
template<typename POINTTYPE>
|
||||
inline bool __HYPERBALL__::IsWithin(POINTTYPE point,
|
||||
int32 dimension,
|
||||
Precision_t range,
|
||||
ComputationsCounter<diagnostic> &comp) {
|
||||
comp.UpdateDistances();
|
||||
Precision_t point_center_distance =
|
||||
Metric_t::Distance(center_, point, dimension);
|
||||
// Inside the ball
|
||||
comp.UpdateComparisons();
|
||||
if (radious_ > sqrt(point_center_distance) + sqrt(range)) {
|
||||
return true;
|
||||
} else {
|
||||
// Completelly outside or crossing
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
__TEMPLATE__
|
||||
inline Precision_t __HYPERBALL__::IsWithin(HyperBall_t &hr,
|
||||
int32 dimension,
|
||||
Precision_t range,
|
||||
ComputationsCounter<diagnostic> &comp) {
|
||||
return IsWithin(hr.center_, dimension, hr.radious_ * hr.radious_, comp);
|
||||
}
|
||||
|
||||
__TEMPLATE__
|
||||
template<typename POINTTYPE>
|
||||
inline bool __HYPERBALL__::CrossesBoundaries(POINTTYPE point,
|
||||
int32 dimension,
|
||||
Precision_t range,
|
||||
ComputationsCounter<diagnostic> &comp) {
|
||||
comp.UpdateDistances();
|
||||
Precision_t point_center_distance = Metric_t::Distance(center_, point, dimension);
|
||||
comp.UpdateComparisons();
|
||||
if (point_center_distance < range) {
|
||||
return true;
|
||||
}
|
||||
comp.UpdateComparisons();
|
||||
if (sqrt(point_center_distance) > radious_+ sqrt(range)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
__TEMPLATE__
|
||||
template<typename POINTTYPE1, typename POINTTYPE2>
|
||||
inline Precision_t __HYPERBALL__::Distance(POINTTYPE1 point1,
|
||||
POINTTYPE2 point2,
|
||||
int32 dimension) {
|
||||
return Metric_t::Distance(point1, point2, dimension);
|
||||
}
|
||||
|
||||
__TEMPLATE__
|
||||
inline Precision_t __HYPERBALL__::Distance(HyperBall_t &hr1,
|
||||
HyperBall_t &hr2,
|
||||
int32 dimension,
|
||||
ComputationsCounter<diagnostic> &comp) {
|
||||
comp.UpdateDistances();
|
||||
Precision_t center_distances=Metric_t::Distance(hr1.center_,
|
||||
hr2.center_, dimension);
|
||||
comp.UpdateComparisons();
|
||||
Precision_t dist=sqrt(center_distances)-(hr2.radious_+hr1.radious_);
|
||||
if (dist<=0) {
|
||||
return 0;
|
||||
} else {
|
||||
return dist*dist;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
__TEMPLATE__
|
||||
Precision_t __HYPERBALL__::Distance(HyperBall_t &hr1,
|
||||
HyperBall_t &hr2,
|
||||
Precision_t threshold_distance,
|
||||
int32 dimension,
|
||||
ComputationsCounter<diagnostic> &comp) {
|
||||
fprintf(stderr, "Not Implemented yet\n");
|
||||
assert("false");
|
||||
return 0;
|
||||
}
|
||||
|
||||
__TEMPLATE__
|
||||
template<typename POINTTYPE, typename NODETYPE>
|
||||
inline pair<Allocator_t::template Ptr<NODETYPE>,
|
||||
Allocator_t::template Ptr<NODETYPE> >
|
||||
__HYPERBALL__::ClosestChild(Allocator_t::template Ptr<NODETYPE> left,
|
||||
Allocator_t::template Ptr<NODETYPE> right,
|
||||
POINTTYPE point,
|
||||
int32 dimension,
|
||||
ComputationsCounter<diagnostic> &comp) {
|
||||
comp.UpdateDistances();
|
||||
comp.UpdateDistances();
|
||||
Precision_t left_dist = Metric_t::Distance(pivot_left_, point, dimension);
|
||||
Precision_t right_dist = Metric_t::Distance(pivot_right_, point, dimension);
|
||||
if (left_dist<right_dist) {
|
||||
return make_pair(left, right);
|
||||
} else {
|
||||
return make_pair(right, left);
|
||||
}
|
||||
}
|
||||
|
||||
__TEMPLATE__
|
||||
string __HYPERBALL__::Print(int32 dimension) {
|
||||
char buf[8192];
|
||||
string str("center: ");
|
||||
for(int32 i=0; i<dimension; i++){
|
||||
sprintf(buf,"%lg ", (double) center_[i]);
|
||||
str.append(buf);
|
||||
}
|
||||
str.append("\nradious: ");
|
||||
sprintf(buf,"%lg\n", (double) radious_);
|
||||
str.append(buf);
|
||||
str.append("pivot_left: ");
|
||||
for(int32 i=0; i<dimension; i++){
|
||||
sprintf(buf,"%lg ", (double)pivot_left_[i]);
|
||||
str.append(buf);
|
||||
}
|
||||
str.append("\npivot_right: ");
|
||||
for(int32 i=0; i<dimension; i++){
|
||||
sprintf(buf,"%lg ", (double)pivot_right_[i]);
|
||||
str.append(buf);
|
||||
}
|
||||
str.append("\n");
|
||||
return str;
|
||||
}
|
||||
|
||||
#undef __TEMPLATE__
|
||||
#undef __HYPERBALL__
|
||||
#endif // HYPER_BALL_IMPL_H_
|
||||
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: hyper_ball_unit.cc
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 04/21/2007 06:12:12 PM EDT
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Nikolaos Vasiloglou (NV), nvasil@ieee.org
|
||||
* Company: Georgia Tech Fastlab-ESP Lab
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
#include "loki/Typelist.h"
|
||||
#include "fastlib/fastlib.h"
|
||||
#include "mmanager/memory_manager.h"
|
||||
#include "hyper_ball.h"
|
||||
|
||||
template<typename TYPELIST, bool diagnostic>
|
||||
class HyperBallTest {
|
||||
public:
|
||||
typedef TypeAt<TYPELIST, 0>::value Precision_t;
|
||||
typedef TypeAt<TYPELIST, 1>::value Allocator_t;
|
||||
typedef TypeAt<TYPELIST, 2>::value Metric_t;
|
||||
typedef HyperBall<TYPELIST, diagnostic> HyperBall_t;
|
||||
HyperBallTest();
|
||||
~HyperBall() {
|
||||
Destruct();
|
||||
}
|
||||
void Init() {
|
||||
dimension_=2;
|
||||
Allocator_t::allocator_ = new Allocator_t();
|
||||
Allocator_t::allocator_->Initialize();
|
||||
hyper_ball_= new HyperBall_t();
|
||||
Allocator_t::ArrayPtr<Precision_t> center(dimension_);
|
||||
center[0]=1;
|
||||
center[1]=-1;
|
||||
Precision_t radious=2;
|
||||
Allocator_t::ArrayPtr<Precision_t> pivot_left;
|
||||
Allocator_t::ArrayPtr<Precision_t> pivot_right;
|
||||
hyper_ball_->Init(center, radious, pivot_left, pivot_right);
|
||||
}
|
||||
void Destruct() {
|
||||
delete hyper_ball_;
|
||||
delete Allocator_t::allocator_;
|
||||
}
|
||||
|
||||
void AliasTest() {
|
||||
printf("Alias Test\n");
|
||||
Init();
|
||||
HyperBall_t other;
|
||||
other.Alias(*hyper_ball_);
|
||||
DEBUG_ASSERT_MSG(other.center_==hyper_ball_->center_,
|
||||
"Centers don't match\n");
|
||||
DEBUG_ASSERT_MSG(other.radious_==hyper_ball_->radious_,
|
||||
"Radious don't match\n");
|
||||
DEBUG_ASSERT_MSG(other.pivot_left_==hyper_ball_->pivot_left_,
|
||||
"Pivot left doesn't match\n");
|
||||
DEBUG_ASSERT_MSG(other.pivot_right_==hyper_ball_->pivot_right_,
|
||||
"Pivot right don't match\n");
|
||||
Destruct();
|
||||
}
|
||||
void DeepCopyTest() {
|
||||
printf("DeepCopy Test\n");
|
||||
Init();
|
||||
HyperBall_t other;
|
||||
other.Init(dimension_);
|
||||
other.DeepCopy(*hyper_ball_, dimension_);
|
||||
DEBUG_ASSERT_MSG(other.radious_==hyper_ball_->radious_,
|
||||
"Radious don't match\n");
|
||||
DEBUG_ASSERT_MSG(other.center_!=hyper_ball_->center_,
|
||||
"Centers are the same \n");
|
||||
for(index_t i=0; i<dimension_; i++) {
|
||||
DEBUG_ASSERT_MSG(other.center_[i]==hyper_ball_->center_[i],
|
||||
"Centers don't match\n");
|
||||
DEBUG_ASSERT_MSG(other.pivot_left_[i]==hyper_ball_->pivot_left_[i],
|
||||
"Pivot left doesn't match\n");
|
||||
DEBUG_ASSERT_MSG(other.pivot_right_[i]==hyper_ball_->pivot_right_[i],
|
||||
"Pivot right don't match\n");
|
||||
}
|
||||
Destruct();
|
||||
}
|
||||
void IsWithinTest() {
|
||||
Point<Precision_t, Allocator_t> point;
|
||||
point[0]=1;
|
||||
point[1]=0.3;
|
||||
Precision_t range=0.03;
|
||||
DEBUG_ASSERT_MSG(hyper_ball_->IsWithin(point, dimension_,
|
||||
range, comp)==true,
|
||||
"IsWithin doesn't work\n");
|
||||
range=2;
|
||||
DEBUG_ASSERT_MSG(hyper_ball_->IsWithin(point, dimension_,
|
||||
range, comp)==false,
|
||||
"IsWithin doesn't work\n");
|
||||
|
||||
Destruct();
|
||||
}
|
||||
void CrossesBoundaryTest() {
|
||||
Point<Precision_t, Allocator_t> point;
|
||||
point.Init(dimension_);
|
||||
point[0]=2;
|
||||
point[1]=-4;
|
||||
Precision_t range=1;
|
||||
DEBUG_ASSERT_MSG(hyper_ball_->CrossesBoundary(point, dimension_,
|
||||
range, comp)==true,
|
||||
"CrossesBoundary doesn't work\n");
|
||||
range=0.25;
|
||||
DEBUG_ASSERT_MSG(hyper_ball_->CrossesBoundary(point, dimension_,
|
||||
range, comp)==false,
|
||||
"CrossesBoundary doesn't work\n");
|
||||
|
||||
Destruct();
|
||||
}
|
||||
void DistanceTest(){
|
||||
Point<Precision_t, Allocator_t> point1;
|
||||
Point<Precision_t, Allocator_t> point2;
|
||||
point1.Init(dimension_);
|
||||
point1[0]=0;
|
||||
point1[1]=1;
|
||||
point2[0]=-1;
|
||||
point2[1]=-2;
|
||||
point2.Init(dimension_);
|
||||
ASSERT_DEBUG_MSG(HyperBall_t::Distance(point1, point2, dimension_)==10,
|
||||
"Distance between points doesn't work\n");
|
||||
HyperBall_t other;
|
||||
other.Init(dimension_);
|
||||
other.center_[0]=1;
|
||||
other.center_[1]=5;
|
||||
other.radious_=3;
|
||||
ASSERT_DEBUG_MSG(HyperBall_t::Distance(*hyper_ball_, other,
|
||||
dimension)==31,
|
||||
"Dimension doesn't work\n");
|
||||
other.radious_=34;
|
||||
ASSERT_DEBUG_MSG(HyperBall_t::Distance(*hyper_ball_, other,
|
||||
dimension)==0,
|
||||
"Dimension doesn't work\n");
|
||||
Destruct();
|
||||
}
|
||||
|
||||
private:
|
||||
HyperBall<TYPELIST, diagnostic> *hyper_ball_;
|
||||
int32 dimension_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
typdef TYPELIST_3(float32, MemoryManager<true>, EuclideanMetric<float32>)
|
||||
UserTypeParameters_t;
|
||||
HyperBallTest<UserTypeParameters_t, false> hyper_ball_test;
|
||||
hyper_ball_test.CopyTest();
|
||||
hyper_ball_test.IsWithinTest();
|
||||
hyper_ball_test.CrossesBoundaryTest();
|
||||
hyper_ball_test.DistanceTest();
|
||||
hyper_ball_test.ClosestDistanceTest();
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: hyper_rectangle.h
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 04/17/2007 04:38:03 PM EDT
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Nikolaos Vasiloglou (NV), nvasil@ieee.org
|
||||
* Company: Georgia Tech Fastlab-ESP Lab
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
#ifndef U_NVASIL_HYPER_RECTANGLE_H_
|
||||
#define U_NVASIL_HYPER_RECTANGLE_H_
|
||||
|
||||
#include <new>
|
||||
#include <limits>
|
||||
#include <math.h>
|
||||
#include <string>
|
||||
#include "u/nvasil/loki/Typelist.h"
|
||||
#include "fastlib/fastlib.h"
|
||||
#include "computations_counter.h"
|
||||
|
||||
using namespace std;
|
||||
template<typename BASICTYPES, bool diagnostic>
|
||||
class HyperRectangle {
|
||||
public:
|
||||
typedef typename BASICTYPES::Precision_t Precision_t;
|
||||
typedef typename BASICTYPES::Allocator_t Allocator_t;
|
||||
typedef typename BASICTYPES::Metric_t Metric_t;
|
||||
/*
|
||||
typedef typename Loki::TL::TypeAt<TYPELIST, 0>::Result Precision_t;
|
||||
typedef typename Loki::TL::TypeAt<TYPELIST, 1>::Result Allocator_t;
|
||||
typedef typename Loki::TL::TypeAt<TYPELIST, 2>::Result Metric_t;
|
||||
*/
|
||||
typedef HyperRectangle<BASICTYPES, diagnostic> HyperRectangle_t;
|
||||
typedef typename Allocator_t:: template ArrayPtr<Precision_t> ArrayPtr_t;
|
||||
typedef typename Allocator_t:: template ArrayPtr<Precision_t> Array_t;
|
||||
template<typename, bool> friend class HyperRectangleTest;
|
||||
|
||||
HyperRectangle();
|
||||
void Init(int32 dimension);
|
||||
void Init(ArrayPtr_t min, ArrayPtr_t max, int32 pivot_dimension,
|
||||
Precision_t pivot_value);
|
||||
~HyperRectangle() {};
|
||||
void Destruct(){
|
||||
}
|
||||
static void *operator new(size_t size);
|
||||
static void operator delete(void *p);
|
||||
HyperRectangle_t &operator=(HyperRectangle_t &);
|
||||
void Alias(const HyperRectangle_t &other);
|
||||
void Copy(const HyperRectangle_t &other, int32 dimension);
|
||||
template<typename POINTTYPE>
|
||||
bool IsWithin(POINTTYPE point, int32 dimension, Precision_t range,
|
||||
ComputationsCounter<diagnostic> &comp);
|
||||
template <typename POINTTYPE>
|
||||
bool IsWithin(POINTTYPE point, int32 dimension, Precision_t metric_matrix,
|
||||
Precision_t range, ComputationsCounter<diagnostic> &comp);
|
||||
Precision_t IsWithin(HyperRectangle_t &hr,
|
||||
int32 dimension,
|
||||
Precision_t range,
|
||||
ComputationsCounter<diagnostic> &comp);
|
||||
template<typename POINTTYPE>
|
||||
bool CrossesBoundaries(POINTTYPE point, int32 dimension, Precision_t range,
|
||||
ComputationsCounter<diagnostic> &comp);
|
||||
template<typename POINTTYPE1, typename POINTTYPE2>
|
||||
static Precision_t Distance(POINTTYPE1 point1, POINTTYPE2 point2,
|
||||
int32 dimension);
|
||||
template<typename POINTTYPE1, typename POINTTYPE2>
|
||||
static Precision_t Distance(POINTTYPE1 point1, POINTTYPE2 point2,
|
||||
int32 dimension, Precision_t **metric_matrix);
|
||||
static Precision_t Distance(HyperRectangle_t &hr1,
|
||||
HyperRectangle_t &hr2,
|
||||
int32 dimension,
|
||||
ComputationsCounter<diagnostic> &comp);
|
||||
static Precision_t Distance(HyperRectangle_t &hr1,
|
||||
HyperRectangle_t &hr2,
|
||||
Precision_t threshold_distance,
|
||||
int32 dimension,
|
||||
ComputationsCounter<diagnostic> &comp);
|
||||
template<typename POINTTYPE, typename NODETYPE>
|
||||
pair<typename Allocator_t::template Ptr<NODETYPE>,
|
||||
typename Allocator_t::template Ptr<NODETYPE> >
|
||||
ClosestChild(typename Allocator_t::template Ptr<NODETYPE> left,
|
||||
typename Allocator_t::template Ptr<NODETYPE> right,
|
||||
POINTTYPE point,
|
||||
int32 dimension,
|
||||
ComputationsCounter<diagnostic> &comp);
|
||||
string Print(int32 dimension);
|
||||
Array_t &get_min() {
|
||||
return min_;
|
||||
}
|
||||
Array_t &get_max() {
|
||||
return max_;
|
||||
}
|
||||
int32 get_pivot_dimension() {
|
||||
return pivot_dimension_;
|
||||
}
|
||||
Precision_t get_pivot_value() {
|
||||
return pivot_value_;
|
||||
}
|
||||
void set_pivot_dimension(int32 pivot_dimension) {
|
||||
pivot_dimension_=pivot_dimension;
|
||||
}
|
||||
void set_pivot_value(Precision_t pivot_value) {
|
||||
pivot_value_=pivot_value;
|
||||
}
|
||||
private:
|
||||
Array_t min_;
|
||||
Array_t max_;
|
||||
int32 pivot_dimension_;
|
||||
Precision_t pivot_value_;
|
||||
};
|
||||
|
||||
#include "hyper_rectangle_impl.h"
|
||||
|
||||
#endif
|
||||
@@ -1,274 +0,0 @@
|
||||
#ifndef HYPER_RECTANGLE_IMPL_H_
|
||||
#define HYPER_RECTANGLE_IMPL_H_
|
||||
|
||||
#define TEMPLATE__ template<typename TYPELIST, bool diagnostic>
|
||||
#define HYPERRECTANGLE__ HyperRectangle<TYPELIST, diagnostic>
|
||||
|
||||
TEMPLATE__
|
||||
HYPERRECTANGLE__::HyperRectangle(){
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void HYPERRECTANGLE__::Init(int32 dimension) {
|
||||
min_.Reset(Allocator_t:: template calloc<Precision_t>
|
||||
(dimension, numeric_limits<Precision_t>::max()));
|
||||
max_.Reset(Allocator_t:: template calloc<Precision_t>
|
||||
(dimension, -numeric_limits<Precision_t>::max()));
|
||||
pivot_dimension_=0;
|
||||
pivot_value_=0;
|
||||
}
|
||||
TEMPLATE__
|
||||
void HYPERRECTANGLE__::Init(Array_t min, Array_t max, int32 pivot_dimension,
|
||||
Precision_t pivot_value) {
|
||||
min_.Reset(min.get());
|
||||
max_ = max;
|
||||
pivot_dimension_ = pivot_dimension;
|
||||
pivot_value_= pivot_value;
|
||||
}
|
||||
|
||||
|
||||
TEMPLATE__
|
||||
HyperRectangle<TYPELIST, diagnostic> &HYPERRECTANGLE__::operator=
|
||||
(HyperRectangle<TYPELIST, diagnostic> &hr) {
|
||||
|
||||
this->min_ = hr.min_;
|
||||
this->max_ = hr.max_;
|
||||
pivot_dimension_ = hr.pivot_dimension_;
|
||||
pivot_value_ = hr.pivot_value_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void HYPERRECTANGLE__::Alias(const HyperRectangle_t &hr) {
|
||||
|
||||
this->min_ = hr.min_;
|
||||
this->max_ = hr.max_;
|
||||
pivot_dimension_ = hr.pivot_dimension_;
|
||||
pivot_value_ = hr.pivot_value_;
|
||||
}
|
||||
|
||||
|
||||
TEMPLATE__
|
||||
void HYPERRECTANGLE__::Copy(const HyperRectangle_t &hr,
|
||||
int32 dimension) {
|
||||
|
||||
this->min_.Copy(hr.min_, dimension);
|
||||
this->max_.Copy(hr.max_, dimension);
|
||||
pivot_dimension_ = hr.pivot_dimension_;
|
||||
pivot_value_ = hr.pivot_value_;
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void *HYPERRECTANGLE__::operator new(size_t size) {
|
||||
return Allocator_t::malloc(size);
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void HYPERRECTANGLE__::operator delete(void *p) {
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
template<typename POINTTYPE>
|
||||
inline bool HYPERRECTANGLE__::IsWithin(
|
||||
POINTTYPE point, int32 dimension, Precision_t range,
|
||||
ComputationsCounter<diagnostic> &comp) {
|
||||
// non overlaping at all
|
||||
for(int32 i=0; i<dimension; i++) {
|
||||
comp.UpdateComparisons();
|
||||
if ( point[i] > max_[i] || point[i] < min_[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Precision_t closest_projection = max_[0]-min_[0];
|
||||
for(int32 i=0; i<dimension; i++) {
|
||||
Precision_t projection1 = max_[i] - point[i];
|
||||
Precision_t projection2 = point[i] - min_[i];
|
||||
comp.UpdateComparisons();
|
||||
if (closest_projection > projection1) {
|
||||
closest_projection = projection1;
|
||||
}
|
||||
comp.UpdateComparisons();
|
||||
if (closest_projection > projection2 ) {
|
||||
closest_projection = projection2;
|
||||
}
|
||||
comp.UpdateComparisons();
|
||||
if (range >= closest_projection * closest_projection) {
|
||||
// Overlapping
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// Completelly inside
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
TEMPLATE__
|
||||
inline typename HYPERRECTANGLE__::Precision_t HYPERRECTANGLE__::IsWithin(
|
||||
HyperRectangle_t &hr,
|
||||
int32 dimension,
|
||||
Precision_t range,
|
||||
ComputationsCounter<diagnostic> &comp) {
|
||||
|
||||
Precision_t closest_projection = numeric_limits<Precision_t>::max();
|
||||
for(int32 i=0; i<dimension; i++) {
|
||||
comp.UpdateComparisons();
|
||||
comp.UpdateComparisons();
|
||||
Precision_t d1=hr.min_[i] - min_[i];
|
||||
Precision_t d2=max_[i] - hr.max_[i];
|
||||
if (d1<0 || d2<0) {
|
||||
return -1;
|
||||
} else {
|
||||
Precision_t dist = min(d1,d2);
|
||||
if (dist < closest_projection) {
|
||||
closest_projection = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (closest_projection * closest_projection > range) {
|
||||
return 0;
|
||||
}
|
||||
return (sqrt(range) - closest_projection) *
|
||||
(sqrt(range) - closest_projection);
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
template<typename POINTTYPE>
|
||||
inline bool HYPERRECTANGLE__::CrossesBoundaries(
|
||||
POINTTYPE point, int32 dimension, HYPERRECTANGLE__::Precision_t range,
|
||||
ComputationsCounter<diagnostic> &comp) {
|
||||
|
||||
Precision_t closest_point_coordinate;
|
||||
Precision_t dist = 0;
|
||||
for(int32 i=0; i<dimension; i++) {
|
||||
comp.UpdateComparisons();
|
||||
if (point[i] <= min_[i]) {
|
||||
closest_point_coordinate = min_[i];
|
||||
} else {
|
||||
comp.UpdateComparisons();
|
||||
if (point[i] < max_[i] && point[i] > min_[i]) {
|
||||
closest_point_coordinate = point[i];
|
||||
} else {
|
||||
closest_point_coordinate = max_[i];
|
||||
}
|
||||
}
|
||||
dist +=(closest_point_coordinate - point[i]) *
|
||||
(closest_point_coordinate - point[i]);
|
||||
comp.UpdateComparisons();
|
||||
if (dist > range ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return dist <= range;
|
||||
}
|
||||
TEMPLATE__
|
||||
template<typename POINTTYPE1, typename POINTTYPE2>
|
||||
inline typename HYPERRECTANGLE__::Precision_t HYPERRECTANGLE__::Distance(
|
||||
POINTTYPE1 point1,
|
||||
POINTTYPE2 point2,
|
||||
int32 dimension) {
|
||||
Precision_t distance = 0;
|
||||
for(int32 i=0; i< dimension; i++) {
|
||||
distance+=(point1[i]-point2[i]) * (point1[i]-point2[i]);
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
inline typename HYPERRECTANGLE__::Precision_t HYPERRECTANGLE__::Distance(
|
||||
typename HYPERRECTANGLE__::HyperRectangle_t &hr1,
|
||||
typename HYPERRECTANGLE__::HyperRectangle_t &hr2,
|
||||
int32 dimension,
|
||||
ComputationsCounter<diagnostic> &comp) {
|
||||
|
||||
Precision_t dist=0;
|
||||
comp.UpdateDistances();
|
||||
for(int32 i=0; i<dimension; i++) {
|
||||
Precision_t d2 = hr1.min_[i] - hr2.max_[i];
|
||||
Precision_t d4 = hr1.max_[i] - hr2.min_[i];
|
||||
if (d2>0) {
|
||||
dist += d2*d2 ;
|
||||
continue;
|
||||
}
|
||||
if (d4<0) {
|
||||
dist += d4*d4;
|
||||
}
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
inline typename HYPERRECTANGLE__::Precision_t HYPERRECTANGLE__::Distance(
|
||||
typename HYPERRECTANGLE__::HyperRectangle_t &hr1,
|
||||
typename HYPERRECTANGLE__::HyperRectangle_t &hr2,
|
||||
typename HYPERRECTANGLE__::Precision_t threshold_distance,
|
||||
int32 dimension,
|
||||
ComputationsCounter<diagnostic> &comp) {
|
||||
|
||||
Precision_t dist=0;
|
||||
comp.UpdateDistances();
|
||||
for(int32 i=0; i<dimension; i++) {
|
||||
Precision_t d2 = hr1.min_[i] - hr2.max_[i];
|
||||
Precision_t d4 = hr1.max_[i] - hr2.min_[i];
|
||||
if (d2>0) {
|
||||
dist += d2*d2;
|
||||
if (dist > threshold_distance) {
|
||||
return numeric_limits<Precision_t>::max();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (d4<0) {
|
||||
dist += d4*d4;
|
||||
if (dist > threshold_distance) {
|
||||
return numeric_limits<Precision_t>::max();
|
||||
}
|
||||
}
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
template<typename POINTTYPE, typename NODETYPE>
|
||||
inline pair<typename HYPERRECTANGLE__::Allocator_t:: template Ptr<NODETYPE>,
|
||||
typename HYPERRECTANGLE__::Allocator_t:: template Ptr<NODETYPE> >
|
||||
HYPERRECTANGLE__::ClosestChild(
|
||||
typename HYPERRECTANGLE__::Allocator_t::template Ptr<NODETYPE> left,
|
||||
typename HYPERRECTANGLE__::Allocator_t::template Ptr<NODETYPE> right,
|
||||
POINTTYPE point,
|
||||
int32 dimension,
|
||||
ComputationsCounter<diagnostic> &comp) {
|
||||
comp.UpdateComparisons();
|
||||
if (point[pivot_dimension_] < pivot_value_) {
|
||||
return make_pair(left, right);
|
||||
} else {
|
||||
return make_pair(right, left);
|
||||
}
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
string HYPERRECTANGLE__::Print(int32 dimension) {
|
||||
char buf[8192];
|
||||
sprintf(buf, "max: ");
|
||||
string str;
|
||||
str.append(buf);
|
||||
for(int32 i=0; i<dimension; i++) {
|
||||
sprintf(buf, " %f ", max_[i]);
|
||||
str.append(buf);
|
||||
}
|
||||
sprintf(buf, "\n");
|
||||
str.append(buf);
|
||||
sprintf(buf, "min: ");
|
||||
str.append(buf);
|
||||
for(int32 i=0; i<dimension; i++) {
|
||||
sprintf(buf, " %f ", min_[i]);
|
||||
str.append(buf);
|
||||
}
|
||||
sprintf(buf, "\n");
|
||||
str.append(buf);
|
||||
|
||||
return str;
|
||||
}
|
||||
#undef TEMPLATE__
|
||||
#undef HYPERRECTANGLE__
|
||||
|
||||
#endif /*HYPER_RECTANGLE_IMPL_H_*/
|
||||
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: hyper_rectangle_unit.cc
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 04/22/2007 09:45:28 PM EDT
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Nikolaos Vasiloglou (NV), nvasil@ieee.org
|
||||
* Company: Georgia Tech Fastlab-ESP Lab
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
#include "u/nvasil/loki/Typelist.h"
|
||||
#include "fastlib/fastlib.h"
|
||||
#include "u/nvasil/mmanager/memory_manager.h"
|
||||
#include "point.h"
|
||||
#include "euclidean_metric.h"
|
||||
#include "hyper_rectangle.h"
|
||||
|
||||
template<typename TYPELIST, bool diagnostic>
|
||||
class HyperRectangleTest {
|
||||
friend class HyperRectangle<TYPELIST, diagnostic>;
|
||||
public:
|
||||
typedef typename TYPELIST::Precision_t Precision_t;
|
||||
typedef typename TYPELIST::Allocator_t Allocator_t;
|
||||
typedef typename TYPELIST::Metric_t Metric_t;
|
||||
typedef HyperRectangle<TYPELIST, diagnostic> HyperRectangle_t;
|
||||
HyperRectangleTest() {
|
||||
}
|
||||
~HyperRectangleTest() {
|
||||
}
|
||||
void Init() {
|
||||
dimension_=2;
|
||||
Allocator_t::allocator_ = new Allocator_t();
|
||||
Allocator_t::allocator_->Initialize();
|
||||
hyper_rectangle_= new HyperRectangle_t();
|
||||
hyper_rectangle_->Init(dimension_);
|
||||
hyper_rectangle_->min_[0]=-1;
|
||||
hyper_rectangle_->min_[1]=-1;
|
||||
hyper_rectangle_->max_[0]=1;
|
||||
hyper_rectangle_->max_[1]=1;
|
||||
}
|
||||
void Destruct() {
|
||||
delete hyper_rectangle_;
|
||||
delete Allocator_t::allocator_;
|
||||
}
|
||||
|
||||
void AliasTest() {
|
||||
printf("Alias Test\n");
|
||||
Init();
|
||||
HyperRectangle_t other;
|
||||
other.Alias(*hyper_rectangle_);
|
||||
DEBUG_ASSERT_MSG(other.min_==hyper_rectangle_->min_,
|
||||
"Min don't match\n");
|
||||
DEBUG_ASSERT_MSG(other.max_==hyper_rectangle_->max_,
|
||||
"Max don't match\n");
|
||||
DEBUG_ASSERT_MSG(other.pivot_dimension_==hyper_rectangle_->pivot_dimension_,
|
||||
"Pivot dimension doesn't match\n");
|
||||
DEBUG_ASSERT_MSG(other.pivot_value_==hyper_rectangle_->pivot_value_,
|
||||
"Pivot value don't match\n");
|
||||
Destruct();
|
||||
}
|
||||
void CopyTest() {
|
||||
printf("Copy Test\n");
|
||||
Init();
|
||||
HyperRectangle_t other;
|
||||
other.Init(dimension_);
|
||||
other.Copy(*hyper_rectangle_, dimension_);
|
||||
DEBUG_ASSERT_MSG(other.min_==hyper_rectangle_->min_,
|
||||
"Min don't match\n");
|
||||
DEBUG_ASSERT_MSG(other.max_!=hyper_rectangle_->max_,
|
||||
"Max are the same \n");
|
||||
for(index_t i=0; i<dimension_; i++) {
|
||||
DEBUG_ASSERT_MSG(other.min_[i]==hyper_rectangle_->min_[i],
|
||||
"Min don't match\n");
|
||||
DEBUG_ASSERT_MSG(other.max_[i]==hyper_rectangle_->max_[i],
|
||||
"Max left doesn't match\n");
|
||||
}
|
||||
Destruct();
|
||||
}
|
||||
void IsWithinTest() {
|
||||
Init();
|
||||
Point<Precision_t, Allocator_t> point;
|
||||
point.Init(dimension_);
|
||||
point[0]=-0.1;
|
||||
point[1]=0.3;
|
||||
Precision_t range=0.03;
|
||||
DEBUG_ASSERT_MSG(hyper_rectangle_->IsWithin(point, dimension_,
|
||||
range, comp_)==true,
|
||||
"IsWithin doesn't work\n");
|
||||
range=2;
|
||||
DEBUG_ASSERT_MSG(hyper_rectangle_->IsWithin(point, dimension_,
|
||||
range, comp_)==false,
|
||||
"IsWithin doesn't work\n");
|
||||
|
||||
Destruct();
|
||||
}
|
||||
void CrossesBoundariesTest() {
|
||||
Init();
|
||||
Point<Precision_t, Allocator_t> point;
|
||||
point.Init(dimension_);
|
||||
point[0]=2;
|
||||
point[1]=-4;
|
||||
Precision_t range=11;
|
||||
DEBUG_ASSERT_MSG(hyper_rectangle_->CrossesBoundaries(point, dimension_,
|
||||
range, comp_)==true,
|
||||
"CrossesBoundary doesn't work\n");
|
||||
range=0.25;
|
||||
DEBUG_ASSERT_MSG(hyper_rectangle_->CrossesBoundaries(point, dimension_,
|
||||
range, comp_)==false,
|
||||
"CrossesBoundary doesn't work\n");
|
||||
|
||||
Destruct();
|
||||
}
|
||||
void DistanceTest(){
|
||||
Init();
|
||||
Point<Precision_t, Allocator_t> point1;
|
||||
Point<Precision_t, Allocator_t> point2;
|
||||
point1.Init(dimension_);
|
||||
point2.Init(dimension_);
|
||||
point1[0]=0;
|
||||
point1[1]=1;
|
||||
point2[0]=-1;
|
||||
point2[1]=-2;
|
||||
DEBUG_ASSERT_MSG(HyperRectangle_t::Distance(point1, point2, dimension_)==10,
|
||||
"Distance between points doesn't work\n");
|
||||
HyperRectangle_t other;
|
||||
other.Init(dimension_);
|
||||
other.min_[0]=2;
|
||||
other.min_[1]=2;
|
||||
other.max_[0]=5;
|
||||
other.max_[1]=5;
|
||||
|
||||
DEBUG_ASSERT_MSG(HyperRectangle_t::Distance(*hyper_rectangle_, other,
|
||||
dimension_, comp_)==2,
|
||||
"Distance doesn't work\n");
|
||||
other.min_[0]=-0.5;
|
||||
other.min_[1]=-0.5;
|
||||
DEBUG_ASSERT_MSG(HyperRectangle_t::Distance(*hyper_rectangle_, other,
|
||||
dimension_, comp_)==0,
|
||||
"Distance doesn't work\n");
|
||||
Destruct();
|
||||
}
|
||||
|
||||
private:
|
||||
HyperRectangle<TYPELIST, diagnostic> *hyper_rectangle_;
|
||||
int32 dimension_;
|
||||
ComputationsCounter<diagnostic> comp_;
|
||||
};
|
||||
|
||||
/*
|
||||
typedef LOKI_TYPELIST_3(float32,
|
||||
MemoryManager<false>,
|
||||
EuclideanMetric<float32>) UserTypeParameters_t;
|
||||
*/
|
||||
struct BasicTypes {
|
||||
typedef float32 Precision_t;
|
||||
typedef MemoryManager<false> Allocator_t;
|
||||
typedef EuclideanMetric<float32> Metric_t;
|
||||
};
|
||||
int main(int argc, char *argv[]) {
|
||||
HyperRectangleTest<BasicTypes, false> hyper_rectangle_test;
|
||||
hyper_rectangle_test.AliasTest();
|
||||
hyper_rectangle_test.IsWithinTest();
|
||||
hyper_rectangle_test.CrossesBoundariesTest();
|
||||
hyper_rectangle_test.DistanceTest();
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: HyperRectanglePivoter.h
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 04/28/2007 12:03:05 PM EDT
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Nikolaos Vasiloglou (NV), nvasil@ieee.org
|
||||
* Company: Georgia Tech Fastlab-ESP Lab
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
#ifndef KD_PIVOTER1_H_
|
||||
#define KD_PIVOTER1_H_
|
||||
|
||||
#include "fastlib/fastlib.h"
|
||||
#include "u/nvasil/dataset/binary_dataset.h"
|
||||
#include "hyper_rectangle.h"
|
||||
using namespace std;
|
||||
template<typename TYPELIST, bool diagnostic>
|
||||
class KdPivoter1 {
|
||||
public:
|
||||
typedef typename TYPELIST::Precision_t Precision_t;
|
||||
typedef typename TYPELIST::Allocator_t Allocator_t;
|
||||
typedef typename TYPELIST::Metric_t Metric_t;
|
||||
typedef HyperRectangle<TYPELIST, diagnostic> HyperRectangle_t;
|
||||
struct PivotInfo {
|
||||
public:
|
||||
void Init(index_t start, index_t num_of_points, HyperRectangle_t &box) {
|
||||
box_.Alias(box);
|
||||
start_=start;
|
||||
num_of_points_=num_of_points;
|
||||
}
|
||||
HyperRectangle_t box_;
|
||||
NullStatistics statistics_;
|
||||
index_t start_;
|
||||
index_t num_of_points_;
|
||||
};
|
||||
void Init(BinaryDataset<Precision_t> *data) {
|
||||
data_=data;
|
||||
}
|
||||
|
||||
pair<PivotInfo*, PivotInfo*> operator()(PivotInfo *pivot) {
|
||||
index_t left_start = pivot->start_;
|
||||
index_t right_start = pivot->start_ + pivot->num_of_points_-1;
|
||||
int32 dimension = data_->get_dimension();
|
||||
int32 max_range_dimension = pivot->box_.get_pivot_dimension();
|
||||
Precision_t pivot_value = pivot->box_.get_pivot_value();
|
||||
Precision_t *point_left = data_->At(left_start);
|
||||
Precision_t *point_right = data_->At(right_start);
|
||||
index_t left_points=0;
|
||||
index_t right_points=0;
|
||||
HyperRectangle_t hr_left;
|
||||
HyperRectangle_t hr_right;
|
||||
hr_left.Init(dimension);
|
||||
hr_right.Init(dimension);
|
||||
|
||||
while (true) {
|
||||
while (left_points < pivot->num_of_points_ &&
|
||||
point_left[max_range_dimension] < pivot_value) {
|
||||
UpdateHyperRectangle(point_left, hr_left);
|
||||
left_points++;
|
||||
point_left = data_->At(left_start+left_points);
|
||||
}
|
||||
if (point_left > point_right || left_points == pivot->num_of_points_) {
|
||||
break;
|
||||
}
|
||||
while (right_points < pivot->num_of_points_ &&
|
||||
point_right[max_range_dimension] >= pivot_value) {
|
||||
UpdateHyperRectangle(point_right, hr_right);
|
||||
right_points++;
|
||||
point_right = data_->At(right_start - right_points);
|
||||
}
|
||||
if (point_left > point_right || right_points == pivot->num_of_points_) {
|
||||
break;
|
||||
}
|
||||
data_->Swap(left_start+left_points, right_start - right_points);
|
||||
}
|
||||
DEBUG_ASSERT(left_points+right_points == right_start - left_start+1);
|
||||
FindPivotDimensionValue(hr_left);
|
||||
FindPivotDimensionValue(hr_right);
|
||||
|
||||
PivotInfo* pv_left = new PivotInfo();
|
||||
pv_left->Init(left_start, left_points, hr_left);
|
||||
PivotInfo* pv_right = new PivotInfo();
|
||||
pv_right->Init(left_start+left_points, right_points, hr_right);
|
||||
return make_pair(pv_left, pv_right);
|
||||
}
|
||||
|
||||
PivotInfo *operator()(index_t num_of_points) {
|
||||
// make the parent
|
||||
HyperRectangle_t hr;
|
||||
hr.Init(data_->get_dimension());
|
||||
for(index_t i=0; i<num_of_points; i++) {
|
||||
Precision_t *point = data_->At(i);
|
||||
UpdateHyperRectangle(point, hr);
|
||||
}
|
||||
FindPivotDimensionValue(hr);
|
||||
PivotInfo *pv = new PivotInfo();
|
||||
pv->Init(0, num_of_points, hr);
|
||||
return pv;
|
||||
}
|
||||
|
||||
private:
|
||||
BinaryDataset<Precision_t> *data_;
|
||||
|
||||
void FindPivotDimensionValue(HyperRectangle_t &hr) {
|
||||
Precision_t max_range = 0;
|
||||
int32 max_range_dimension =0;
|
||||
for(int32 j=0; j<data_->get_dimension(); j++) {
|
||||
Precision_t range = hr.get_max()[j] - hr.get_min()[j];
|
||||
if (range > max_range) {
|
||||
max_range = range;
|
||||
max_range_dimension = j;
|
||||
}
|
||||
}
|
||||
hr.set_pivot_value((hr.get_max()[max_range_dimension] +
|
||||
hr.get_min()[max_range_dimension])/2);
|
||||
hr.set_pivot_dimension(max_range_dimension);
|
||||
}
|
||||
|
||||
void UpdateHyperRectangle(Precision_t *point,
|
||||
HyperRectangle_t &hr) {
|
||||
for(int32 j=0; j<data_.get_dimension(); j++) {
|
||||
if (point[j] > hr.get_max()[j]) {
|
||||
hr.get_max()[j] = point[j];
|
||||
}
|
||||
if (point[j] < hr.get_min()[j]) {
|
||||
hr.get_min()[j] = point[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // KD_PIVOTER_H_
|
||||
@@ -1,177 +0,0 @@
|
||||
#ifndef NODE_H_
|
||||
#define NODE_H_
|
||||
#include <new>
|
||||
#include <limits>
|
||||
#include "u/nvasil/loki/TypeTraits.h"
|
||||
#include "u/nvasil/loki/Typelist.h"
|
||||
#include "fastlib/fastlib.h"
|
||||
#include "point.h"
|
||||
#include "point_identity_discriminator.h"
|
||||
#include "computations_counter.h"
|
||||
#include "u/nvasil/dataset/binary_dataset.h"
|
||||
|
||||
template<typename TYPELIST,
|
||||
bool diagnostic>
|
||||
class Node {
|
||||
public:
|
||||
typedef typename TYPELIST::Precision_t Precision_t;
|
||||
typedef typename TYPELIST::Allocator_t Allocator_t;
|
||||
typedef typename TYPELIST::Metric_t Metric_t;
|
||||
typedef typename TYPELIST::BoundingBox_t BoundingBox_t;
|
||||
typedef typename TYPELIST::NodeCachedStatistics_t NodeCachedStatistics_t;
|
||||
typedef typename TYPELIST::PointIdDiscriminator_t PointIdDiscriminator_t;
|
||||
typedef typename Allocator_t::template ArrayPtr<Precision_t> Array_t;
|
||||
typedef Node<TYPELIST, diagnostic> Node_t;
|
||||
typedef typename Allocator_t::template Ptr<Node> NodePtr_t;
|
||||
typedef Point<Precision_t, Allocator_t> Point_t;
|
||||
template<typename , bool> friend class NodeTest;
|
||||
struct NNResult {
|
||||
NNResult() : point_id_(0),
|
||||
distance_(numeric_limits<Precision_t>::max()) {
|
||||
}
|
||||
bool operator<(const NNResult &other) const {
|
||||
if (point_id_==other.point_id_) {
|
||||
return distance_<other.distance_;
|
||||
} else {
|
||||
return point_id_<other.point_id_;
|
||||
}
|
||||
}
|
||||
Precision_t get_distance() const {
|
||||
return distance_;
|
||||
}
|
||||
index_t get_point_id() {
|
||||
return point_id_;
|
||||
}
|
||||
index_t point_id_;
|
||||
Point_t nearest_;
|
||||
Precision_t distance_;
|
||||
};
|
||||
class PairComparator {
|
||||
public:
|
||||
bool operator()(const pair<Precision_t, Point_t> &a,
|
||||
const pair<Precision_t, Point_t> &b) {
|
||||
return a.first<b.first;
|
||||
}
|
||||
};
|
||||
Node();
|
||||
// Use this for node
|
||||
void Init(const BoundingBox_t &box,
|
||||
const NodeCachedStatistics_t &statistics,
|
||||
index_t node_id,
|
||||
index_t num_of_points);
|
||||
// Use this for leaf
|
||||
void Init(const BoundingBox_t &box,
|
||||
const NodeCachedStatistics_t &statistics,
|
||||
index_t node_id,
|
||||
index_t start,
|
||||
index_t num_of_points,
|
||||
int32 dimension,
|
||||
BinaryDataset<Precision_t> *dataset);
|
||||
~Node();
|
||||
static void *operator new(size_t size);
|
||||
static void operator delete(void *p);
|
||||
bool IsLeaf() {
|
||||
return !points_.IsNULL();
|
||||
}
|
||||
template<typename POINTTYPE>
|
||||
pair<NodePtr_t, NodePtr_t>
|
||||
ClosestChild(POINTTYPE point,
|
||||
int32 dimension,
|
||||
ComputationsCounter<diagnostic> &comp);
|
||||
|
||||
pair<pair<NodePtr_t, Precision_t>,
|
||||
pair<NodePtr_t, Precision_t> >
|
||||
ClosestNode(NodePtr_t,
|
||||
NodePtr_t,
|
||||
int32 dimension,
|
||||
ComputationsCounter<diagnostic> &comp);
|
||||
|
||||
// This one is using a custom discriminator
|
||||
// We use this for timit experiments so that we exclude points
|
||||
// from the same speaker
|
||||
template<typename POINTTYPE, typename NEIGHBORTYPE>
|
||||
void FindNearest(POINTTYPE query_point,
|
||||
vector<pair<Precision_t, Point_t> > &nearest,
|
||||
NEIGHBORTYPE range,
|
||||
int32 dimension,
|
||||
PointIdDiscriminator_t &discriminator,
|
||||
ComputationsCounter<diagnostic> &comp);
|
||||
|
||||
// This one store the results directly on a memmory mapped file
|
||||
// for k-nearest neighbors and to a normal file for range nearest neighbors
|
||||
// very efficient for large datasets
|
||||
// Uses a custom descriminator
|
||||
template<typename NEIGHBORTYPE>
|
||||
void FindAllNearest(NodePtr_t query_node,
|
||||
Precision_t &max_neighbor_distance,
|
||||
NEIGHBORTYPE range,
|
||||
int32 dimension,
|
||||
PointIdDiscriminator_t &discriminator,
|
||||
ComputationsCounter<diagnostic> &comp);
|
||||
|
||||
NodePtr_t& get_left() {
|
||||
return left_;
|
||||
}
|
||||
NodePtr_t& get_right() {
|
||||
return right_;
|
||||
}
|
||||
BoundingBox_t &get_box() {
|
||||
return box_;
|
||||
}
|
||||
typename Allocator_t::template ArrayPtr<Point_t>& get_points() {
|
||||
return points_;
|
||||
}
|
||||
index_t get_num_of_points() {
|
||||
return num_of_points_;
|
||||
}
|
||||
|
||||
NNResult *get_kneighbors() {
|
||||
return kneighbors_;
|
||||
}
|
||||
void set_kneighbors(NNResult *chunk, uint32 knns) {
|
||||
kneighbors_=chunk;
|
||||
for(index_t i=0; i< num_of_points_; i++) {
|
||||
for(index_t j=0; j<(index_t)knns; j++) {
|
||||
kneighbors_[i*knns+j].point_id_ =
|
||||
index_[i];
|
||||
kneighbors_[i*knns+j].nearest_.
|
||||
set_id(numeric_limits<index_t>::max());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InitKNeighbors(int32 knns);
|
||||
|
||||
void set_range_neighbors(FILE *fp) {
|
||||
range_nn_fp_=fp;
|
||||
}
|
||||
FILE *get_range_nn_fp() {
|
||||
return range_nn_fp_;
|
||||
}
|
||||
Precision_t get_min_dist_so_far() {
|
||||
return min_dist_so_far_;
|
||||
}
|
||||
void set_min_dist_so_far(Precision_t distance) {
|
||||
min_dist_so_far_=distance;
|
||||
}
|
||||
string Print(int32 dimension);
|
||||
|
||||
private:
|
||||
BoundingBox_t box_;
|
||||
index_t node_id_;
|
||||
NodePtr_t left_;
|
||||
NodePtr_t right_;
|
||||
typename Allocator_t::template ArrayPtr<index_t> index_;
|
||||
typename Allocator_t::template ArrayPtr<Precision_t> points_;
|
||||
NodeCachedStatistics_t statistics_;
|
||||
index_t num_of_points_;
|
||||
union {
|
||||
NNResult *kneighbors_;
|
||||
FILE *range_nn_fp_;
|
||||
};
|
||||
Precision_t min_dist_so_far_;
|
||||
|
||||
};
|
||||
|
||||
#include "node_impl.h"
|
||||
#endif /*NODE_H_*/
|
||||
@@ -1,277 +0,0 @@
|
||||
#ifndef NODE_IMPL_H_
|
||||
#define NODE_IMPL_H_
|
||||
|
||||
#define TEMPLATE__ \
|
||||
template<typename TYPELIST, bool diagnostic>
|
||||
|
||||
#define NODE__ \
|
||||
Node<TYPELIST, diagnostic>
|
||||
|
||||
TEMPLATE__
|
||||
NODE__::Node() {
|
||||
left_.SetNULL();
|
||||
right_.SetNULL();
|
||||
points_.SetNULL();
|
||||
kneighbors_=NULL;
|
||||
node_id_ = numeric_limits<index_t>::max();
|
||||
min_dist_so_far_=numeric_limits<Precision_t>::max();
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void NODE__::Init(const BoundingBox_t &box,
|
||||
const NodeCachedStatistics_t &statistics,
|
||||
index_t node_id,
|
||||
index_t num_of_points) {
|
||||
box_.Alias(box);
|
||||
statistics_.Alias(statistics);
|
||||
node_id_ = node_id;
|
||||
num_of_points_ = num_of_points;
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void NODE__::Init(const typename NODE__::BoundingBox_t &box,
|
||||
const typename NODE__::NodeCachedStatistics_t &statistics,
|
||||
index_t node_id,
|
||||
index_t start,
|
||||
index_t num_of_points,
|
||||
int32 dimension,
|
||||
BinaryDataset<Precision_t> *dataset) {
|
||||
box_.Alias(box);
|
||||
statistics_.Alias(statistics);
|
||||
node_id_ = node_id;
|
||||
num_of_points_ = num_of_points;
|
||||
points_.Reset(Allocator_t::template malloc<Precision_t>
|
||||
(num_of_points_*dimension));
|
||||
index_.Reset(Allocator_t::template malloc<index_t>(num_of_points_));
|
||||
for(index_t i=start; i<start+num_of_points_; i++) {
|
||||
for(int32 j=0; j<dimension; j++) {
|
||||
points_[(i-start)*dimension+j]=dataset->At(i,j);
|
||||
}
|
||||
index_[i-start]=dataset->get_id(i);
|
||||
}
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
NODE__::~Node() {
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void *NODE__::operator new(size_t size) {
|
||||
return Allocator_t::allocator_->AllignedAlloc(size);
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void NODE__::operator delete(void *p) {
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
void NODE__::InitKNeighbors(int32 knns) {
|
||||
for(index_t i=0; i<num_of_points_; i++) {
|
||||
for(int32 j=0; j<knns; j++) {
|
||||
kneighbors_[i*knns+j].point_id_=index_[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
template<typename POINTTYPE>
|
||||
pair<typename NODE__::NodePtr_t, typename NODE__::NodePtr_t>
|
||||
NODE__::ClosestChild(POINTTYPE point, int32 dimension,
|
||||
ComputationsCounter<diagnostic> &comp) {
|
||||
return box_.ClosestChild(left_, right_, point, dimension, comp);
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
inline
|
||||
pair<pair<typename NODE__::NodePtr_t, typename NODE__::Precision_t>,
|
||||
pair<typename NODE__::NodePtr_t, typename NODE__::Precision_t> >
|
||||
NODE__::ClosestNode(typename NODE__::NodePtr_t ptr1,
|
||||
typename NODE__::NodePtr_t ptr2,
|
||||
int32 dimension,
|
||||
ComputationsCounter<diagnostic> &comp) {
|
||||
Precision_t dist1 = BoundingBox_t::Distance(box_, ptr1->get_box(),
|
||||
dimension, comp);
|
||||
Precision_t dist2 = BoundingBox_t::Distance(box_, ptr2->get_box(),
|
||||
dimension, comp);
|
||||
if (dist1<dist2) {
|
||||
return make_pair(make_pair(ptr1, dist1), make_pair(ptr2, dist2));
|
||||
} else {
|
||||
return make_pair(make_pair(ptr2,dist2), make_pair(ptr1, dist1));
|
||||
}
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
template<typename POINTTYPE, typename NEIGHBORTYPE>
|
||||
inline void NODE__::FindNearest(POINTTYPE query_point,
|
||||
vector<pair<typename NODE__::Precision_t,
|
||||
typename NODE__::Point_t> > &nearest,
|
||||
NEIGHBORTYPE range,
|
||||
int32 dimension,
|
||||
typename NODE__::PointIdDiscriminator_t &discriminator,
|
||||
ComputationsCounter<diagnostic> &comp) {
|
||||
|
||||
for(index_t i=0; i<num_of_points_; i++) {
|
||||
comp.UpdateDistances();
|
||||
// we have to check if we are comparing the point with itself
|
||||
if (unlikely(discriminator.AreTheSame(index_[i],
|
||||
query_point.get_id())==true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Precision_t dist = BoundingBox_t::
|
||||
template Distance(query_point,
|
||||
points_.get()+i*dimension,
|
||||
dimension);
|
||||
// In case it is range nearest neighbors
|
||||
if (Loki::TypeTraits<NEIGHBORTYPE>::isStdFloat==true) {
|
||||
if (dist<=range){
|
||||
Point_t point;
|
||||
point.Alias(points_.get()+i*dimension, index_[i]);
|
||||
nearest.push_back(make_pair(dist, point));
|
||||
}
|
||||
} else {
|
||||
// for k nearest neighbors
|
||||
Point_t point;
|
||||
point.Alias(points_.get()+i*dimension, index_[i]);
|
||||
nearest.push_back(make_pair(dist, point));
|
||||
}
|
||||
}
|
||||
|
||||
// for k-nearest neighbors
|
||||
if (Loki::TypeTraits<NEIGHBORTYPE>::isStdFloat==false) {
|
||||
typename std::vector<pair<Precision_t, Point_t> >::iterator it;
|
||||
//it=nearest.begin()+(index_t)range;
|
||||
index_t j=0;
|
||||
for(it=nearest.begin(), j=0; j<(index_t)range; j++) {
|
||||
it++;
|
||||
}
|
||||
std::sort(nearest.begin(),
|
||||
nearest.end(),
|
||||
PairComparator());
|
||||
if (likely(nearest.size()>(uint32)range)) {
|
||||
nearest.erase(it, nearest.end());
|
||||
} else {
|
||||
pair<Precision_t, Point_t> dummy;
|
||||
dummy.first=numeric_limits<Precision_t>::max();
|
||||
index_t extra_size=(index_t)(range-nearest.size());
|
||||
for(index_t i=0; i<extra_size; i++) {
|
||||
nearest.push_back(dummy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
template<typename NEIGHBORTYPE>
|
||||
inline void NODE__::FindAllNearest(
|
||||
NodePtr_t query_node,
|
||||
typename NODE__::Precision_t &max_neighbor_distance,
|
||||
NEIGHBORTYPE range,
|
||||
int32 dimension,
|
||||
typename NODE__::PointIdDiscriminator_t &discriminator,
|
||||
ComputationsCounter<diagnostic> &comp) {
|
||||
printf("%u--%u\n", query_node->get_node_id(), node_id_);
|
||||
Precision_t max_local_distance = numeric_limits<Precision_t>::min();
|
||||
for(index_t i=0; i<query_node->num_of_points_; i++) {
|
||||
Precision_t distance;
|
||||
// for k nearest neighbors
|
||||
if (Loki::TypeTraits<NEIGHBORTYPE>::isStdFloat==false) {
|
||||
// get the current maximum distance for the specific point
|
||||
distance = query_node->kneighbors_[i*(int32)range+(int32)range-1].distance_;
|
||||
} else {
|
||||
distance=range;
|
||||
}
|
||||
// We should check whether this speeds up or slows down
|
||||
// the performance
|
||||
comp.UpdateComparisons();
|
||||
if (this->box_.CrossesBoundaries(query_node->points_.get()+i*dimension,
|
||||
dimension,
|
||||
distance,
|
||||
comp)) {
|
||||
// for k nearest neighbors
|
||||
if (Loki::TypeTraits<NEIGHBORTYPE>::isStdFloat==false) {
|
||||
vector<pair<Precision_t, Point_t> > temp((index_t)range);
|
||||
for(int32 j=0; j<range; j++) {
|
||||
temp[j].first=query_node->kneighbors_[i*(index_t)range+j].distance_;
|
||||
temp[j].second=query_node->kneighbors_[i*(index_t)range+j].nearest_;
|
||||
}
|
||||
Point_t point;
|
||||
point.Alias(query_node->points_.get()+i*dimension,
|
||||
query_node->index_[i]);
|
||||
FindNearest(point, temp,
|
||||
range, dimension,
|
||||
discriminator, comp);
|
||||
DEBUG_ASSERT_MSG((index_t)temp.size()==range,
|
||||
"During %i-nn seach, returned %u results",(int)range,
|
||||
(unsigned int)temp.size());
|
||||
|
||||
|
||||
for(int32 j=0; j<(index_t)range; j++) {
|
||||
query_node->kneighbors_[i*(index_t)range+j].distance_=temp[j].first;
|
||||
query_node->kneighbors_[i*(index_t)range+j].nearest_=temp[j].second;
|
||||
}
|
||||
// Estimate the maximum nearest neighbor distance
|
||||
comp.UpdateComparisons();
|
||||
if (max_local_distance < temp.back().first) {
|
||||
max_local_distance = temp.back().first;
|
||||
}
|
||||
} else {
|
||||
// for range nearest neighbors
|
||||
vector<pair<Precision_t, Point_t> > temp;
|
||||
temp.clear();
|
||||
Point_t point;
|
||||
point.Alias(query_node->points_.get()+i*dimension,
|
||||
query_node->index_[i]);
|
||||
FindNearest(point, temp,
|
||||
range, dimension,
|
||||
discriminator, comp);
|
||||
for(index_t j=0; j<(index_t)temp.size(); j++) {
|
||||
NNResult result;
|
||||
result.point_id_=query_node->index_[i];
|
||||
result.nearest_.Alias(temp[j].second);
|
||||
result.distance_=temp[j].first;
|
||||
if (fwrite(&result, sizeof(NNResult), 1, range_nn_fp_)!=1) {
|
||||
FATAL("Error while writing range nearest neighbors: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Loki::TypeTraits<NEIGHBORTYPE>::isStdFloat==true) {
|
||||
max_local_distance=range;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEMPLATE__
|
||||
string NODE__::Print(int32 dimension) {
|
||||
char buf[8192];
|
||||
string str;
|
||||
if (!IsLeaf()) {
|
||||
sprintf(buf, "Node: %llu\n", (unsigned long long)node_id_);
|
||||
str.append(buf);
|
||||
} else {
|
||||
sprintf(buf, "Leaf: %llu\n", (unsigned long long)node_id_);
|
||||
str.append(buf);
|
||||
}
|
||||
str.append(box_.Print(dimension));
|
||||
str.append("num_of_points: ");
|
||||
sprintf(buf,"%llu\n", (unsigned long long)num_of_points_);
|
||||
str.append(buf);
|
||||
if (IsLeaf()) {
|
||||
for(index_t i=0; i<num_of_points_; i++) {
|
||||
for(int32 j=0; j<dimension; j++) {
|
||||
sprintf(buf,"%lg ", points_[i*dimension+j]);
|
||||
str.append(buf);
|
||||
}
|
||||
sprintf(buf, "-%llu \n",(unsigned long long) index_[i]);
|
||||
str.append(buf);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
#undef TEMPLATE__
|
||||
#undef NODE__
|
||||
#endif /*NODE_IMPL_H_*/
|
||||
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: node_unit.cc
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 04/23/2007 10:19:28 AM EDT
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Nikolaos Vasiloglou (NV), nvasil@ieee.org
|
||||
* Company: Georgia Tech Fastlab-ESP Lab
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
#include "u/nvasil/loki/Typelist.h"
|
||||
#include "fastlib/fastlib.h"
|
||||
#include "u/nvasil/mmanager/memory_manager.h"
|
||||
#include "u/nvasil/dataset/binary_dataset.h"
|
||||
#include "hyper_rectangle.h"
|
||||
#include "euclidean_metric.h"
|
||||
#include "null_statistics.h"
|
||||
#include "point_identity_discriminator.h"
|
||||
#include "computations_counter.h"
|
||||
#include "node.h"
|
||||
|
||||
template<typename TYPELIST, bool diagnostic>
|
||||
class NodeTest {
|
||||
public:
|
||||
typedef typename TYPELIST::Precision_t Precision_t;
|
||||
typedef typename TYPELIST::Allocator_t Allocator_t;
|
||||
typedef typename TYPELIST::Metric_t Metric_t;
|
||||
typedef HyperRectangle<TYPELIST, diagnostic> HyperRectangle_t;
|
||||
struct NodeParameters : public TYPELIST {
|
||||
typedef HyperRectangle_t BoundingBox_t;
|
||||
typedef NullStatistics NodeCachedStatistics_t;
|
||||
typedef SimpleDiscriminator PointIdDescriminator_t;
|
||||
};
|
||||
typedef Node<NodeParameters, diagnostic> Node_t;
|
||||
typedef typename Allocator_t:: template ArrayPtr<Precision_t> Array_t;
|
||||
typedef Point<Precision_t, Loki::NullType> Point_t;
|
||||
NodeTest() {
|
||||
}
|
||||
~NodeTest() {
|
||||
}
|
||||
void Init() {
|
||||
dimension_=2;
|
||||
num_of_points_=30;
|
||||
Allocator_t::allocator_ = new Allocator_t();
|
||||
Allocator_t::allocator_->Initialize();
|
||||
Array_t min(dimension_);
|
||||
min[0]=-1;
|
||||
min[1]=-1;
|
||||
Array_t max(dimension_);
|
||||
max[0]=1;
|
||||
max[1]=1;
|
||||
data_file_="data";
|
||||
dataset_.Init(data_file_, num_of_points_, dimension_);
|
||||
for(index_t i=0; i<num_of_points_; i++) {
|
||||
dataset_.At(i)[0]=Precision_t(rand())/RAND_MAX;
|
||||
dataset_.At(i)[1]=Precision_t(-rand())/RAND_MAX;
|
||||
dataset_.set_id(i,i);
|
||||
}
|
||||
hyper_rectangle_.Init(min, max, 0, 0);
|
||||
NullStatistics statistics;
|
||||
// typename Node_t::NodeCachedStatistics_t statistics;
|
||||
node_.Reset(new Node_t);
|
||||
node_->Init(hyper_rectangle_,
|
||||
statistics,
|
||||
0,
|
||||
0,
|
||||
num_of_points_,
|
||||
dimension_,
|
||||
&dataset_);
|
||||
}
|
||||
void Destruct() {
|
||||
hyper_rectangle_.Destruct();
|
||||
delete Allocator_t::allocator_;
|
||||
dataset_.Destruct();
|
||||
unlink(data_file_.c_str());
|
||||
unlink(data_file_.append(".ind").c_str());
|
||||
}
|
||||
|
||||
void FindNearest() {
|
||||
printf("Testing find nearest\n");
|
||||
SimpleDiscriminator discriminator;
|
||||
vector<pair<Precision_t, Point<Precision_t, Allocator_t> > > nearest;
|
||||
ComputationsCounter<diagnostic> comp;
|
||||
for(index_t i=0; i<num_of_points_; i++) {
|
||||
Point_t query_point;
|
||||
query_point.Alias(dataset_.At(i), dataset_.get_id(i));
|
||||
nearest.clear();
|
||||
node_->FindNearest(query_point,
|
||||
nearest,
|
||||
1,
|
||||
dimension_,
|
||||
discriminator,
|
||||
comp);
|
||||
Precision_t min_dist=numeric_limits<Precision_t>::max();
|
||||
index_t min_id=0;
|
||||
for(index_t j=0; j<num_of_points_; j++) {
|
||||
if (unlikely(dataset_.get_id(j)==dataset_.get_id(i))) {
|
||||
continue;
|
||||
}
|
||||
Precision_t distance = HyperRectangle_t::Distance(dataset_.At(i),
|
||||
dataset_.At(j),
|
||||
dimension_);
|
||||
if (distance<min_dist) {
|
||||
min_id=j;
|
||||
min_dist=distance;
|
||||
}
|
||||
}
|
||||
DEBUG_ASSERT_MSG(min_dist==nearest[0].first,
|
||||
"Something wrong in the distance\n");
|
||||
DEBUG_ASSERT_MSG(min_id==nearest[0].second.get_id(),
|
||||
"Something wrong in the distance\n");
|
||||
}
|
||||
}
|
||||
void FindAllNearest() {
|
||||
printf("Testing find all nearest\n");
|
||||
typename Node_t::NNResult result[num_of_points_];
|
||||
node_->set_kneighbors(result, 1);
|
||||
Precision_t max_neighbor_distance=numeric_limits<Precision_t>::max();
|
||||
SimpleDiscriminator discriminator;
|
||||
ComputationsCounter<diagnostic> comp;
|
||||
node_->FindAllNearest(node_,
|
||||
max_neighbor_distance,
|
||||
1,
|
||||
dimension_,
|
||||
discriminator,
|
||||
comp);
|
||||
for(index_t i=0; i<num_of_points_; i++) {
|
||||
Precision_t min_dist=numeric_limits<Precision_t>::max();
|
||||
index_t min_id=0;
|
||||
for(index_t j=0; j<num_of_points_; j++) {
|
||||
if (unlikely(dataset_.get_id(j)==dataset_.get_id(i))) {
|
||||
continue;
|
||||
}
|
||||
Precision_t distance = HyperRectangle_t::Distance(dataset_.At(i),
|
||||
dataset_.At(j),
|
||||
dimension_);
|
||||
if (distance<min_dist) {
|
||||
min_id=j;
|
||||
min_dist=distance;
|
||||
}
|
||||
}
|
||||
DEBUG_ASSERT_MSG(min_dist==result[i].distance_,
|
||||
"Something wrong in the distance\n");
|
||||
DEBUG_ASSERT_MSG(min_id==result[i].nearest_.get_id(),
|
||||
"Something wrong in the distance\n");
|
||||
}
|
||||
}
|
||||
|
||||
void TestAll(){
|
||||
Init();
|
||||
FindNearest();
|
||||
Destruct();
|
||||
Init();
|
||||
FindAllNearest();
|
||||
Destruct();
|
||||
}
|
||||
|
||||
private:
|
||||
typename Allocator_t:: template Ptr<Node_t> node_;
|
||||
string data_file_;
|
||||
HyperRectangle_t hyper_rectangle_;
|
||||
BinaryDataset<Precision_t> dataset_;
|
||||
index_t num_of_points_;
|
||||
int32 dimension_;
|
||||
|
||||
};
|
||||
|
||||
struct BasicParameters{
|
||||
typedef float32 Precision_t;
|
||||
typedef MemoryManager<false> Allocator_t;
|
||||
typedef EuclideanMetric<float32> Metric_t;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
NodeTest<BasicParameters, false> node_test;
|
||||
node_test.TestAll();
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
#ifndef POINT_H_
|
||||
#define POINT_H_
|
||||
#include <new>
|
||||
#include <string>
|
||||
#include "u/nvasil/loki/NullType.h"
|
||||
#include "fastlib/fastlib.h"
|
||||
|
||||
template<typename PRECISION, typename ALLOCATOR>
|
||||
class Point {
|
||||
public:
|
||||
typedef PRECISION Precision_t;
|
||||
typedef ALLOCATOR Allocator_t;
|
||||
typedef Point<Precision_t, Allocator_t> Point_t;
|
||||
Point() {
|
||||
this->p_.Reset(NULL);
|
||||
this->id_=0;
|
||||
};
|
||||
void *operator new(size_t size) {
|
||||
return Allocator_t::allocator->AllignedAlloc(size);
|
||||
}
|
||||
void operator delete(void *p) {
|
||||
}
|
||||
|
||||
void Init(int32 dim) {
|
||||
p_.Reset(Allocator_t::template calloc<Precision_t>(dim, 0));
|
||||
}
|
||||
Precision_t &operator[](index_t i) {
|
||||
return p_[i];
|
||||
}
|
||||
void Alias(const Point_t &point) {
|
||||
this->p_ = point.p_;
|
||||
this->id_ = point.id_;
|
||||
}
|
||||
|
||||
void Alias(Precision_t *ptr, index_t point_id) {
|
||||
this->p_.Reset(ptr);
|
||||
this->id_=point_id;
|
||||
}
|
||||
template<typename POINTTYPE>
|
||||
void Copy(POINTTYPE point, int32 dimension) {
|
||||
for(int32 i=0; i<dimension; i++) {
|
||||
p_[i] = point[i];
|
||||
}
|
||||
}
|
||||
|
||||
void Copy(Point_t point, int32 dimension) {
|
||||
for(int32 i=0; i<dimension; i++) {
|
||||
p_[i] = point[i];
|
||||
}
|
||||
id_=point.id_;
|
||||
}
|
||||
void SetNULL() {
|
||||
p_=NULL;
|
||||
}
|
||||
void Print(int32 dimension) {
|
||||
printf("values= ");
|
||||
for(int32 i=0; i< dimension; i++) {
|
||||
printf("%lg ", (double)this->operator[](i));
|
||||
}
|
||||
printf("; id="LI, id_);
|
||||
}
|
||||
index_t get_id() {
|
||||
return id_;
|
||||
}
|
||||
void set_id(index_t id) {
|
||||
id_ = id;
|
||||
}
|
||||
|
||||
private:
|
||||
typename Allocator_t::template ArrayPtr<Precision_t> p_;
|
||||
index_t id_;
|
||||
};
|
||||
|
||||
// use this for points where you don't care about the allocator
|
||||
// this class stands only as alias to other types
|
||||
template<typename PRECISION>
|
||||
class Point<PRECISION, Loki::NullType> {
|
||||
public:
|
||||
typedef PRECISION Precision_t;
|
||||
typedef Point<Precision_t, Loki::NullType> Point_t;
|
||||
Point() {
|
||||
this->p_=NULL;
|
||||
this->id_=0;
|
||||
};
|
||||
Precision_t &operator[](index_t i) {
|
||||
return p_[i];
|
||||
}
|
||||
void Alias(const Point_t &point) {
|
||||
this->p_ = point.p_;
|
||||
this->id_ = point.id_;
|
||||
}
|
||||
void Alias(Precision_t *ptr, index_t id) {
|
||||
p_=ptr;
|
||||
id_=id;
|
||||
}
|
||||
template<typename POINTTYPE>
|
||||
void Copy(POINTTYPE point, int32 dimension) {
|
||||
for(int32 i=0; i<dimension; i++) {
|
||||
p_[i] = point[i];
|
||||
}
|
||||
}
|
||||
void Copy(Point_t point, int32 dimension) {
|
||||
for(int32 i=0; i<dimension; i++) {
|
||||
p_[i] = point[i];
|
||||
}
|
||||
id_=point.id_;
|
||||
}
|
||||
void SetNULL() {
|
||||
p_=NULL;
|
||||
}
|
||||
void Print(int32 dimension) {
|
||||
printf("values= ");
|
||||
for(int32 i=0; i< dimension; i++) {
|
||||
printf("%lg ", (double)this->operator[](i));
|
||||
}
|
||||
printf("; id="LI, id_);
|
||||
}
|
||||
index_t get_id() {
|
||||
return id_;
|
||||
}
|
||||
void set_id(index_t id) {
|
||||
id_ = id;
|
||||
}
|
||||
|
||||
private:
|
||||
Precision_t *p_;
|
||||
index_t id_;
|
||||
};
|
||||
|
||||
template<class PRECISION>
|
||||
class CompletePoint {
|
||||
public:
|
||||
typedef PRECISION Precision_t;
|
||||
typedef CompletePoint<Precision_t> CompletePoint_t;
|
||||
CompletePoint() {}
|
||||
~CompletePoint(){}
|
||||
CompletePoint(const CompletePoint_t &other) {
|
||||
this->p_=other.p_;
|
||||
this->id_=other.id_;
|
||||
this->dimension_=other.dimension_;
|
||||
dd return *this;
|
||||
}
|
||||
CompletePoint_t &operator=(const CompletePoint_t &other) {
|
||||
DEBUG_ASSERT_MSG(this->dimension_==other.dimension_,
|
||||
"Points have different dimensions "LI"!="LI"",
|
||||
this->dimension_, other.dimension_);
|
||||
memcpy(this->p_, other.p_, dimension_*sizeof(Precision_t));
|
||||
this->id_=other.id_;
|
||||
}
|
||||
void Alias(Precision_t *ptr, index_t id, int32 dimension) {
|
||||
p_=ptr;
|
||||
id_=id;
|
||||
dimension_=dimension;
|
||||
}
|
||||
private:
|
||||
Precision_t *p_;
|
||||
index_t id_;
|
||||
int32 dimension_;
|
||||
};
|
||||
|
||||
#endif /*POINT_H_*/
|
||||
@@ -1,186 +0,0 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: tree.h
|
||||
*
|
||||
* Description: A generic multidimensional binary tree. Currently tested under
|
||||
* kd-nodes and ball-nodes
|
||||
*
|
||||
* Version: 2.0
|
||||
* Created: 02/09/2007 08:25:15 PM EST
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Nikolaos Vasiloglou (NV), nvasil@ieee.org
|
||||
* Company: This material is property of Georgia Tech Fastlab-ESP Lab,
|
||||
* and it is not for distribution
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef TREE_H_
|
||||
#define TREE_H_
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include "loki/Typelist.h"
|
||||
#include "fastlib/fastlib.h"
|
||||
#include "show_progress.h"
|
||||
|
||||
template<typename TYPELIST, bool diagnostic>
|
||||
class BinaryTree {
|
||||
public:
|
||||
// For testing purposes only
|
||||
friend class BinaryTreeTest;
|
||||
typedef Loki::TL::TypeAt<TYPELIST, 0>::Result Precision_t;
|
||||
typedef Loki::TL::TypeAt<TYPELIST, 1>::Result Allocator_t;
|
||||
typedef Loki::TL::TypeAt<TYPELIST, 2>::Result Metric_t;
|
||||
typedef Loki::TL::TypeAt<TYPELIST, 3>::Result BoundingBox_t;
|
||||
typedef Loki::TL::TypeAt<TYPELIST, 4>::Result NodeCachedStatistics_t;
|
||||
typedef Allocator_t::template ArrayPtr<Precision_t> Array_t;
|
||||
typedef Node<TYPELIST, diagnostic> Node_t;
|
||||
typedef Allocator_t::template Ptr<Node> NodePtr_t;
|
||||
typedef Point<Precision_t, Allocator_t> Point_t;
|
||||
typedef Node_t::Result Result_t;
|
||||
typedef BinaryTree<TYPELIST, bool> BinaryTree_t;
|
||||
class OutPutAllocator {
|
||||
public:
|
||||
OutPutAllocator() {
|
||||
num_=0;
|
||||
}
|
||||
void set_ptr(Result_t *ptr) {
|
||||
ptr_=ptr;
|
||||
}
|
||||
Result_t *get_ptr() {
|
||||
return ptr_;
|
||||
}
|
||||
Result_t *Allocate(int32 num_of_points, int32 range) {
|
||||
Result_t *result=ptr_+num_;
|
||||
num_+=range*num_of_points;
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
Result_t *ptr_;
|
||||
IDPRECISION num_;
|
||||
|
||||
};
|
||||
BinaryTree();
|
||||
~BinaryTree();
|
||||
void Init(BinaryDataset &data);
|
||||
// Call this function to build Depth first a tree
|
||||
void BuildDepthFirst();
|
||||
void BuildDepthFirst(Node_ptr &ptr, Pivot_t *pivot);
|
||||
void BuildBreadthFirst();
|
||||
void BuildBreadthFirst(list<pair<Node_ptr_ptr, Pivot_t *> > &fifo);
|
||||
// Builds tree k depth first. It builds all the subtrees depth first up to k level
|
||||
void SerialBuildKDepthFirst();
|
||||
template<typename POINTTYPE, typename NEIGHBORTYPE>
|
||||
void NearestNeighbor(POINTTYPE &test_point,
|
||||
vector<pair<Precision_t, Point_t> > *nearest_point,
|
||||
Precisio_t *distance,
|
||||
NEIGHBORTYPE range);
|
||||
|
||||
// This is the core function doing the recursion, Use that only if you want
|
||||
// to start the search from a particular node and not the parent
|
||||
template<typename POINTTYPE, typename NEIGHBORTYPE>
|
||||
void NearestNeighbor(Node_ptr ptr,
|
||||
POINTTYPE &test_point,
|
||||
vector<pair<Precision_t, Point_t> > *nearest_point,
|
||||
Precision_t *distance,
|
||||
NEIGHBORTYPE range,
|
||||
bool &found);
|
||||
|
||||
// This is the duall tree nearest neighbors method, again it works
|
||||
// for all cases k nearest/ range nearest
|
||||
template<typename NEIGHBORTYPE>
|
||||
void AllNearestNeighbors(Node_ptr query,
|
||||
Node_ptr reference,
|
||||
NEIGHBORTYPE range);
|
||||
template<typename NEIGHBORTYPE>
|
||||
void AllNearestNeighbors(Node_ptr query,
|
||||
Node_ptr reference,
|
||||
NEIGHBORTYPE range,
|
||||
PRECISION distance);
|
||||
void InitAllKNearestNeighborOutput(string file, int32 knns);
|
||||
void CloseAllKNearestNeighborOutput(int32 knns);
|
||||
void InitAllKNearestNeighborOutput(Node_ptr ptr,
|
||||
int32 knns);
|
||||
void InitAllRangeNearestNeighborOutput(string file, int32 range);
|
||||
void CloseAllRangeNearestNeighborOutput(int32 range);
|
||||
void InitAllRangeNearestNeighborOutput(Node_ptr ptr,
|
||||
int32 range);
|
||||
|
||||
|
||||
// Print the tree depth first
|
||||
void Print();
|
||||
void RecursivePrint(Node_ptr ptr);
|
||||
// Resets the counters of the tree that keep the statistics of search
|
||||
void ResetCounters() {
|
||||
computations_.Reset();
|
||||
}
|
||||
string Statistics();
|
||||
string Computations();
|
||||
void set_log_file(const string &log_file);
|
||||
int32 get_current_level() {
|
||||
return current_level_;
|
||||
};
|
||||
uint64 get_num_of_points(){
|
||||
return num_of_points_;
|
||||
}
|
||||
Node_ptr get_parent() {
|
||||
return parent_;
|
||||
}
|
||||
void set_discriminator(PointIdentityDiscriminator<IDPRECISION> *disc) {
|
||||
discriminator_.reset(disc);
|
||||
}
|
||||
void set_max_points_on_leaf(index_t max_point_on_leaf) {
|
||||
max_points_on_leaf_=max_points_on_leaf;
|
||||
}
|
||||
index_t get_max_points_on_leaf() {
|
||||
return max_points_on_leaf();
|
||||
}
|
||||
private:
|
||||
// Maximum number of points on a leaf
|
||||
index_t max_points_on_leaf_;
|
||||
// Parent/Root
|
||||
Node_ptr parent_;
|
||||
// Source of data
|
||||
BinaryDataset data_;
|
||||
// Total number of points on the tree
|
||||
index_t num_of_points_;
|
||||
// Number of Leafs on the tree
|
||||
index_t num_of_leafs_;
|
||||
// Number of nodes (incuding leafs)
|
||||
index_t node_id_;
|
||||
// Current level of tree while we build it
|
||||
index_t current_level_;
|
||||
// Maximum depth of the tree
|
||||
index_t max_depth_;
|
||||
// Minimum depth of the tree
|
||||
index_t min_depth_;
|
||||
// Dimensionality of points
|
||||
int32 dimension_;
|
||||
// Total number of points visited during search
|
||||
index_t total_nodes_visited_;
|
||||
// Structure for keeping statistics on the comparisons and distances computed
|
||||
// during search
|
||||
ComputationsCounter<diagnostic> computations_;
|
||||
// total number of nodes visited
|
||||
index_t total_points_visited_;
|
||||
// used for visualization of progress during tree build
|
||||
ShowProgress progress_;
|
||||
bool log_progress_;
|
||||
// Output file for All nearest neighbors
|
||||
OutPutAllocator all_nn_out_;
|
||||
FILE *log_file_ptr_;
|
||||
string log_file_;
|
||||
// This is usefull for our timit experiments
|
||||
boost::scoped_ptr<PointIdentityDiscriminator<IDPRECISION> >
|
||||
discriminator_;
|
||||
};
|
||||
#include "tree_impl.h"
|
||||
#endif /*TREE_H_*/
|
||||
Reference in New Issue
Block a user