From 0ee227b0fcf80a54f9a4a8a327e7ab0614eefb4e Mon Sep 17 00:00:00 2001 From: gmravi2003 Date: Tue, 22 Jan 2008 03:47:32 +0000 Subject: [PATCH] Fully Commented and refurbished --- fastlib/u/gmravi/allknn/allknn.h | 989 +++++++++++++------------ fastlib/u/gmravi/allknn/allknn_main.cc | 2 +- 2 files changed, 502 insertions(+), 489 deletions(-) diff --git a/fastlib/u/gmravi/allknn/allknn.h b/fastlib/u/gmravi/allknn/allknn.h index 2a6b23c2f2..b86b888372 100644 --- a/fastlib/u/gmravi/allknn/allknn.h +++ b/fastlib/u/gmravi/allknn/allknn.h @@ -59,7 +59,7 @@ class AllNNNaive{ Matrix& get_reference_set(){ - return r_matrix_; + return r_matrix_; } ArrayList& get_results(){ @@ -77,15 +77,15 @@ class AllNNNaive{ //Destructor - ~AllNNNaive(){ + ~AllNNNaive(){ } /** This function will simply load the query files - * and the reference files specified by the user - * into matrices - */ + * and the reference files specified by the user + * into matrices + */ void Init(Matrix &q_matrix, Matrix &r_matrix) { //First Copy the dataset @@ -106,8 +106,8 @@ class AllNNNaive{ } /** This does the naive computation of comparing the - * query point to all the reference points - */ + * query point to all the reference points + */ void ComputeAllNNNaive() { @@ -164,13 +164,13 @@ class AllNNSingleTree{ public: - //forward declaration sof class + //forward declaration sof class class SingleTreeResults; /** This class will hold the index of the nearest neighbour reference point * and the distance of the nearest neighbour to the query point - */ + */ class SingleTreeResults{ @@ -228,7 +228,7 @@ class AllNNSingleTree{ -//Definition of AllNNSingleTree begins........................................ + //Definition of AllNNSingleTree begins................ public: @@ -262,7 +262,8 @@ class AllNNSingleTree{ //Interesting functions.... - /** This function simply loads the reference dataset and the query dataset into matrices + /** This function simply loads the reference dataset + * and the query dataset into matrices * and makes a tree form the reference dataset */ @@ -298,41 +299,44 @@ class AllNNSingleTree{ return true; } - //This is the function which will perform the actual single tree algorithm and spit the results + //This is the function which will perform the actual + //single tree algorithm and spit the results void ComputeAllNNSingleTree(){ - //For each point find out the nearest neighbour + //For each point find out the nearest neighbour - for(index_t q=0;qis_leaf()) { //find out the minimum distance by querying all points. - //Remember we need to find neighbours within the potential_distance estimate we have + //Remember we need to find neighbours within + //the potential_distance estimate we have for(index_t i=rnode->begin();iend();i++) { - double temp_dist=la::DistanceSqEuclidean(r_matrix_.n_rows(),r_matrix_.GetColumnPtr(i),point); + double temp_dist=la::DistanceSqEuclidean(r_matrix_.n_rows(), + r_matrix_.GetColumnPtr(i),point); //check_if_equal function is being called to //avoid comparison between the same points @@ -353,7 +359,8 @@ class AllNNSingleTree{ //that the query and reference sets //have no common points - if(check_if_equal(r_matrix_.GetColumnPtr(i),point,r_matrix.n_rows())==false && temp_dist < + if(check_if_equal(r_matrix_.GetColumnPtr(i),point, + r_matrix.n_rows())==false && temp_dist < potential_distance) { potential_distance=temp_dist; @@ -367,8 +374,11 @@ class AllNNSingleTree{ //This is not a leaf //so find the nearer node and the farther node - double min_distance_to_left_child=rnode->left()->bound().MinDistanceSq(point); - double min_distance_to_right_child=rnode->right()->bound().MinDistanceSq(point); + double min_distance_to_left_child= + rnode->left()->bound().MinDistanceSq(point); + + double min_distance_to_right_child= + rnode->right()->bound().MinDistanceSq(point); double nearest_bb_distance=min_distance_to_left_child < @@ -403,7 +413,8 @@ class AllNNSingleTree{ if(potential_distance>farther->bound().MinDistanceSq(point)){ - FindNearestNeighbour(farther,point,r_matrix,potential_distance,potential_index); + FindNearestNeighbour(farther,point,r_matrix, + potential_distance,potential_index); } } @@ -436,7 +447,7 @@ class AllKNNSingleTree public: - //forward declaration sof class + //forward declaration sof class class AllKNSingleTreeResults; class AllKNNSingleTreeResults{ @@ -481,7 +492,7 @@ class AllKNNSingleTree }; //definition for AllKNNSingleTreeStat ends here......... -private: + private: Matrix q_matrix_; Matrix r_matrix_; @@ -491,7 +502,7 @@ private: public: //Constructor - AllKNNSingleTree() + AllKNNSingleTree() { } @@ -519,7 +530,7 @@ private: } - //interesting functions............................................................. + //interesting functions............................... ArrayList &get_results(){ @@ -564,31 +575,31 @@ private: temp_result.distance_sqd[i]=DBL_MAX; } - for(int i=0;iis_leaf()){ + if(rnode->is_leaf()){ - int position; + int position; - double dist; - int end; + double dist; + int end; - //length=0 => no neighbours have been found and hence end=-1 in such a case + //length=0 => no neighbours have been found and hence end=-1 in such a case - /*end points to the position where the arrays in the class - * AllKNNSingleTreeResults ends. - * That is it is the index of the last element - */ + /*end points to the position where the arrays in the class + * AllKNNSingleTreeResults ends. + * That is it is the index of the last element + */ - end=length-1; - for(int i=rnode->begin();iend();i++){ + end=length-1; + for(int i=rnode->begin();iend();i++){ - //one very important check is to see that - //query point is not the same point as any other point being compared + //one very important check is to see that + //query point is not the same point as any other point being compared - if(!check_if_equal(point,r_matrix->GetColumnPtr(i),r_matrix->n_rows())) - { - dist=la::DistanceSqEuclidean(r_matrix->n_rows(),point, - r_matrix->GetColumnPtr(i)); + if(!check_if_equal(point,r_matrix->GetColumnPtr(i),r_matrix->n_rows())) + { + dist=la::DistanceSqEuclidean(r_matrix->n_rows(),point, + r_matrix->GetColumnPtr(i)); - //find where the new element should be pushed + //find where the new element should be pushed - int start=0; + int start=0; - //find_index function findws what would be the position of the - // potential k-nearest neighbour which is at a distance dist as - //calculated above + //find_index function findws what would be the position of the + // potential k-nearest neighbour which is at a distance dist as + //calculated above - position=find_index(result,dist,start,end); + position=find_index(result,dist,start,end); - //push into array returns 1 if an element is pushable. - //an element is pushable if it is a possible knn + //push into array returns 1 if an element is pushable. + //an element is pushable if it is a possible knn - length+=push_into_array(result,position,dist,length,i,k_); - end=length-1; + length+=push_into_array(result,position,dist,length,i,k_); + end=length-1; - } - - } } + + } + } + else + { + //this is not a root node. Hence find + //the distance to the bounding boxes + + double min_distance_to_left_child= + rnode->left()->bound().MinDistanceSq(point); + double min_distance_to_right_child= + rnode->right()->bound().MinDistanceSq(point); + + double min_dist_to_bb=min_distance_to_left_child > + min_distance_to_right_child ? + min_distance_to_right_child : + min_distance_to_left_child; + + Tree *farther; + + //This condition considers further recursion only if all k nearest neighbours + //have not been found or if distance of the nearest bb + //is less than the distance of the kth nearest neighbour + + + if(lengthright(); + FindKNearestNeighbours(rnode->left(),point,r_matrix,result,length,k_); + } + + else{ + + //Recursively explore the right child + farther=rnode->left(); + FindKNearestNeighbours(rnode->right(),point,r_matrix,result,length,k_); + } + + //If number of neighbours found are less than + //k then go ahead and explore the other half too + + if(lengthleft()->bound().MinDistanceSq(point); - double min_distance_to_right_child=rnode->right()->bound().MinDistanceSq(point); - - double min_dist_to_bb=min_distance_to_left_child > - min_distance_to_right_child ? - min_distance_to_right_child : - min_distance_to_left_child; + //This means i have k nearest neighbours + //check the other half only if the kth nn distance is greater + //than the distance of the point form the farther bounding box - Tree *farther; - - //This condition considers further recursion only if all k nearest neighbours - //have not been found or if distance of the nearest bb - //is less than the distance of the kth nearest neighbour - - - if(lengthright(); - FindKNearestNeighbours(rnode->left(),point,r_matrix,result,length,k_); - } - - else{ - - //Recursively explore the right child - farther=rnode->left(); - FindKNearestNeighbours(rnode->right(),point,r_matrix,result,length,k_); - } - - //If number of neighbours found are less than - //k then go ahead and explore the other half too - - if(length farther->bound().MinDistanceSq(point)){ - FindKNearestNeighbours(farther,point,r_matrix,result,length,k_); - } - } - } + if(result.distance_sqd[k_-1]> farther->bound().MinDistanceSq(point)){ + FindKNearestNeighbours(farther,point,r_matrix,result,length,k_); + } } + } + } } /* This function finds where the element whose distance * is dist from the query point should be pushed in the array results */ - int find_index(AllKNNSingleTreeResults &result, - double dist,int start,int end){ + int find_index(AllKNNSingleTreeResults &result, + double dist,int start,int end){ - //this means that there are no elements in the array - if(start>end){ + //this means that there are no elements in the array + if(start>end){ - return 0; - } - - //this means there is exactly 1 element in the array - if(start==end) - { - - if(dist>result.distance_sqd[start]) - { - /* the element should be added to the back of the array*/ - - return end+1; - } - - else { - - return start; - } + return 0; } - // find where the element will be in the sorted array. - // This is just the binary search - - if(dist==result.distance_sqd[(start+end)/2]){ - printf("Will return %d \n",(start+end)/2); - return (start+end)/2; - } - - else - { + //this means there is exactly 1 element in the array + if(start==end) + { - if(distresult.distance_sqd[start]) + { + /* the element should be added to the back of the array*/ + + return end+1; + } + + else { + + return start; + } + } + + // find where the element will be in the sorted array. + // This is just the binary search + + if(dist==result.distance_sqd[(start+end)/2]){ + printf("Will return %d \n",(start+end)/2); + return (start+end)/2; + } + + else + { + + if(distposition;t--){ + + temp.distance_sqd[t]=result.distance_sqd[t-1]; + temp.index_of_neighbour[t]=result.index_of_neighbour[t-1]; + + } + //copy temp back to result + for(int j=0;jposition;t--){ + + temp.distance_sqd[t]=result.distance_sqd[t-1]; + temp.index_of_neighbour[t]=result.index_of_neighbour[t-1]; + } + + + for(int j=0;jposition;t--){ - - temp.distance_sqd[t]=result.distance_sqd[t-1]; - temp.index_of_neighbour[t]=result.index_of_neighbour[t-1]; - - } - //copy temp back to result - for(int j=0;jposition;t--){ - - temp.distance_sqd[t]=result.distance_sqd[t-1]; - temp.index_of_neighbour[t]=result.index_of_neighbour[t-1]; - } - - - for(int j=0;j (r_matrix_, LEAF_SIZE,NULL,NULL); @@ -1004,7 +1017,7 @@ class AllKNNDualTree{ temp[i].index_of_neighbour.Init(k_); temp[i].distance_sqd.Init(k_); - } + } //fill up the temporary variable first for(index_t i=0;i< q_matrix_.n_cols();i++){ @@ -1012,8 +1025,8 @@ class AllKNNDualTree{ temp[old_from_new[i]].distance_sqd[l]=results[i].distance_sqd[l]; temp[old_from_new[i]].index_of_neighbour[l]=results[i].index_of_neighbour[l]; - } - } + } + } //copy them back to results variable for(index_t i=0;i< q_matrix_.n_cols();i++){ @@ -1025,42 +1038,42 @@ class AllKNNDualTree{ } -void FindKNearestNeighboursDualTree(Tree *q_node,Tree *r_node) - { + void FindKNearestNeighboursDualTree(Tree *q_node,Tree *r_node) + { - //if distance between the two boxes is larger than the max _distance then return - double distance_between_boxes=q_node->bound().MinDistanceSq (r_node->bound()); + //if distance between the two boxes is larger than the max _distance then return + double distance_between_boxes=q_node->bound().MinDistanceSq (r_node->bound()); - //Base Case - if(q_node->is_leaf()&& r_node->is_leaf()) - { - int start,end; + //Base Case + if(q_node->is_leaf()&& r_node->is_leaf()) + { + int start,end; - //check if pruneable - if(q_node->stat().distance_max< distance_between_boxes) - { + //check if pruneable + if(q_node->stat().distance_max< distance_between_boxes) + { - return; - } - else - { - //not purneable. therefore carry out exhaustive point-to-point computations + return; + } + else + { + //not purneable. therefore carry out exhaustive point-to-point computations - double distance; - int position; + double distance; + int position; - for(int i=q_node->begin();iend();i++){ + for(int i=q_node->begin();iend();i++){ - //for each query point in the node + //for each query point in the node - for(int j=r_node->begin();jend();j++){ + for(int j=r_node->begin();jend();j++){ - //for each reference point in the reference node + //for each reference point in the reference node - if(!check_if_equal(q_matrix_.GetColumnPtr(i),r_matrix_.GetColumnPtr(j), - q_matrix_.n_rows())) + if(!check_if_equal(q_matrix_.GetColumnPtr(i),r_matrix_.GetColumnPtr(j), + q_matrix_.n_rows())) { distance=la::DistanceSqEuclidean (r_matrix_.n_rows(), @@ -1086,9 +1099,9 @@ void FindKNearestNeighboursDualTree(Tree *q_node,Tree *r_node) //increase the length of the results[i]. //This creates an additional pocket to hold an extra element - results[i].distance_sqd.AddBack(1); - results[i].index_of_neighbour.AddBack(1); - } + results[i].distance_sqd.AddBack(1); + results[i].index_of_neighbour.AddBack(1); + } //Note the length is still the old length, //the one that has been claulated in the step above. @@ -1100,233 +1113,233 @@ void FindKNearestNeighboursDualTree(Tree *q_node,Tree *r_node) } - //see if all knn have been found - if(results[i].distance_sqd.size()stat().distance_max=DBL_MAX; + q_node->stat().distance_max=DBL_MAX; + } + else { + + //all k nn have been found + q_node->stat().distance_max=q_node->stat().distance_max > + results[i].distance_sqd[k_-1]? + q_node->stat().distance_max: + results[i].distance_sqd[k_-1]; + + } } - else { - - //all k nn have been found - q_node->stat().distance_max=q_node->stat().distance_max > - results[i].distance_sqd[k_-1]? - q_node->stat().distance_max: - results[i].distance_sqd[k_-1]; - - } - } - } - } + } + } - //not base case. - else - { - //Check if one can Prune - if(q_node->stat().distance_max < distance_between_boxes) + //not base case. + else { - //then there is no need to go further and hence we can return - return; - } + //Check if one can Prune + if(q_node->stat().distance_max < distance_between_boxes) + { + //then there is no need to go further and hence we can return + return; + } - //NOT PRUNEABLE - //both are not leafs - if(!q_node->is_leaf() && !r_node->is_leaf()){ + //NOT PRUNEABLE + //both are not leafs + if(!q_node->is_leaf() && !r_node->is_leaf()){ - FindKNearestNeighboursDualTree(q_node->left(),r_node->left()); - FindKNearestNeighboursDualTree(q_node->left(),r_node->right()); + FindKNearestNeighboursDualTree(q_node->left(),r_node->left()); + FindKNearestNeighboursDualTree(q_node->left(),r_node->right()); - double max_dist_q_left= q_node->left()->stat().distance_max; + double max_dist_q_left= q_node->left()->stat().distance_max; - FindKNearestNeighboursDualTree(q_node->right(),r_node->left()); - FindKNearestNeighboursDualTree(q_node->right(),r_node->right()); + FindKNearestNeighboursDualTree(q_node->right(),r_node->left()); + FindKNearestNeighboursDualTree(q_node->right(),r_node->right()); - double max_dist_q_right= q_node->right()->stat().distance_max; + double max_dist_q_right= q_node->right()->stat().distance_max; - double max_dist_q=max_dist_q_left > - max_dist_q_right? - max_dist_q_left: - max_dist_q_right; + double max_dist_q=max_dist_q_left > + max_dist_q_right? + max_dist_q_left: + max_dist_q_right; - q_node->stat().distance_max=max_dist_q; - } + q_node->stat().distance_max=max_dist_q; + } - else{ + else{ - //q_tree is leaf and r_tree is not - if(q_node->is_leaf()&&!r_node->is_leaf()){ + //q_tree is leaf and r_tree is not + if(q_node->is_leaf()&&!r_node->is_leaf()){ - FindKNearestNeighboursDualTree(q_node,r_node->left()); - FindKNearestNeighboursDualTree(q_node,r_node->right()); - } + FindKNearestNeighboursDualTree(q_node,r_node->left()); + FindKNearestNeighboursDualTree(q_node,r_node->right()); + } - else - { - - //q_tree is not a leaf and r_tree is - - if(!q_node->is_leaf()&&r_node->is_leaf()) + else { + + //q_tree is not a leaf and r_tree is + + if(!q_node->is_leaf()&&r_node->is_leaf()) + { - FindKNearestNeighboursDualTree(q_node->left(),r_node); - double max_dist_q_left=q_node->left()->stat().distance_max; + FindKNearestNeighboursDualTree(q_node->left(),r_node); + double max_dist_q_left=q_node->left()->stat().distance_max; - FindKNearestNeighboursDualTree(q_node->right(),r_node); - double max_dist_q_right=q_node->right()->stat().distance_max; + FindKNearestNeighboursDualTree(q_node->right(),r_node); + double max_dist_q_right=q_node->right()->stat().distance_max; - double max_dist_q= max_dist_q_left> - max_dist_q_right? - max_dist_q_left: - max_dist_q_right; - q_node->stat().distance_max=max_dist_q; + double max_dist_q= max_dist_q_left> + max_dist_q_right? + max_dist_q_left: + max_dist_q_right; + q_node->stat().distance_max=max_dist_q; + } } } - } - } - } - - int find_index(AllKNNDualTreeResults &result,double dist,int start,int end){ - - //this means that there are no elements in the array - if(start>end){ - printf("will return 0..\n"); - return 0; - } - - //this means there is exactly 1 element in the array - if(start==end) - { - - if(dist>result.distance_sqd[start]) - { - /* the element should be added to the back of the array*/ - printf("will return %d\n",end+1); - return end+1; } - - else { - printf("return %d\n",start); - return start; - } } - //find where the element will be in the sorted array. - //This is just the binary search + int find_index(AllKNNDualTreeResults &result,double dist,int start,int end){ + + //this means that there are no elements in the array + if(start>end){ + printf("will return 0..\n"); + return 0; + } - if(dist==result.distance_sqd[(start+end)/2]){ - printf("Will return %d \n",(start+end)/2); - return (start+end)/2; - } - - else - { + //this means there is exactly 1 element in the array + if(start==end) + { - if(distresult.distance_sqd[start]) + { + /* the element should be added to the back of the array*/ + printf("will return %d\n",end+1); + return end+1; + } + + else { + printf("return %d\n",start); + return start; + } + } + + //find where the element will be in the sorted array. + //This is just the binary search + + if(dist==result.distance_sqd[(start+end)/2]){ + printf("Will return %d \n",(start+end)/2); + return (start+end)/2; + } + + else + { + + if(distposition;t--){ + + temp.distance_sqd[t]=result.distance_sqd[t-1]; + temp.index_of_neighbour[t]=result.index_of_neighbour[t-1]; + + } + //copy temp back to result + for(int j=0;jposition;t--){ + + temp.distance_sqd[t]=result.distance_sqd[t-1]; + temp.index_of_neighbour[t]=result.index_of_neighbour[t-1]; + } + + + for(int j=0;jposition;t--){ - - temp.distance_sqd[t]=result.distance_sqd[t-1]; - temp.index_of_neighbour[t]=result.index_of_neighbour[t-1]; - - } - //copy temp back to result - for(int j=0;jposition;t--){ - - temp.distance_sqd[t]=result.distance_sqd[t-1]; - temp.index_of_neighbour[t]=result.index_of_neighbour[t-1]; - } - - - for(int j=0;j number of nearest neighbours * * @see allknn.h -*/ + */ #include "allknn.h"