tdkdtree.c
Go to the documentation of this file.00001
00017 #include "tdkdtree.h"
00018 #include "queue.h"
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021
00022
00023 static void globaltreebuild();
00024 static infokdnode* infokdnodebuild();
00025 static kdtree* localtreebuild();
00026 static kdnode* tdbuild();
00027 static kdnode* tdfindcutvalues();
00028 static int arrange();
00029 static void rnn();
00030 static double distsqrd2();
00031 static void destroytdkdtreenode();
00036 static double** y = NULL;
00037
00041 static int n = 0;
00042
00046 static int k = 0;
00047
00051 static int* perm = NULL;
00052
00056 static kdnode* root = NULL;
00057
00062 static int cutoff = 15;
00063
00070 static int bigbucket = 0;
00071
00088 kdtree* newtdkdtree
00089 (
00090 double** param_y ,
00091 int param_n ,
00092 int param_k ,
00093 int p ,
00094 int q
00095 )
00096 {
00097 kdtree* tree = NULL ;
00098 int i = 0 ;
00099
00100 tree = (kdtree*)malloc(sizeof(kdtree));
00101 tree->y = y = param_y;
00102 tree->n = n = param_n;
00103 tree->k = k = param_k;
00104 perm = (int*)malloc(sizeof(int)*n);
00105 for( i = 0 ; i < n ; i++ ) perm[i] = i;
00106 tree->perm = perm;
00107 if( p == 1 )
00108 tree->root = root = tdbuild(0,n-1);
00109 else
00110 {
00111 globaltreebuild(p);
00112 tree = localtreebuild(tree,p,q);
00113 }
00114
00115 return tree;
00116 }
00117
00128 static void globaltreebuild
00129 (
00130 int p
00131 )
00132 {
00133 qnode* node = NULL ;
00134 qnode* lonode = NULL ;
00135 qnode* hinode = NULL ;
00136 int i = 0 ;
00137
00138 qbuild();
00139 node = (qnode*)malloc(sizeof(qnode));
00140 node->info = infokdnodebuild(0,n-1);
00141 qinsert(node);
00142 for( i = 2 ; i <= p ; i++ )
00143 {
00144 node = qretrieve();
00145 lonode = (qnode*)malloc(sizeof(qnode));
00146 lonode->info = infokdnodebuild(node->info->lopt_l,node->info->hipt_l);
00147 hinode = (qnode*)malloc(sizeof(qnode));
00148 hinode->info = infokdnodebuild(node->info->lopt_h,node->info->hipt_h);
00149 qinsert(lonode);
00150 qinsert(hinode);
00151 qdelete();
00152 }
00153
00154 return;
00155 }
00156
00169 static infokdnode* infokdnodebuild
00170 (
00171 int l ,
00172 int u
00173 )
00174 {
00175 infokdnode* info = NULL ;
00176 kdnode* p = NULL ;
00177 int m = 0 ;
00178
00179 info = (infokdnode*)malloc(sizeof(infokdnode));
00180 p = (kdnode*)malloc(sizeof(kdnode));
00181 p = tdfindcutvalues(l,u,p);
00182 info->cutdim = p->cutdim;
00183 info->cutval = p->cutval;
00184 m = arrange(l,u,info->cutval,info->cutdim);
00185 info->lopt_l = l;
00186 info->hipt_l = m;
00187 info->lopt_h = m+1;
00188 info->hipt_h = u;
00189
00190 return info;
00191 }
00192
00206 static kdtree* localtreebuild
00207 (
00208 kdtree* tree ,
00209 int p ,
00210 int q
00211 )
00212 {
00213 int id = 0 ;
00214 qnode* node = NULL ;
00215 int i = 0 ;
00216 int j = 0 ;
00217 int* newperm = NULL ;
00218
00219 for( id = 0 ; id < p ; id++ )
00220 {
00221 node = qretrieve();
00222 if( id == q )
00223 {
00224 tree->n = n = node->info->hipt_h - node->info->lopt_l + 1;
00225 newperm = (int*)malloc(sizeof(int)*n);
00226 j = 0;
00227 for( i = node->info->lopt_l ; i <= node->info->hipt_h ; i++ )
00228 {
00229 newperm[j] = perm[i];
00230 j++;
00231 }
00232 if( perm ) free(perm);
00233 tree->perm = perm = newperm;
00234 tree->root = root = tdbuild(0,n-1);
00235 break;
00236 }
00237 qdelete();
00238 }
00239 qdestroy();
00240
00241 return tree;
00242 }
00243
00264 static kdnode* tdbuild
00265 (
00266 int l ,
00267 int u
00268 )
00269 {
00270 kdnode* p = NULL ;
00271 int m = 0 ;
00272
00273 p = (kdnode*)malloc(sizeof(kdnode));
00274 if( u - l + 1 <= cutoff )
00275 {
00276 p->bucket = 1;
00277 p->lopt = l;
00278 p->hipt = u;
00279 p->loson = p->hison = NULL;
00280 }
00281 else
00282 {
00283 p->bucket = 0;
00284 p = tdfindcutvalues(l,u,p);
00285 m = arrange(l,u,p->cutval,p->cutdim);
00286 if( bigbucket )
00287 {
00288 p->bucket = 1;
00289 p->lopt = l;
00290 p->hipt = u;
00291 p->loson = p->hison = NULL;
00292
00293 return p;
00294 }
00295 p->loson = tdbuild(l,m);
00296 p->hison = tdbuild(m+1,u);
00297 }
00298
00299 return p;
00300 }
00301
00314 static kdnode* tdfindcutvalues
00315 (
00316 int l ,
00317 int u ,
00318 kdnode* p
00319 )
00320 {
00321 int i = 0 ;
00322 int j = 0 ;
00323 double sum = 0.0 ;
00324 double mean = 0.0 ;
00325 double temp = 0.0 ;
00326 double deviation = 0.0 ;
00327 double maxspread = -HUGE ;
00328
00329 if( u - l + 1 > 1000 )
00330 u = l + 1000 - 1;
00331 for( i = 0 ; i < k ; i++)
00332 {
00333 sum = 0.0;
00334 for( j = l ; j <= u ; j++)
00335 sum += y[i][perm[j]];
00336 mean = sum / (u - l + 1);
00337 sum = 0.0;
00338 for( j = l ; j <= u ; j++)
00339 {
00340 temp = y[i][perm[j]] - mean;
00341 if( temp < 0.0 )
00342 temp *= -1;
00343 sum += temp;
00344 }
00345 deviation = sum / (u - l + 1);
00346 if(deviation > maxspread )
00347 {
00348 p->cutdim = i;
00349 p->cutval = mean;
00350 maxspread = deviation;
00351 }
00352 }
00353
00354 return p;
00355 }
00356
00374 static int arrange
00375 (
00376 int l ,
00377 int u ,
00378 double cutval ,
00379 int cutdim
00380 )
00381 {
00382 int n = 0 ;
00383 int n_l = 0 ;
00384 int n_r = 0 ;
00385 int i = 0 ;
00386 double value = 0.0 ;
00387 int m = 0 ;
00388
00389 n = u - l + 1;
00390 do
00391 {
00392 i = perm[l + n_l];
00393 value = y[cutdim][i];
00394 if (value <= cutval )
00395 n_l++;
00396 else
00397 {
00398 perm[l + n_l] = perm[u - n_r];
00399 perm[u - n_r] = i;
00400 n_r++;
00401 }
00402 }while( n_l + n_r != n );
00403 m = l + n_l - 1;
00404 bigbucket = 0;
00405 if( n > cutoff && ( n_l == 0 || n_r == 0 ) )
00406 bigbucket = 1;
00407
00408 return m;
00409 }
00410
00415 static int nntarget = 0;
00420 static int nnfound = 0;
00425 static double nndist2 = 0.0;
00426
00441 int tdnn
00442 (
00443 int j ,
00444 double* param_nndist2
00445 )
00446 {
00447 nntarget = j;
00448 nndist2 = HUGE;
00449 rnn(root);
00450 *param_nndist2 = nndist2;
00451
00452 return nnfound;
00453 }
00454
00472 static void rnn
00473 (
00474 kdnode* p
00475 )
00476 {
00477 int i = 0 ;
00478 double thisdist = 0.0 ;
00479 double diff = 0.0 ;
00480
00481 if( p->bucket )
00482 {
00483 for( i = p->lopt ; i <= p->hipt ; i++ )
00484 {
00485 if( perm[i] != nntarget )
00486 {
00487 thisdist = distsqrd2(perm[i],nntarget);
00488 if( thisdist < nndist2 )
00489 {
00490 nndist2 = thisdist;
00491 nnfound = perm[i];
00492 }
00493 }
00494 }
00495 }
00496 else
00497 {
00498 diff = y[p->cutdim][nntarget] - p->cutval;
00499 if( diff < 0.0 )
00500 {
00501 rnn(p->loson);
00502 if( nndist2 > diff * diff )
00503 rnn(p->hison);
00504 }
00505 else
00506 {
00507 rnn(p->hison);
00508 if( nndist2 > diff * diff )
00509 rnn(p->loson);
00510 }
00511 }
00512 }
00513
00523 static double distsqrd2
00524 (
00525 int i ,
00526 int j
00527 )
00528 {
00529 int d = 0 ;
00530 double diff = 0.0 ;
00531 double dist2 = 0.0 ;
00532
00533 for( d = 0 ; d < k ; d++ )
00534 {
00535 diff = y[d][i] - y[d][j];
00536 dist2 += diff * diff;
00537 }
00538
00539 return dist2;
00540 }
00541
00553 void destroytdkdtree
00554 (
00555 kdtree* tree
00556 )
00557 {
00558 if( tree )
00559 {
00560 if( tree->root )
00561 destroytdkdtreenode(tree->root);
00562 free(tree);
00563 }
00564 if( perm ) free(perm);
00565 y = NULL;
00566 n = 0;
00567 k = 0;
00568 perm = NULL;
00569 root = NULL;
00570 }
00571
00582 static void destroytdkdtreenode
00583 (
00584 kdnode* node
00585 )
00586 {
00587 if( node )
00588 {
00589 if( node->loson ) destroytdkdtreenode(node->loson);
00590 if( node->hison ) destroytdkdtreenode(node->hison);
00591 free(node);
00592 }
00593 }
00594
00595