This source file includes following definitions.
- kPartitioning
- memory_allocation
- initialization
- algo
- nextGain
- balancing
- destruction
- kpartition_greedy2
- allocate_vertex2
- eval_cost2
- build_p_vector
   1 #include <stdlib.h>
   2 #include <stdio.h>
   3 #include "k-partitioning.h"
   4 #include "tm_mt.h"
   5 #include "tm_verbose.h"
   6 
   7 void memory_allocation(PriorityQueue ** Q, PriorityQueue ** Qinst, double *** D, int n, int k);
   8 void initialization(int * const part, double ** const matrice, PriorityQueue * const Qpart, PriorityQueue * const Q, PriorityQueue * const Qinst, double ** const D, int n, int k, int * const deficit, int * const surplus);
   9 void algo(int * const part, double ** const matrice, PriorityQueue * const Qpart, PriorityQueue * const Q, PriorityQueue * const Qinst, double ** const D, int n,  int * const deficit, int * const surplus);
  10 double nextGain(PriorityQueue * const Qpart, PriorityQueue * const Q, int * const deficit, int * const surplus);
  11 void balancing(int n, int deficit, int surplus, double ** const D, int * const part);
  12 void destruction(PriorityQueue * Qpart, PriorityQueue * Q, PriorityQueue * Qinst, double ** D, int n, int k);
  13 
  14 void allocate_vertex2(int u, int *res, double **comm, int n, int *size, int max_size);
  15 double eval_cost2(int *,int,double **);
  16 int  *kpartition_greedy2(int k, double **comm, int n, int nb_try_max, int *constraints, int nb_constraints);
  17 int*  build_p_vector(double **comm, int n, int k, int greedy_trials, int * constraints, int nb_constraints);
  18 
  19 int* kPartitioning(double ** comm, int n, int k, int * constraints, int nb_constraints, int greedy_trials)
  20 {
  21   
  22 
  23   PriorityQueue Qpart, *Q = NULL, *Qinst = NULL;
  24   double **D = NULL;
  25   int deficit, surplus, *part = NULL;
  26   int real_n = n-nb_constraints;
  27 
  28   part = build_p_vector(comm, n, k, greedy_trials, constraints, nb_constraints);
  29 
  30   memory_allocation(&Q, &Qinst, &D, real_n, k);
  31 
  32   
  33 
  34   initialization(part, comm, &Qpart, Q, Qinst, D, real_n, k, &deficit, &surplus);
  35 
  36   
  37   while((nextGain(&Qpart, Q, &deficit, &surplus))>0)
  38     {
  39       algo(part, comm, &Qpart, Q, Qinst, D, real_n, &deficit, &surplus);
  40     }
  41 
  42   
  43   balancing(real_n, deficit, surplus, D, part); 
  44 
  45   
  46   destruction(&Qpart, Q, Qinst, D, real_n, k);
  47 
  48   return part;
  49 }
  50 
  51 void memory_allocation(PriorityQueue ** Q, PriorityQueue ** Qinst, double *** D, int n, int k)
  52 {
  53   int i;
  54   *Q = calloc(k, sizeof(PriorityQueue)); 
  55   *Qinst = calloc(n, sizeof(PriorityQueue)); 
  56   *D = malloc(sizeof(double *) * n); 
  57   for(i=0; i < n; ++i)
  58     (*D)[i] = calloc(k, sizeof(double));
  59 }
  60 
  61 void initialization(int * const part, double ** const matrice, PriorityQueue * const Qpart, PriorityQueue * const Q, PriorityQueue * const Qinst, double ** const D, int n, int k, int * const deficit, int * const surplus)
  62 {
  63   int i,j;
  64 
  65   
  66   
  67   PQ_init(Qpart, k);
  68 
  69   
  70   
  71   for(i=0; i<k; ++i)
  72     PQ_init(&Q[i], n);
  73 
  74   
  75   for(i=0; i<n; ++i)
  76     PQ_init(&Qinst[i], k);
  77 
  78   
  79   for(i=0; i < n; ++i) 
  80     {
  81       for(j=0; j < n; ++j) 
  82         {
  83           D[i][part[j]] += matrice[i][j];
  84         }
  85     }
  86 
  87   
  88   
  89   for(i=0; i < n; ++i) 
  90     for(j=0; j < k; ++j) 
  91       PQ_insert(&Qinst[i], j, D[i][j]); 
  92 
  93   
  94   for(i=0; i<n; ++i) 
  95     PQ_insert(&Q[part[i]], i, PQ_findMaxKey(&Qinst[i])-D[i][part[i]]); 
  96 
  97   
  98   for(i=0; i < k; ++i) 
  99     PQ_insert(Qpart, i, PQ_findMaxKey(&Q[i])); 
 100 
 101 
 102   
 103   *surplus = *deficit = 0;
 104 }
 105 
 106 void algo(int * const part, double ** const matrice, PriorityQueue * const Qpart, PriorityQueue * const Q, PriorityQueue * const Qinst, double ** const D, int n, int * const deficit, int * const surplus)
 107 {
 108   int p,u,v,j;
 109   double d;
 110   if(*deficit == *surplus) 
 111     {
 112       p = PQ_deleteMax(Qpart); 
 113       u = PQ_deleteMax(&Q[p]); 
 114       *deficit = part[u]; 
 115     }
 116   else 
 117     {
 118       u = PQ_deleteMax(&Q[*surplus]); 
 119       PQ_delete(Qpart, part[u]); 
 120     }
 121   d = PQ_findMaxKey(&Q[part[u]]); 
 122   PQ_insert(Qpart, part[u], d); 
 123   j = PQ_deleteMax(&Qinst[u]); 
 124   if ( j < 0){
 125     if(tm_get_verbose_level() >= CRITICAL)
 126       fprintf(stderr,"Error Max element in priority queue negative!\n");
 127     exit(-1);
 128   }
 129   *surplus = j; 
 130 
 131   for(v=0; v < n; ++v) 
 132     {
 133       j = part[u]; 
 134       D[v][j]= D[v][j] - matrice[u][v]; 
 135       PQ_adjustKey(&Qinst[v], j, D[v][j]); 
 136       j = *surplus; 
 137       D[v][j] = D[v][j] + matrice[u][v]; 
 138       PQ_adjustKey(&Qinst[v], j, D[v][j]);
 139       d = PQ_findMaxKey(&Qinst[v]) - D[v][part[v]]; 
 140       PQ_adjustKey(&Q[part[v]], v, d); 
 141       d = PQ_findMaxKey(&Q[part[v]]); 
 142       PQ_adjustKey(Qpart, part[v], d); 
 143     }
 144   part[u] = *surplus; 
 145 
 146   d = PQ_findMaxKey(&Qinst[u]) - D[u][part[u]]; 
 147   if(!PQ_isEmpty(&Qinst[u])) 
 148     PQ_insert(&Q[part[u]], u, d); 
 149   PQ_adjustKey(Qpart, part[u], d); 
 150 }
 151 
 152 double nextGain(PriorityQueue * const Qpart, PriorityQueue * const Q, int * const deficit, int * const surplus)
 153 {
 154   double res;
 155   if(*deficit == *surplus) 
 156     res = PQ_findMaxKey(Qpart); 
 157   else 
 158     res = PQ_findMaxKey(&Q[*surplus]); 
 159   return res;
 160 }
 161 
 162 void balancing(int n, int deficit, int surplus, double ** const D, int * const part)
 163 {
 164   if(surplus != deficit) 
 165     {
 166       int i;
 167       PriorityQueue moves; 
 168       PQ_init(&moves, n);
 169       for(i=0; i<n; ++i) 
 170         {
 171           if(part[i] == surplus) 
 172             PQ_insert(&moves, i, D[i][deficit]-D[i][surplus]); 
 173         }
 174       part[PQ_deleteMax(&moves)] = deficit; 
 175       PQ_exit(&moves);
 176     }
 177 }
 178 
 179 void destruction(PriorityQueue * Qpart, PriorityQueue * Q, PriorityQueue * Qinst, double ** D, int n, int k)
 180 {
 181   int i;
 182   PQ_exit(Qpart);
 183   for(i=0; i<k; ++i)
 184     PQ_exit(&Q[i]);
 185   free(Q);
 186   for(i=0; i<n; ++i)
 187     {
 188       PQ_exit(&Qinst[i]);
 189     }
 190   free(Qinst);
 191 
 192   for(i=0; i<n; ++i)
 193     free(D[i]);
 194   free(D);
 195 }
 196 
 197 
 198 int  *kpartition_greedy2(int k, double **comm, int n, int nb_try_max, int *constraints, int nb_constraints)
 199 {
 200   int *res = NULL, *best_res=NULL, *size = NULL;
 201   int i,j,nb_trials;
 202   int max_size;
 203   double cost, best_cost = -1;
 204 
 205   for( nb_trials = 0 ; nb_trials < nb_try_max ; nb_trials++ ){
 206     res = (int *)malloc(sizeof(int)*n);
 207     for ( i = 0 ; i < n ; ++i )
 208       res[i] = -1;
 209 
 210     size = (int *)calloc(k,sizeof(int));
 211     max_size = n/k;
 212 
 213     
 214     if (nb_constraints){ 
 215       int nb_real_nodes = n-nb_constraints; 
 216       for(i=0; i<nb_constraints; ++i) 
 217         {
 218           int i_part = constraints[i]/max_size; 
 219           res[nb_real_nodes+i] = i_part; 
 220           size[i_part]++; 
 221         }
 222     }
 223 
 224     
 225     for ( i = 0 ; i < k ; ++i ){
 226       
 227       if(size[i] >= max_size)
 228         continue;
 229       
 230       do{
 231         
 232         j =  genrand_int32() % n;
 233       } while ( res[j] != -1 );
 234       
 235       res[j] = i;
 236       
 237       size[i]++;
 238     }
 239 
 240     
 241     for( i = 0 ;  i < n ; ++i )
 242       if( res[i] == -1)
 243         allocate_vertex2(i, res, comm, n-nb_constraints, size, max_size);
 244 
 245     cost = eval_cost2(res,n-nb_constraints,comm);
 246     
 247 
 248     if((cost<best_cost) || (best_cost == -1)){
 249       best_cost=cost;
 250       free(best_res);
 251       best_res=res;
 252     }else
 253       free(res);
 254 
 255     free(size);
 256   }
 257 
 258   
 259 
 260 
 261   return best_res;
 262 }
 263 
 264 void allocate_vertex2(int u, int *res, double **comm, int n, int *size, int max_size)
 265 {
 266   int i,best_part = -1;
 267   double cost, best_cost = -1;
 268 
 269   
 270 
 271   for( i = 0 ; i < n ; ++i){
 272     if (( res[i] != -1 ) && ( size[res[i]] < max_size )){
 273       cost = comm[u][i];
 274       if (( cost > best_cost)){
 275         best_cost = cost;
 276         best_part = res[i];
 277       }
 278     }
 279   }
 280 
 281   
 282   
 283 
 284   res[u] = best_part;
 285   size[best_part]++;
 286 }
 287 
 288 double eval_cost2(int *partition, int n, double **comm)
 289 {
 290   double cost = 0;
 291   int i,j;
 292 
 293   for( i = 0 ; i < n ; ++i )
 294     for( j = i+1 ; j < n ; ++j )
 295       if(partition[i] != partition[j])
 296         cost += comm[i][j];
 297 
 298   return cost;
 299 }
 300 
 301 int* build_p_vector(double **comm, int n, int k, int greedy_trials, int * constraints, int nb_constraints)
 302 {
 303   int * part = NULL;
 304   if(greedy_trials>0) 
 305     {
 306       part = kpartition_greedy2(k, comm, n, greedy_trials, constraints, nb_constraints);
 307     }
 308   else
 309     {
 310       int * size = calloc(k, sizeof(int));
 311       int i,j;
 312       int nodes_per_part = n/k;
 313       int nb_real_nodes = n-nb_constraints;
 314       part = malloc(sizeof(int) * n);
 315       for(i=0; i<nb_constraints; i++) 
 316         {
 317           int i_part = constraints[i]/nodes_per_part; 
 318           part[nb_real_nodes+i] = i_part;
 319           size[i_part]++;
 320         }
 321       j=0;
 322       
 323       for(i=0; i<nb_real_nodes; i++) 
 324         {
 325           if(size[j] < nodes_per_part) 
 326             {
 327               size[j]++;
 328               part[i] = j; 
 329             }
 330           else 
 331             {
 332               i--;
 333             }
 334           j = (j+1)%k; 
 335         }
 336       free(size);
 337     }
 338   return part;
 339 }