Files
mlpack/fastlib/u/nvasil/tree/old/tree.h
T
2007-04-28 16:15:38 +00:00

245 lines
9.6 KiB
C++

/*
* =====================================================================================
*
* 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 <unistd.h>
#include <fcntl.h>
#include <string>
#include <math.h>
#include <errno.h>
#include <string.h>
#include <list>
#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>
#include "base/basic_types.h"
#include "pivot_policy.h"
#include "show_progress.h"
#include "point_identity_discriminator.h"
// The tree operates on points that have precision PRECISION and a unique identifier
// of type IDPRECISION. The trees can use any type of memory managment defined by
// ALLOCATOR. ALLOCATOR can be disk-based, use cache or it can be distributed. It
// would be prefered to be a singleton structure although this is necessary.
// The minimum requirments are to implement the following types:
// ALLOCATOR::Ptr<typename T> It has to be assignable, copyable
// ALLOCATOR::ArrayPtr<typename T>
// ALLOCATOR::malloc<typename T>()
// ALLOCATOR::malloc<typename T>(size_t size)
// ALLOCATOR::calloc<typename T>(size_t size, T initial_value)
// For more information about the requirments of the ALLOCATOR look at documentation.
// NODE is the class that implements node and leafs on the tree. It is required
// to have the same PRECISION and IDPRECISION, ALLOCATOR as the tree that's why it is
// passed as a templage parameter. See documentation for the functions that NODE
// should implement. It is recomended that you derive NODE from class Node as described
// in node.h, see also kdnode.h as an example
// The bool diagnostic template parameter is provided as a parameter for the logging
// procedures on the tree
template<typename PRECISION,
typename IDPRECISION,
typename ALLOCATOR,
bool diagnostic,
template<typename PRECISION,
typename IDPRECISION,
typename ALLOCATOR,
bool diagnostic> class NODE>
class Tree {
public:
// For testing purposes only
friend class TreeTest;
// Some quick typedef definitions for making code more readable
typedef NODE<PRECISION, IDPRECISION, ALLOCATOR, diagnostic> Node_t;
typedef typename Node_t::Result Result_t;
typedef typename Node_t::BoundingBox_t BoundingBox_t;
// PivotPolicy is necessary for the tree building. For more inforamtion look at
// Andrew Moore's paper on kd-trees
typedef PivotPolicy<PRECISION,
IDPRECISION,
ALLOCATOR, Node_t, diagnostic> Policy_t;
typedef typename Policy_t::Pivot_t Pivot_t;
typedef typename ALLOCATOR::template Ptr<Node_t> Node_ptr;
typedef typename ALLOCATOR::template Ptr<typename
ALLOCATOR::template Ptr<Node_t> > Node_ptr_ptr;
typedef Tree<PRECISION, IDPRECISION, ALLOCATOR, diagnostic, NODE> Tree_t;
class OutPutAllocator {
public:
OutPutAllocator() {
num_=0;
}
void set_ptr(typename Node_t::Result *ptr) {
ptr_=ptr;
}
typename Node_t::Result *get_ptr() {
return ptr_;
}
typename Node_t::Result *Allocate(int32 num_of_points, int32 range) {
typename Node_t::Result *result=ptr_+num_;
num_+=range*num_of_points;
return result;
}
private:
typename Node_t::Result *ptr_;
IDPRECISION num_;
};
// Constructor, sets some tree parameters
// Data<PRECISION, IDPRECISION> *data is the source of data, it is not destroyed
// after the construction of the tree. It is a stream of points with their identifier
// value [ PRECISION PRECISION ..... IDPRECISION]
// dimension is the dimensionality of the data points
// num_of_points is the number of data_points
Tree(DataReader<PRECISION, IDPRECISION> *data,
int32 dimension, IDPRECISION num_of_points);
// Destructor
~Tree();
// Call this function to build Depth first a tree in a serial way
void SerialBuildDepthFirst();
// This is the function for the recursion of SerialBuildFirst
// It builds the subtree starting from ptr, based on the information
// provided by Pivot_t *pivot
void SerialBuildDepthFirst(Node_ptr &ptr, Pivot_t *pivot);
// Builds the tree depth first in a parallel way (not implemented yet)
void ParallelBuildDepthFirst();
void ParallelBuildDepthFirst(Node_ptr &ptr, Pivot_t *pivot);
// Call this function to build the tree breadth first
void SerialBuildBreadthFirst();
// Core function for breadth first build
void SerialBuildBreadthFirst(list<pair<Node_ptr_ptr, Pivot_t *> > &fifo);
// Not implemented yet
void ParallelBuildBreadthFirst();
void ParallelBuildBreadthFirst(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();
void ParallelBuildKDepthFirst();
// This function will return any of the nearest neighbors types
// k nearest, range nearest or just nearest, depending on how you
// call it. It seaches starting from the parent
// If RETURNTYPE is a point then it will return the nearest neighbor
// IF RETURNTYPE is a vector then it will return
// a) The range nearest neighbors if NEIGHBORTYPE is PRECISION
// b) the k nearest neigbors if NERIGBORTYPE is int32
// We recommend that when you call it you do explicit template parameter
// definition. If you leave it on the compiler you might accidently
// get the wrong results. It is much more error prone
template<typename POINTTYPE, typename RETURNTYPE, typename NEIGHBORTYPE>
void NearestNeighbor(POINTTYPE &test_point,
RETURNTYPE *nearest_point,
PRECISION *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 RETURNTYPE, typename NEIGHBORTYPE>
void NearestNeighbor(Node_ptr ptr,
POINTTYPE &test_point,
RETURNTYPE *nearest_point,
PRECISION *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);
// After you run AllNearestNeighbors, run this one to dump the nearest neigbors on
// a file
void PrintNeighbors(string filename);
void PrintNeighborsRecursive(Node_ptr ptr, FILE *fp);
// These are being used by All nn for efficient output of the data
// it turns out that most of the time is spent in collecting the
// results for output, while this one is writing directly on the output
void InitAllKNearestNeighborOutput(string file, int32 range);
void CloseAllKNearestNeighborOutput(int32 range);
void InitAllKNearestNeighborOutput(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);
}
private:
// Maximum number of points on a leaf
IDPRECISION max_points_on_leaf_;
// Parent/Root
Node_ptr parent_;
// Source of data
DataReader<PRECISION, IDPRECISION> *data_;
// Total number of points on the tree
IDPRECISION num_of_points_;
// Number of Leafs on the tree
IDPRECISION num_of_leafs_;
// Number of nodes (incuding leafs)
IDPRECISION node_id_;
// Current level of tree while we build it
IDPRECISION current_level_;
// Maximum depth of the tree
IDPRECISION max_depth_;
// Minimum depth of the tree
IDPRECISION min_depth_;
// Dimensionality of points
int32 dimension_;
// Total number of points visited during search
IDPRECISION total_nodes_visited_;
// Structure for keeping statistics on the comparisons and distances computed
// during search
ComputationsCounter<diagnostic> computations_;
// total number of nodes visited
IDPRECISION 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_*/