00001 #include <stdio.h>
00002 #include <float.h>
00003 #include <math.h>
00004 #include <assert.h>
00005 #include "tm_tree.h"
00006 #include "tm_bucket.h"
00007 #include "tm_timings.h"
00008 #ifdef _WIN32
00009 #include <windows.h>
00010 #include <winbase.h>
00011 #define random() rand()
00012 #define srandom(x) srand(x)
00013 #endif
00014
00015 #if __CHARMC__
00016 #include "converse.h"
00017 #else
00018 #define CmiLog2 log2
00019 #endif
00020
00021 #undef DEBUG
00022 bucket_list_t global_bl;
00023
00024 int tab_cmp(const void* x1,const void* x2){
00025 int *e1,*e2,i1,i2,j1,j2;
00026 double **tab;
00027 bucket_list_t bl;
00028
00029 bl=global_bl;
00030
00031 e1=((int *)x1);
00032 e2=((int *)x2);
00033
00034
00035 tab=bl->tab;
00036
00037 i1=e1[0];
00038 j1=e1[1];
00039 i2=e2[0];
00040 j2=e2[1];
00041
00042 return tab[i1][j1]>tab[i2][j2]?-1:1;
00043 }
00044
00045
00046 int old_bucket_id(int i,int j,bucket_list_t bucket_list){
00047 double *pivot,val;
00048 int n,sup,inf,p;
00049 pivot=bucket_list->pivot;
00050 n=bucket_list->nb_buckets;
00051 val=bucket_list->tab[i][j];
00052
00053 inf=-1;
00054 sup=n;
00055
00056 while(sup-inf>1){
00057 p=(sup+inf)/2;
00058
00059 if(val<pivot[p]){
00060 inf=p;
00061 if(inf==sup)
00062 inf--;
00063 }else{
00064 sup=p;
00065 if(sup==inf)
00066 sup++;
00067 }
00068 }
00069
00070 return sup;
00071 }
00072
00073
00074 int bucket_id(int i,int j,bucket_list_t bucket_list){
00075 double *pivot_tree,val;
00076 int p,k;
00077 pivot_tree=bucket_list->pivot_tree;
00078 val=bucket_list->tab[i][j];
00079
00080
00081
00082 p=1;
00083 for(k=0;k<bucket_list->max_depth;k++){
00084 if(val>pivot_tree[p])
00085 p=p*2;
00086 else
00087 p=p*2+1;
00088 }
00089
00090 return (int)pivot_tree[p];
00091 }
00092
00093
00094
00095 void display_bucket(bucket_t *b){
00096 printf("\tb.bucket=%p\n",(void *)b->bucket);
00097 printf("\tb.bucket_len=%d\n",(int)b->bucket_len);
00098 printf("\tb.nb_elem=%d\n",(int)b->nb_elem);
00099
00100 }
00101
00102 void check_bucket(bucket_t *b,double **tab,double inf, double sup,int N){
00103 int k,i,j;
00104 for(k=0;k<b->nb_elem;k++){
00105 i=b->bucket[k].i;
00106 j=b->bucket[k].j;
00107 if((tab[i][j]<inf)||(tab[i][j]>sup)){
00108 printf("[%d] (%d,%d):%f not in [%f,%f]\n",k,i,j,tab[i][j],inf,sup);
00109 exit(-1);
00110 }
00111 }
00112 }
00113
00114 void display_pivots(bucket_list_t bucket_list){
00115 int i;
00116
00117 for(i=0;i<bucket_list->nb_buckets-1;i++){
00118 printf("pivot[%d]=%f\n",i,bucket_list->pivot[i]);
00119 }
00120 printf("\n");
00121 }
00122
00123 void display_bucket_list(bucket_list_t bucket_list){
00124 int i;
00125 double inf,sup;
00126
00127 display_pivots(bucket_list);
00128
00129 for(i=0;i<bucket_list->nb_buckets;i++){
00130 inf=bucket_list->pivot[i];
00131 sup=bucket_list->pivot[i-1];
00132 if(i==0)
00133 sup=DBL_MAX;
00134 if(i==bucket_list->nb_buckets-1)
00135 inf=0;
00136 printf("Bucket %d:\n",i);
00137 display_bucket(bucket_list->bucket_tab[i]);
00138 printf("\n");
00139 check_bucket(bucket_list->bucket_tab[i],bucket_list->tab,inf,sup,bucket_list->N);
00140 }
00141
00142 }
00143
00144 void add_to_bucket(int id,int i,int j,bucket_list_t bucket_list){
00145 bucket_t *bucket;
00146 int N,n,size;
00147
00148 bucket=bucket_list->bucket_tab[id];
00149
00150
00151 if(bucket->bucket_len==bucket->nb_elem){
00152 N=bucket_list->N;
00153 n=bucket_list->nb_buckets;
00154 size=N*N/n;
00155
00156 bucket->bucket=(coord*)realloc(bucket->bucket,sizeof(coord)*(size+bucket->bucket_len));
00157 bucket->bucket_len+=size;
00158 #ifdef DEBUG
00159 printf("malloc/realloc: %d\n",id);
00160 printf("(%d,%d)\n",i,j);
00161 display_bucket(bucket);
00162 printf("\n");
00163 #endif
00164 }
00165
00166 bucket->bucket[bucket->nb_elem].i=i;
00167 bucket->bucket[bucket->nb_elem].j=j;
00168 bucket->nb_elem++;
00169
00170
00171
00172 }
00173
00174 void dfs(int i,int inf,int sup,double *pivot,double *pivot_tree,int depth,int max_depth){
00175 int p;
00176 if(depth==max_depth)
00177 return;
00178
00179 p=(inf+sup)/2;
00180 pivot_tree[i]=pivot[p-1];
00181
00182 dfs(2*i,inf,p-1,pivot,pivot_tree,depth+1,max_depth);
00183 dfs(2*i+1,p+1,sup,pivot,pivot_tree,depth+1,max_depth);
00184 }
00185
00186 void built_pivot_tree(bucket_list_t bucket_list){
00187 double *pivot_tree,*pivot;
00188 int n,i,k;
00189 pivot=bucket_list->pivot;
00190 n=bucket_list->nb_buckets;
00191 pivot_tree=(double*)malloc(sizeof(double)*2*n);
00192 bucket_list->max_depth=(int)CmiLog2(n);
00193
00194 dfs(1,1,n-1,pivot,pivot_tree,0,bucket_list->max_depth);
00195
00196 k=0;
00197 for(i=n;i<2*n;i++)
00198 pivot_tree[i]=k++;
00199
00200 bucket_list->pivot_tree=pivot_tree;
00201
00202
00203
00204
00205
00206 }
00207
00208 void fill_buckets(bucket_list_t bucket_list){
00209 int N,i,j,id;
00210
00211 N=bucket_list->N;
00212
00213 for(i=0;i<N;i++){
00214 for(j=i+1;j<N;j++){
00215 id=bucket_id(i,j,bucket_list);
00216 add_to_bucket(id,i,j,bucket_list);
00217 }
00218 }
00219
00220
00221 }
00222
00223 int is_power_of_2(int val){
00224 int n=1;
00225 do{
00226 if(n==val)
00227 return 1;
00228 n<<=1;
00229 }while(n>0);
00230 return 0;
00231 }
00232
00233
00234 void partial_sort(bucket_list_t *bl,double **tab,int N,int nb_buckets){
00235 int *sample;
00236 int i,j,k,n;
00237 int id;
00238 double *pivot;
00239 bucket_list_t bucket_list;
00240
00241
00242 if(!is_power_of_2(nb_buckets)){
00243 fprintf(stderr,"Error! Paramater nb_buckets is: %d and should be a power of 2\n",nb_buckets);
00244 exit(-1);
00245 }
00246
00247
00248 bucket_list=(bucket_list_t)malloc(sizeof(_bucket_list_t));
00249
00250 bucket_list->tab=tab;
00251 bucket_list->N=N;
00252
00253
00254 n=pow(nb_buckets,2);
00255
00256 assert(n=N);
00257 printf("N=%d, n=%d\n",N,n);
00258 sample=(int*)malloc(2*sizeof(int)*n);
00259
00260 for(k=0;k<n;k++){
00261 i=random()%(N-2)+1;
00262 if(i==N-2)
00263 j=N-1;
00264 else
00265 j=random()%(N-i-2)+i+1;
00266 assert(i!=j);
00267 assert(i<j);
00268 assert(i<N);
00269 assert(j<N);
00270 sample[2*k]=i;
00271 sample[2*k+1]=j;
00272 }
00273
00274 global_bl=bucket_list;
00275 qsort(sample,n,2*sizeof(int),tab_cmp);
00276
00277
00278
00279
00280
00281
00282
00283 pivot=(double*)malloc(sizeof(double)*nb_buckets-1);
00284 id=1;
00285 for(k=1;k<nb_buckets;k++){
00286 i=sample[2*(id-1)];
00287 j=sample[2*(id-1)+1];
00288 id*=2;
00289
00290
00291
00292
00293 pivot[k-1]=tab[i][j];
00294
00295 }
00296
00297 bucket_list->pivot=pivot;
00298 bucket_list->nb_buckets=nb_buckets;
00299 built_pivot_tree(bucket_list);
00300
00301 bucket_list->bucket_tab=(bucket_t**)malloc(nb_buckets*sizeof(bucket_t*));
00302 for(i=0;i<nb_buckets;i++){
00303 bucket_list->bucket_tab[i]=(bucket_t*)calloc(1,sizeof(bucket_t));
00304 }
00305
00306 fill_buckets(bucket_list);
00307
00308
00309
00310 bucket_list->cur_bucket=0;
00311 bucket_list->bucket_indice=0;
00312
00313 free(sample);
00314
00315 *bl=bucket_list;
00316 }
00317
00318 void next_bucket_elem(bucket_list_t bucket_list,int *i,int *j){
00319 int N;
00320 bucket_t *bucket=bucket_list->bucket_tab[bucket_list->cur_bucket];
00321
00322
00323
00324
00325 while(bucket->nb_elem<=bucket_list->bucket_indice){
00326
00327 bucket_list->bucket_indice=0;
00328 bucket_list->cur_bucket++;
00329 bucket=bucket_list->bucket_tab[bucket_list->cur_bucket];
00330
00331
00332
00333
00334 }
00335
00336 if(!bucket->sorted){
00337 global_bl=bucket_list;
00338 qsort(bucket->bucket,bucket->nb_elem,2*sizeof(int),tab_cmp);
00339 bucket->sorted=1;
00340 }
00341
00342
00343
00344 N=bucket_list->N;
00345
00346 *i=bucket->bucket[bucket_list->bucket_indice].i;
00347 *j=bucket->bucket[bucket_list->bucket_indice].j;
00348 bucket_list->bucket_indice++;
00349 }
00350
00351
00352 int add_edge_3(double **tab,tree_t *tab_node, tree_t *parent,int i,int j,int N,int *nb_groups){
00353
00354
00355 if((!tab_node[i].parent) && (!tab_node[j].parent)){
00356 if(parent){
00357 parent->child[0]=&tab_node[i];
00358 parent->child[1]=&tab_node[j];
00359 tab_node[i].parent=parent;
00360 tab_node[j].parent=parent;
00361 #ifdef DEBUG
00362 printf("%d: %d-%d\n",*nb_groups,parent->child[0]->id,parent->child[1]->id);
00363 #endif
00364 return 1;
00365 }
00366 return 0;
00367 }
00368
00369 if(tab_node[i].parent && (!tab_node[j].parent)){
00370 parent=tab_node[i].parent;
00371 if(!parent->child[2]){
00372 parent->child[2]=&tab_node[j];
00373 tab_node[j].parent=parent;
00374 #ifdef DEBUG
00375 printf("%d: %d-%d-%d\n",*nb_groups,parent->child[0]->id,parent->child[1]->id,parent->child[2]->id);
00376 #endif
00377 (*nb_groups)++;
00378 }
00379 return 0;
00380 }
00381
00382 if(tab_node[j].parent && (!tab_node[i].parent)){
00383 parent=tab_node[j].parent;
00384 if(!parent->child[2]){
00385 parent->child[2]=&tab_node[i];
00386 tab_node[i].parent=parent;
00387 #ifdef DEBUG
00388 printf("%d: %d-%d-%d\n",*nb_groups,parent->child[0]->id,parent->child[1]->id,parent->child[2]->id);
00389 #endif
00390 (*nb_groups)++;
00391 }
00392 return 0;
00393 }
00394
00395 return 0;
00396 }
00397
00398 int try_add_edge(double **tab,tree_t *tab_node, tree_t *parent,int arity,int i,int j,int N,int *nb_groups){
00399
00400 assert(i!=j);
00401
00402
00403 switch(arity){
00404 case 2:
00405 if(tab_node[i].parent)
00406 return 0;
00407 if(tab_node[j].parent)
00408 return 0;
00409
00410 parent->child[0]=&tab_node[i];
00411 parent->child[1]=&tab_node[j];
00412 tab_node[i].parent=parent;
00413 tab_node[j].parent=parent;
00414
00415 (*nb_groups)++;
00416
00417 return 1;
00418 case 3:
00419 return add_edge_3(tab,tab_node,parent,i,j,N,nb_groups);
00420 default:
00421 fprintf(stderr,"Cannot handle arity %d\n",parent->arity);
00422 exit(-1);
00423 }
00424 }
00425
00426
00427 void free_bucket(bucket_t *bucket){
00428 free(bucket->bucket);
00429 free(bucket);
00430
00431 }
00432
00433 void free_tab_bucket(bucket_t **bucket_tab,int N){
00434 int i;
00435 for(i=0;i<N;i++){
00436 free_bucket(bucket_tab[i]);
00437 }
00438 free(bucket_tab);
00439 }
00440
00441
00442 void free_bucket_list(bucket_list_t bucket_list){
00443
00444
00445
00446 free_tab_bucket(bucket_list->bucket_tab,bucket_list->nb_buckets);
00447 free(bucket_list->pivot);
00448 free(bucket_list->pivot_tree);
00449 free(bucket_list);
00450 }
00451
00452 void bucket_grouping(double **tab,tree_t *tab_node, tree_t *new_tab_node, int arity,int N, int M,long int k){
00453 bucket_list_t bucket_list;
00454 double duration;
00455 int l,i,j,nb_groups;
00456 double val=0;
00457
00458 TIC;
00459 partial_sort(&bucket_list,tab,N,8);
00460 duration=TOC;
00461 printf("Partial sorting=%fs\n",duration);
00462
00463 display_pivots(bucket_list);
00464
00465
00466 TIC;
00467 l=0;
00468 i=0;
00469 nb_groups=0;
00470 while(l<M){
00471 next_bucket_elem(bucket_list,&i,&j);
00472 if(try_add_edge(tab,tab_node,&new_tab_node[l],arity,i,j,N,&nb_groups)){
00473 l++;
00474 }
00475 }
00476
00477 #ifdef DEBUG
00478 printf("l=%d,nb_groups=%d\n",l,nb_groups);
00479 #endif
00480
00481 while(nb_groups<M){
00482 next_bucket_elem(bucket_list,&i,&j);
00483 try_add_edge(tab,tab_node,NULL,arity,i,j,N,&nb_groups);
00484 }
00485
00486 #ifdef DEBUG
00487 printf("l=%d,nb_groups=%d\n",l,nb_groups);
00488 #endif
00489
00490 for(l=0;l<M;l++){
00491 update_val(tab,&new_tab_node[l],N);
00492 val+=new_tab_node[l].val;
00493 }
00494
00495
00496
00497
00498
00499 duration=TOC;
00500 printf("Grouping =%fs\n",duration);
00501
00502 printf("Bucket: %d, indice:%d\n",bucket_list->cur_bucket,bucket_list->bucket_indice);
00503
00504 printf("val=%f\n",val);
00505 free_bucket_list(bucket_list);
00506
00507
00508
00509
00510
00511
00512 }
00513