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 // STATIC FUNCTIONS DECLARATION.
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 ) // Monoprocessing.
00108       tree->root = root = tdbuild(0,n-1);
00109    else // Multiprocessing.
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 // END OF FILE.
Generated on Tue Nov 16 18:24:44 2010 by  doxygen 1.6.3