00001 #include "cuik-kdtree.h"
00002 #include "random.h"
00003 #include "definitions.h"
00004 #include "vector.h"
00005
00006 #include <stdio.h>
00007 #include <time.h>
00008 #include <stdlib.h>
00009 #include <string.h>
00010 #include <math.h>
00011 #include <sys/resource.h>
00012 #include <DNN/ANN_C.h>
00013
00033 #define POINTS_ON_SPHERE 0
00034
00040 #define N_POINTS 50000
00041
00047 #define DIM 8
00048
00054 #define TOPOLOGY TOPOLOGY_S
00055
00061 #define POINTS_IN_LEAF 25
00062
00070 #define SAMPLING_EXPANSION 1.0
00071
00077 #define R 2.0
00078
00085 #define REP 1000
00086
00087
00093 #define N_OPTIONS 9
00094
00107 int CmpUInt(const void *a,const void *b);
00108
00116 double getTime();
00117
00118
00119
00120
00121 int CmpUInt(const void *a,const void *b)
00122 {
00123 return(*((unsigned int*)a)-*((unsigned int*)b));
00124 }
00125
00126 double getTime()
00127 {
00128 struct rusage usage;
00129
00130 getrusage(RUSAGE_SELF,&usage);
00131
00132
00133 return((double)(usage.ru_utime.tv_sec +usage.ru_stime.tv_sec )*1000.0+
00134 (double)(usage.ru_utime.tv_usec+usage.ru_stime.tv_usec)/1000.0);
00135 }
00136
00137
00138
00139
00159 int main(int argc, char **arg)
00160 {
00161 char *option[N_OPTIONS]={"-h","-n","-d","-t","-l","-r","-m","-s","-e"};
00162
00163 unsigned int nPoints,dim,tpg,pLeaf,rep;
00164 double searchR,expansion;
00165
00166
00167 TKDtree *Mkdt;
00168 #ifdef _MPNN
00169 TKDTree *Ykdt;
00170 #endif
00171
00172
00173 boolean found;
00174 unsigned int i,j;
00175 double **point,*q;
00176 Trectangle ambient;
00177 unsigned int *topology;
00178 unsigned int id;
00179 double l,u,d,r2;
00180 unsigned int *nn,n,m;
00181 double *dst,dMin;
00182 unsigned int idMin;
00183
00184
00185 unsigned int ri;
00186
00187
00188 time_t t;
00189 double tStart,tEnd;
00190
00191
00192 nPoints=N_POINTS;
00193 dim=DIM;
00194 tpg=TOPOLOGY;
00195 pLeaf=POINTS_IN_LEAF;
00196 expansion=SAMPLING_EXPANSION;
00197 searchR=R;
00198 rep=REP;
00199
00200
00201 i=1;
00202 while (i<argc)
00203 {
00204 found=FALSE;
00205 j=0;
00206 while((!found)&&(j<N_OPTIONS))
00207 {
00208 if (strcmp(arg[i],option[j])==0)
00209 {
00210 switch(j)
00211 {
00212 case 0:
00213 fprintf(stderr,"cuik-kdtree test program\n");
00214 fprintf(stderr,"Usage: \n");
00215 fprintf(stderr," test-cuik-kdtree <option> <ooption> <option> ...\n");
00216 fprintf(stderr,"Options: \n");
00217 fprintf(stderr," -n <value> Number of random points to generate.\n");
00218 fprintf(stderr," Default value: %u\n",N_POINTS);
00219 fprintf(stderr," -d <value> Dimension of the points to generate.\n");
00220 fprintf(stderr," Default value: %u\n",DIM);
00221 fprintf(stderr," -t <R|S> Topology (R or S) of the points to generate.\n");
00222 fprintf(stderr," The same topology is used for all the dimensions.\n");
00223 fprintf(stderr," Default value: %s\n",(TOPOLOGY==TOPOLOGY_R?"R":"S"));
00224 fprintf(stderr," -l <value> Maximum number of points in each leaf.\n");
00225 fprintf(stderr," Default value: %u\n",POINTS_IN_LEAF);
00226 fprintf(stderr," -r <value> Search radius (for the in-ball queries).\n");
00227 fprintf(stderr," Default value: %f\n",R);
00228 fprintf(stderr," -m <value> Number of reptetions to gather execution times.\n");
00229 fprintf(stderr," Default value: %u\n",REP);
00230 fprintf(stderr," -e <value> Sampling expansion (not used so far in the test).\n");
00231 fprintf(stderr," Default value: %f\n",SAMPLING_EXPANSION);
00232 fprintf(stderr," -s <value> Random seed.\n");
00233 fprintf(stderr," Default value: arbitrarily fixed\n");
00234 fprintf(stderr," -h This help.\n");
00235 fprintf(stderr,"Examples: \n");
00236 fprintf(stderr," test-cuik-kdtree\n");
00237 fprintf(stderr," test-cuik-kdtree -t R -r 0.75\n");
00238 fprintf(stderr," test-cuik-kdtree -n 100000\n");
00239 exit(EXIT_SUCCESS);
00240 break;
00241
00242 case 1:
00243 found=TRUE;
00244 i++;
00245 nPoints=(unsigned int)atoi(arg[i]);
00246 if (nPoints<2)
00247 {
00248 fprintf(stderr,"Too smalll number of points (-n).\n");
00249 exit(EXIT_FAILURE);
00250 }
00251 break;
00252
00253 case 2:
00254 found=TRUE;
00255 i++;
00256 dim=(unsigned int)atoi(arg[i]);
00257 if (dim<1)
00258 {
00259 fprintf(stderr,"Too smalll dimension (-d).\n");
00260 exit(EXIT_FAILURE);
00261 }
00262 break;
00263
00264 case 3:
00265 found=TRUE;
00266 i++;
00267
00268 if (arg[i][0]=='R')
00269 tpg=TOPOLOGY_R;
00270 else
00271 {
00272 if (arg[i][0]=='S')
00273 tpg=TOPOLOGY_S;
00274 else
00275 {
00276 fprintf(stderr,"Unknown topology (-t).\n");
00277 exit(EXIT_FAILURE);
00278 }
00279 }
00280 break;
00281
00282 case 4:
00283 found=TRUE;
00284 i++;
00285 pLeaf=(unsigned int)atoi(arg[i]);
00286 if (pLeaf<1)
00287 {
00288 fprintf(stderr,"Too smalll number of points in each leaf (-l).\n");
00289 exit(EXIT_FAILURE);
00290 }
00291 break;
00292
00293 case 5:
00294 found=TRUE;
00295 i++;
00296 searchR=(double)atof(arg[i]);
00297 if (searchR<=0)
00298 {
00299 fprintf(stderr,"The search radius must be positive (-r).\n");
00300 exit(EXIT_FAILURE);
00301 }
00302 break;
00303
00304 case 6:
00305 found=TRUE;
00306 i++;
00307 rep=(unsigned int)atoi(arg[i]);
00308 if (rep<1)
00309 {
00310 fprintf(stderr,"The number of repetitions must be positive (-m).\n");
00311 exit(EXIT_FAILURE);
00312 }
00313 break;
00314
00315 case 7:
00316 found=TRUE;
00317 i++;
00318 ri=(unsigned int)atof(arg[i]);
00319 break;
00320
00321 case 8:
00322 found=TRUE;
00323 i++;
00324 ri=(unsigned int)atof(arg[i]);
00325 break;
00326 }
00327 }
00328 j++;
00329 }
00330
00331 if (!found)
00332 {
00333 fprintf(stderr,"Unknown command line option %s.\nUse -h for help.\n",arg[i]);
00334 exit(EXIT_FAILURE);
00335 }
00336 i++;
00337 }
00338
00339
00340 t=time(NULL);
00341 ri=(unsigned int)t;
00342
00343 randomSet(ri);
00344
00345
00346 printf("\n\n************************************************************\n");
00347 printf("Parameters\n");
00348 printf(" Random seed : %u\n",ri);
00349 printf(" Topology : %s\n",(tpg==TOPOLOGY_R?"R":"S"));
00350 printf(" No. points : %u\n",nPoints);
00351 printf(" Dimension : %u\n",dim);
00352 printf(" Points in leaf: %u\n",pLeaf);
00353 printf(" Search radius : %f\n",searchR);
00354 if (rep>1)
00355 printf(" Repetitions : %u\n",rep);
00356 printf("\n");
00357
00358
00359 InitRectangle(dim,NULL,NULL,&ambient);
00360
00361 if (tpg==TOPOLOGY_R)
00362 {
00363 l=-1;
00364 u=1;
00365 topology=NULL;
00366 }
00367 else
00368 {
00369 l=-M_PI;
00370 u=+M_PI;
00371 NEW(topology,dim,unsigned int);
00372 for(i=0;i<dim;i++)
00373 topology[i]=tpg;
00374 }
00375 for(i=0;i<dim;i++)
00376 {
00377 SetRectangleLowerLimit(i,l,&ambient);
00378 SetRectangleUpperLimit(i,u,&ambient);
00379 }
00380
00381
00382 printf("Generating %u random points\n\n",nPoints);
00383 NEW(point,nPoints,double*);
00384 for(i=0;i<nPoints;i++)
00385 {
00386 NEW(point[i],dim,double);
00387 #if (POINTS_ON_SPHERE)
00388 for(j=0;j<dim;j++)
00389 point[i][j]=randomNormal();
00390 VectorNormalize(dim,point[i]);
00391 #else
00392 RandomPointInRectangle(point[i],&ambient);
00393 #endif
00394 }
00395
00396
00397 printf("Building kd-tree\n");
00398 #ifdef _MPNN
00399 tStart=getTime();
00400 if (topology==NULL)
00401 Ykdt=CreateKDTree(dim);
00402 else
00403 Ykdt=CreateKDTreeT(dim,(int *)topology);
00404 for(i=0;i<nPoints;i++)
00405 AddPoint2KDTree(point[i],Ykdt);
00406 tEnd=getTime();
00407 printf(" MPNN : %7.3f ms\n",tEnd-tStart);
00408 printf(" MPNN x point: %7.3f ms\n",(tEnd-tStart)/(double)nPoints);
00409 #endif
00410
00411 tStart=getTime();
00412 for(i=0;i<nPoints;i++)
00413 {
00414 if (i==0)
00415 Mkdt=InitKDTree(&ambient,pLeaf,expansion,1,&(point[i]),&i);
00416 else
00417 AddPoint2KDtree(topology,point[i],i,&Mkdt);
00418 }
00419 tEnd=getTime();
00420 printf(" Cuik : %7.3f ms\n",tEnd-tStart);
00421 printf(" Cuik x point: %7.3f ms\n\n",(tEnd-tStart)/(double)nPoints);
00422
00423
00424
00425 printf("Defining the query point\n\n");
00426 NEW(q,dim,double);
00427 RandomPointInRectangle(q,&ambient);
00428
00429
00430 #ifdef _MPNN
00431 printf("Searching NN\n");
00432 printf(" MPNN kd-tree : ");
00433 QueryKDTree(q,(int *)&id,&d,Ykdt);
00434 printf("%u\n",id);
00435 #endif
00436
00437 printf(" Cuik kd-tree : ");
00438 NearestNeighbour(topology,q,Mkdt);
00439 printf("%u\n",id);
00440
00441 printf(" Brute-force search: ");
00442 dMin=INF;
00443 for(i=0;i<nPoints;i++)
00444 {
00445 d=VectorSquaredDistanceTopologyMin(dMin,dim,topology,point[i],q);
00446 if (d<dMin)
00447 {
00448 idMin=i;
00449 dMin=d;
00450 }
00451 }
00452 printf("%u\n\n",idMin);
00453
00454 printf("Searching in-ball\n");
00455 #ifdef _MPNN
00456 printf(" MPNN kd-tree : ");
00457 QueryKDTreeR(q,searchR,(int *)(&n),(int **)(&nn),&dst,Ykdt);
00458 if (n>0)
00459 {
00460 qsort(nn,n,sizeof(unsigned int),CmpUInt);
00461 printf("[%u] ",n);
00462 if (n>10)
00463 {
00464 for(i=0;i<5;i++)
00465 printf("%u ",nn[i]);
00466 printf("... ");
00467 for(i=n-5;i<n;i++)
00468 printf("%u ",nn[i]);
00469 }
00470 else
00471 {
00472 for(i=0;i<n;i++)
00473 printf("%u ",nn[i]);
00474 }
00475 if (n>0)
00476 {
00477 free(nn);
00478 free(dst);
00479 }
00480 }
00481 else
00482 printf("no point");
00483 printf("\n");
00484 #endif
00485
00486 printf(" Cuik kd-tree : ");
00487 NeighboursInBall(topology,q,searchR,&n,&nn,Mkdt);
00488 if (n>0)
00489 {
00490 qsort(nn,n,sizeof(unsigned int),CmpUInt);
00491 printf("[%u] ",n);
00492 if (n>10)
00493 {
00494 for(i=0;i<5;i++)
00495 printf("%u ",nn[i]);
00496 printf("... ");
00497 for(i=n-5;i<n;i++)
00498 printf("%u ",nn[i]);
00499 }
00500 else
00501 {
00502 for(i=0;i<n;i++)
00503 printf("%u ",nn[i]);
00504 }
00505 if (n>0)
00506 free(nn);
00507 }
00508 else
00509 printf("no point");
00510 printf("\n");
00511
00512 printf(" Brute-force search: ");
00513 r2=searchR*searchR;
00514 n=0;
00515 m=100;
00516 NEW(nn,m,unsigned int);
00517 for(i=0;i<nPoints;i++)
00518 {
00519 if (VectorSquaredDistanceTopologyMin(r2,dim,topology,point[i],q)<r2)
00520 {
00521 if (n==m)
00522 MEM_DUP(nn,m,unsigned int);
00523 nn[n]=i;
00524 n++;
00525 }
00526 }
00527 if (n>0)
00528 {
00529 printf("[%u] ",n);
00530 if (n>10)
00531 {
00532 for(i=0;i<5;i++)
00533 printf("%u ",nn[i]);
00534 printf("... ");
00535 for(i=n-5;i<n;i++)
00536 printf("%u ",nn[i]);
00537 }
00538 else
00539 {
00540 for(i=0;i<n;i++)
00541 printf("%u ",nn[i]);
00542 }
00543 }
00544 else
00545 printf("no point");
00546 free(nn);
00547 printf("\n\n");
00548
00549
00550 if (rep>1)
00551 {
00552 printf("Average time per NN query\n");
00553
00554 #ifdef _MPNN
00555 tStart=getTime();
00556 for(j=0;j<rep;j++)
00557 {
00558 RandomPointInRectangle(q,&ambient);
00559 QueryKDTree(q,(int *)&id,&d,Ykdt);
00560 }
00561 tEnd=getTime();
00562 printf(" MPNN : %f ms\n",(tEnd-tStart)/(double)rep);
00563 #endif
00564
00565 tStart=getTime();
00566 for(j=0;j<rep;j++)
00567 {
00568 RandomPointInRectangle(q,&ambient);
00569 id=NearestNeighbour(topology,q,Mkdt);
00570 }
00571 tEnd=getTime();
00572 printf(" Cuik : %f ms\n",(tEnd-tStart)/(double)rep);
00573
00574 tStart=getTime();
00575 for(j=0;j<rep;j++)
00576 {
00577 dMin=INF;
00578 for(i=0;i<nPoints;i++)
00579 {
00580 d=VectorSquaredDistanceTopologyMin(dMin,dim,topology,point[i],q);
00581 if (d<dMin)
00582 {
00583 idMin=i;
00584 dMin=d;
00585 }
00586 }
00587 }
00588 tEnd=getTime();
00589 printf(" Brute-force: %f ms\n\n",(tEnd-tStart)/(double)rep);
00590
00591 printf("Average time per in-ball query\n");
00592
00593 #ifdef _MPNN
00594 tStart=getTime();
00595 for(j=0;j<rep;j++)
00596 {
00597 RandomPointInRectangle(q,&ambient);
00598 QueryKDTreeR(q,searchR,(int *)(&n),(int **)(&nn),&dst,Ykdt);
00599 if (n>0)
00600 {
00601 free(nn);
00602 free(dst);
00603 }
00604 }
00605 tEnd=getTime();
00606 printf(" MPNN : %f ms\n",(tEnd-tStart)/(double)rep);
00607 #endif
00608
00609 tStart=getTime();
00610 for(j=0;j<rep;j++)
00611 {
00612 RandomPointInRectangle(q,&ambient);
00613 NeighboursInBall(topology,q,searchR,&n,&nn,Mkdt);
00614 if (n>0)
00615 free(nn);
00616 }
00617 tEnd=getTime();
00618 printf(" Cuik : %f ms\n",(tEnd-tStart)/(double)rep);
00619
00620 tStart=getTime();
00621 for(j=0;j<rep;j++)
00622 {
00623 RandomPointInRectangle(q,&ambient);
00624 n=0;
00625 m=100;
00626 NEW(nn,m,unsigned int);
00627 for(i=0;i<nPoints;i++)
00628 {
00629 if (VectorSquaredDistanceTopologyMin(r2,dim,topology,point[i],q)<r2)
00630 {
00631 if (n==m)
00632 MEM_DUP(nn,m,unsigned int);
00633 nn[n]=i;
00634 n++;
00635 }
00636 }
00637 free(nn);
00638 }
00639 tEnd=getTime();
00640 printf(" Brute force: %f ms\n\n",(tEnd-tStart)/(double)rep);
00641 }
00642
00643
00644 free(q);
00645
00646 for(i=0;i<nPoints;i++)
00647 free(point[i]);
00648 free(point);
00649
00650 if (topology!=NULL)
00651 free(topology);
00652 DeleteRectangle(&ambient);
00653
00654 DeleteKDtree(Mkdt);
00655 #ifdef _MPNN
00656 DeleteKDTree(Ykdt);
00657 #endif
00658
00659 return(EXIT_SUCCESS);
00660 }
Follow us!