00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00039 #ifndef ORTHO_RANGE_SEARCH_H
00040 #define ORTHO_RANGE_SEARCH_H
00041
00042 #include "fastlib/fastlib.h"
00043 #include "contrib/dongryel/proximity_project/gen_kdtree.h"
00044 #include "contrib/dongryel/proximity_project/gen_kdtree_hyper.h"
00045 #include "contrib/dongryel/proximity_project/general_type_bounds.h"
00046
00060 template<typename T>
00061 class OrthoRangeSearch {
00062
00063
00064 FORBID_ACCIDENTAL_COPIES(OrthoRangeSearch);
00065
00066 public:
00067
00069
00072 OrthoRangeSearch() {
00073 tree_buffer_ = NULL;
00074 old_from_new_buffer_ = NULL;
00075 new_from_old_buffer_ = NULL;
00076 root_ = NULL;
00077 }
00078
00081 ~OrthoRangeSearch() {
00082 if(tree_buffer_ != NULL) {
00083 mem::Free(tree_buffer_);
00084 mem::Free(old_from_new_buffer_);
00085 mem::Free(new_from_old_buffer_);
00086 }
00087 else {
00088 delete root_;
00089 }
00090 }
00091
00093
00100 void Compute(GenMatrix<T> &set_of_low_coord_limits,
00101 GenMatrix<T> &set_of_high_coord_limits,
00102 GenMatrix<bool> *candidate_points) {
00103
00104
00105
00106 candidate_points->Init(data_.n_cols(), set_of_low_coord_limits.n_cols());
00107 for(index_t j = 0; j < set_of_low_coord_limits.n_cols(); j++) {
00108 for(index_t i = 0; i < data_.n_cols(); i++) {
00109 (*candidate_points).set(i, j, false);
00110 }
00111 }
00112
00113 fx_timer_start(NULL, "tree_range_search");
00114
00115
00116 ArrayList<index_t> old_from_new_windows;
00117 ArrayList<index_t> new_from_old_windows;
00118
00119 Tree *tree_of_windows =
00120 proximity::MakeGenKdTree<T, Tree, proximity::GenKdTreeMedianSplitter>
00121 (set_of_low_coord_limits, set_of_high_coord_limits, 2,
00122 &old_from_new_windows, &new_from_old_windows);
00123
00124 ortho_range_search(tree_of_windows, set_of_low_coord_limits,
00125 set_of_high_coord_limits, old_from_new_windows,
00126 new_from_old_windows,
00127 root_, 0, data_.n_rows() - 1, *candidate_points);
00128
00129 fx_timer_stop(NULL, "tree_range_search");
00130
00131
00132 delete tree_of_windows;
00133
00134
00135 GenMatrix<T> tmp_matrix;
00136 tmp_matrix.Init(set_of_low_coord_limits.n_rows(),
00137 set_of_low_coord_limits.n_cols());
00138 for(index_t i = 0; i < tmp_matrix.n_cols(); i++) {
00139 GenVector<T> dest;
00140 GenVector<T> src;
00141 tmp_matrix.MakeColumnVector(old_from_new_windows[i], &dest);
00142 set_of_low_coord_limits.MakeColumnVector(i, &src);
00143 dest.CopyValues(src);
00144 }
00145 set_of_low_coord_limits.CopyValues(tmp_matrix);
00146
00147 for(index_t i = 0; i < tmp_matrix.n_cols(); i++) {
00148 GenVector<T> dest;
00149 GenVector<T> src;
00150 tmp_matrix.MakeColumnVector(old_from_new_windows[i], &dest);
00151 set_of_high_coord_limits.MakeColumnVector(i, &src);
00152 dest.CopyValues(src);
00153 }
00154 set_of_high_coord_limits.CopyValues(tmp_matrix);
00155 }
00156
00162 void SaveTree(const char *save_tree_file_name) {
00163
00164 printf("Serializing the tree data structure...\n");
00165
00166 FILE *output = fopen(save_tree_file_name, "w+");
00167
00168
00169
00170 int tree_size = ot::FrozenSize(*root_);
00171 printf("Tree occupies %d bytes...\n", tree_size);
00172
00173 fwrite((const void *) &tree_size, sizeof(int), 1, output);
00174 char *tmp_root = (char *) mem::AllocBytes<Tree>(tree_size);
00175 ot::Freeze(tmp_root, *root_);
00176 fwrite((const void *) tmp_root, tree_size, 1, output);
00177 mem::Free(tmp_root);
00178
00179
00180
00181 int old_from_new_size = ot::FrozenSize(old_from_new_);
00182 int new_from_old_size = ot::FrozenSize(new_from_old_);
00183 char *tmp_array =
00184 (char *) mem::AllocBytes<ArrayList<index_t> >(old_from_new_size);
00185
00186 fwrite((const void *) &old_from_new_size, sizeof(int), 1, output);
00187 ot::Freeze(tmp_array, old_from_new_);
00188 fwrite((const void *) tmp_array, old_from_new_size, 1, output);
00189
00190 fwrite((const void*) &new_from_old_size, sizeof(int), 1, output);
00191 ot::Freeze(tmp_array, new_from_old_);
00192 fwrite((const void *) tmp_array, new_from_old_size, 1, output);
00193
00194 mem::Free(tmp_array);
00195
00196 printf("Tree is serialized...\n");
00197 }
00198
00209 void Init(GenMatrix<T> &dataset, bool make_copy,
00210 const char *load_tree_file_name) {
00211
00212 int leaflen = fx_param_int(NULL, "leaflen", 20);
00213
00214
00215 if(make_copy) {
00216 data_.StaticCopy(dataset);
00217 }
00218 else {
00219 data_.StaticOwn(&dataset);
00220 }
00221
00222 fx_timer_start(NULL, "tree_d");
00223
00224
00225 if(load_tree_file_name != NULL) {
00226 LoadTree(load_tree_file_name);
00227 }
00228
00229
00230 else {
00231 root_ = proximity::MakeGenKdTree
00232 <T, Tree, proximity::GenKdTreeMedianSplitter>(data_, leaflen,
00233 &old_from_new_,
00234 &new_from_old_);
00235 }
00236 fx_timer_stop(NULL, "tree_d");
00237 }
00238
00239 private:
00240
00242 typedef GeneralBinarySpaceTree<GenHrectBound<T, 2>, GenMatrix<T> > Tree;
00243
00245 enum PruneStatus {SUBSUME, INCONCLUSIVE, EXCLUDE};
00246
00248
00250 GenMatrix<T> data_;
00251
00253 ArrayList<index_t> *old_from_new_buffer_;
00254
00256 ArrayList<index_t> *new_from_old_buffer_;
00257
00259 Tree *tree_buffer_;
00260
00261 ArrayList<index_t> old_from_new_;
00262
00263 ArrayList<index_t> new_from_old_;
00264
00266 Tree *root_;
00267
00269
00275 void LoadTree(const char *load_tree_file_name) {
00276
00277
00278 FILE *input = fopen(load_tree_file_name, "r");
00279
00280
00281 int tree_size, old_from_new_size, new_from_old_size;
00282 fread((void *) &tree_size, sizeof(int), 1, input);
00283
00284 printf("Tree file: %s occupies %d bytes...\n", load_tree_file_name,
00285 tree_size);
00286 tree_buffer_ = mem::AllocBytes<Tree>(tree_size);
00287 fread((void *) tree_buffer_, 1, tree_size, input);
00288 root_ = ot::SemiThaw<Tree>((char *) tree_buffer_);
00289
00290
00291 fread((void *) &old_from_new_size, sizeof(int), 1, input);
00292 old_from_new_buffer_ =
00293 mem::AllocBytes<ArrayList<index_t> >(old_from_new_size);
00294 fread((void *) old_from_new_buffer_, old_from_new_size, 1, input);
00295 old_from_new_.InitCopy(*(ot::SemiThaw<ArrayList<index_t> >
00296 ((char *) old_from_new_buffer_)));
00297
00298
00299 fread((void *) &new_from_old_size, sizeof(int), 1, input);
00300 new_from_old_buffer_ =
00301 mem::AllocBytes<ArrayList<index_t> >(new_from_old_size);
00302 fread((void *) new_from_old_buffer_, new_from_old_size, 1, input);
00303 new_from_old_.InitCopy(*(ot::SemiThaw<ArrayList<index_t> >
00304 ((char *) new_from_old_buffer_)));
00305
00306 printf("Tree has been loaded...\n");
00307
00308
00309 GenMatrix<T> tmp_data;
00310 tmp_data.Init(data_.n_rows(), data_.n_cols());
00311
00312 for(index_t i = 0; i < data_.n_cols(); i++) {
00313 GenVector<T> source, dest;
00314 data_.MakeColumnVector(i, &source);
00315 tmp_data.MakeColumnVector(new_from_old_[i], &dest);
00316 dest.CopyValues(source);
00317 }
00318 data_.CopyValues(tmp_data);
00319 }
00320
00336 void ortho_slow_range_search(Tree *search_window_node,
00337 GenMatrix<T> &low_coord_limits,
00338 GenMatrix<T> &high_coord_limits,
00339 const ArrayList<index_t> &old_from_new_windows,
00340 const ArrayList<index_t> &new_from_old_windows,
00341 Tree *reference_node,
00342 index_t start_dim, index_t end_dim,
00343 GenMatrix<bool> &candidate_points) {
00344 PruneStatus prune_flag;
00345
00346
00347 for(index_t window = search_window_node->begin();
00348 window < search_window_node->end(); window++) {
00349
00350
00351 for(index_t row = reference_node->begin(); row < reference_node->end();
00352 row++) {
00353 prune_flag = SUBSUME;
00354
00355
00356 for(index_t d = start_dim; d <= end_dim; d++) {
00357
00358
00359
00360
00361
00362
00363 if(data_.get(d, row) > high_coord_limits.get(d, window) ||
00364 data_.get(d, row) < low_coord_limits.get(d, window)) {
00365 prune_flag = EXCLUDE;
00366 break;
00367 }
00368 }
00369
00370
00371 candidate_points.set(old_from_new_[row], old_from_new_windows[window],
00372 (prune_flag == SUBSUME));
00373
00374 }
00375 }
00376 }
00377
00394 void ortho_range_search(Tree *search_window_node,
00395 GenMatrix<T> &low_coord_limits,
00396 GenMatrix<T> &high_coord_limits,
00397 const ArrayList<index_t> &old_from_new_windows,
00398 const ArrayList<index_t> &new_from_old_windows,
00399 Tree *reference_node, index_t start_dim,
00400 index_t end_dim, GenMatrix<bool> &candidate_points) {
00401
00402 PruneStatus prune_flag = SUBSUME;
00403
00404
00405
00406
00407 for(index_t d = start_dim; d <= end_dim; d++) {
00408
00409 const GenRange<T> &reference_node_dir_range =
00410 reference_node->bound().get(d);
00411 const GenRange<T> &search_window_node_dir_range =
00412 search_window_node->bound().get(d);
00413
00414
00415
00416
00417
00418
00419
00420 if(reference_node_dir_range.lo > search_window_node_dir_range.hi ||
00421 reference_node_dir_range.hi < search_window_node_dir_range.lo) {
00422 return;
00423 }
00424
00425 else if(search_window_node_dir_range.lo <= reference_node_dir_range.lo &&
00426 reference_node_dir_range.hi <= search_window_node_dir_range.hi) {
00427 }
00428
00429 else {
00430 if(search_window_node->count() == 1) {
00431 start_dim = d;
00432 }
00433 prune_flag = INCONCLUSIVE;
00434 break;
00435 }
00436 }
00437
00438
00439
00440
00441 if(search_window_node->count() == 1 && prune_flag == SUBSUME) {
00442 for(index_t j = search_window_node->begin();
00443 j < search_window_node->end(); j++) {
00444 for(index_t i = reference_node->begin();
00445 i < reference_node->end(); i++) {
00446 candidate_points.set(old_from_new_[i], old_from_new_windows[j],
00447 true);
00448 }
00449 }
00450 return;
00451 }
00452 else {
00453 if(search_window_node->is_leaf()) {
00454
00455
00456
00457 if(reference_node->is_leaf()) {
00458 ortho_slow_range_search(search_window_node, low_coord_limits,
00459 high_coord_limits, old_from_new_windows,
00460 new_from_old_windows, reference_node,
00461 start_dim, end_dim, candidate_points);
00462 }
00463
00464 else {
00465 ortho_range_search(search_window_node, low_coord_limits,
00466 high_coord_limits, old_from_new_windows,
00467 new_from_old_windows, reference_node->left(),
00468 start_dim, end_dim, candidate_points);
00469 ortho_range_search(search_window_node, low_coord_limits,
00470 high_coord_limits, old_from_new_windows,
00471 new_from_old_windows, reference_node->right(),
00472 start_dim, end_dim, candidate_points);
00473 }
00474 }
00475 else {
00476
00477
00478 if(reference_node->is_leaf()) {
00479 ortho_range_search(search_window_node->left(), low_coord_limits,
00480 high_coord_limits, old_from_new_windows,
00481 new_from_old_windows, reference_node,
00482 start_dim, end_dim, candidate_points);
00483 ortho_range_search(search_window_node->right(), low_coord_limits,
00484 high_coord_limits, old_from_new_windows,
00485 new_from_old_windows, reference_node,
00486 start_dim, end_dim, candidate_points);
00487 }
00488
00489 else {
00490 ortho_range_search(search_window_node->left(), low_coord_limits,
00491 high_coord_limits, old_from_new_windows,
00492 new_from_old_windows, reference_node->left(),
00493 start_dim, end_dim, candidate_points);
00494 ortho_range_search(search_window_node->left(), low_coord_limits,
00495 high_coord_limits, old_from_new_windows,
00496 new_from_old_windows, reference_node->right(),
00497 start_dim, end_dim, candidate_points);
00498 ortho_range_search(search_window_node->right(), low_coord_limits,
00499 high_coord_limits, old_from_new_windows,
00500 new_from_old_windows, reference_node->left(),
00501 start_dim, end_dim, candidate_points);
00502 ortho_range_search(search_window_node->right(), low_coord_limits,
00503 high_coord_limits, old_from_new_windows,
00504 new_from_old_windows, reference_node->right(),
00505 start_dim, end_dim, candidate_points);
00506 }
00507 }
00508 }
00509 }
00510 };
00511
00512 #endif