ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
wkkm_experiment.c
Go to the documentation of this file.
1 /*
2  * Copyright 2005, Yuqiang Guan
3  *
4  * wkkm.c
5  *
6  * This file contains weighted kernel k-means and refinement.
7  *
8  * Started 12/04
9  * Yuqiang Guan
10  *
11  *
12  */
13 
14 #include "metis.h"
15 #include <float.h>
16 
18 
19 void Compute_Weights(CtrlType *ctrl, GraphType *graph, idxtype *w)
20  /* compute the weights for WKKM; for the time, only Ncut. w is zero-initialized */
21 {
22  int nvtxs, i, j;
23  idxtype *xadj, *adjwgt;
24 
25  nvtxs = graph->nvtxs;
26  xadj = graph->xadj;
27  adjwgt = graph->adjwgt;
28 
29  if ((cutType == RASSO) || (cutType == RCUT))
30  for (i=0; i<nvtxs; i++)
31  w[i] = 1;
32  else
33  if (adjwgt == NULL)
34  for (i=0; i<nvtxs; i++)
35  for (j=xadj[i]; j<xadj[i+1]; j++)
36  w[i] ++;
37  else
38  for (i=0; i<nvtxs; i++)
39  for (j=xadj[i]; j<xadj[i+1]; j++)
40  w[i] += adjwgt[j];
41 }
42 
43 void transform_matrix(CtrlType *ctrl, GraphType *graph, idxtype *w, float *m_adjwgt)
44  /* normalized the adjacency matrix for Ncut only*/
45 {
46  int nvtxs, i, j;
47  idxtype *xadj, *adjncy, *adjwgt, *where;
48 
49  nvtxs = graph->nvtxs;
50  xadj = graph->xadj;
51  adjncy = graph->adjncy;
52  adjwgt = graph->adjwgt;
53 
54  if (cutType == RASSO){ // ratio asso.
55  if (adjwgt == NULL)
56  for (i=0; i<nvtxs; i++)
57  for (j=xadj[i]; j<xadj[i+1]; j++)
58  m_adjwgt[j] =1;
59  else
60  for (i=0; i<nvtxs; i++)
61  for (j=xadj[i]; j<xadj[i+1]; j++)
62  m_adjwgt[j] = adjwgt[j];
63  }
64  else{ //normalize rows and columns
65  if (adjwgt == NULL){
66  for (i=0; i<nvtxs; i++)
67  for (j=xadj[i]; j<xadj[i+1]; j++)
68  if (w[i]>0)
69  m_adjwgt[j] = 1.0/w[i];
70  for (i=0; i<nvtxs; i++)
71  for (j=xadj[i]; j<xadj[i+1]; j++)
72  if (w[i]>0)
73  m_adjwgt[j] /= w[adjncy[j]];
74  }
75  else{
76  for (i=0; i<nvtxs; i++)
77  for (j=xadj[i]; j<xadj[i+1]; j++)
78  if (w[i]>0)
79  m_adjwgt[j] = adjwgt[j] *1.0/w[i];
80  else
81  m_adjwgt[j] = 0;
82  for (i=0; i<nvtxs; i++)
83  for (j=xadj[i]; j<xadj[i+1]; j++)
84  if (w[i]>0)
85  m_adjwgt[j] /= w[adjncy[j]];
86  }
87  }
88 }
89 
90 void pingpong(CtrlType *ctrl, GraphType *graph, int nparts, int chain_length, float *tpwgts, float ubfactor, int toplevel)
91  // do batch-local search; chain_length is the search length
92 {
93 
94  int nvtxs, nedges, moves, iter;
95  idxtype *w;
96  //float *m_adjwgt;
97 
98  nedges = graph->nedges;
99  nvtxs = graph->nvtxs;
100 
101  w = idxsmalloc(nvtxs, 0, "pingpong: weight");
102  Compute_Weights(ctrl, graph, w);
103  //m_adjwgt = fmalloc(nedges, "pingpong: normalized matrix");
104  //transform_matrix(ctrl, graph, w, m_adjwgt);
105 
106  moves =0;
107  iter =0;
108 
109  //printf("Number of boundary points is %d\n", graph->nbnd);
110  do{
111  //Weighted_kernel_k_means(ctrl, graph, nparts, w, m_adjwgt, tpwgts, ubfactor);
112  Weighted_kernel_k_means(ctrl, graph, nparts, w, tpwgts, ubfactor);
113  if (chain_length>0){
114 
115  //moves = local_search(ctrl, graph, nparts, chain_length, w, m_adjwgt, tpwgts, ubfactor);
116  moves = local_search(ctrl, graph, nparts, chain_length, w, tpwgts, ubfactor);
117  //printf("number of local search moves is %d\n", moves);
118  }
119  iter ++;
120  if (iter > MAXITERATIONS)
121  break;
122  }while(moves >0) ;
123  if(memory_saving ==0){
124  remove_empty_clusters_l1(ctrl, graph, nparts, w, tpwgts, ubfactor);
125  if(toplevel>0)
126  remove_empty_clusters_l2(ctrl, graph, nparts, w, tpwgts, ubfactor);
127  }
128  free(w);
129  //free(m_adjwgt);
130 }
131 
132 void Weighted_kernel_k_means(CtrlType *ctrl, GraphType *graph, int nparts, idxtype *w, float *tpwgts, float ubfactor){
133  // w is the weights
134 
135 
136  int nvtxs, nbnd, nedges, me, i, j;
137  idxtype *squared_sum, *sum, *xadj, *adjncy, *adjwgt, *where, *new_where, *bndptr, *bndind;
138  float obj, old_obj, epsilon, *inv_sum, *squared_inv_sum;
139  int change;
140  int *linearTerm, ii;
141  int loopend;
142 
143  nedges = graph->nedges;
144  nvtxs = graph->nvtxs;
145  nbnd = graph-> nbnd;
146  xadj = graph->xadj;
147  adjncy = graph->adjncy;
148  adjwgt = graph->adjwgt;
149  where = graph->where;
150  bndptr = graph->bndptr;
151  bndind = graph->bndind;
152 
153  // we need new_where because in kernel k-means distance is based on cluster label
154  // if we change a label, distance to that cluster will change
155  new_where = imalloc(nvtxs, "Weighted_kernel_k_means: new_where");
156  for (i=0; i<nvtxs; i++)
157  new_where[i] = where[i];
158 
159  sum = idxsmalloc(nparts,0, "Weighted_kernel_k_means: weight sum");
160  inv_sum = fmalloc(nparts, "Weighted_kernel_k_means: sum inverse");
161  squared_inv_sum = fmalloc(nparts, "Weighted_kernel_k_means: squared sum inverse");
162  squared_sum = idxsmalloc(nparts,0, "Weighted_kernel_k_means: weight squared sum");
163 
164  //initialization
165 
166  obj = old_obj = 0;
167  for (i=0; i<nvtxs; i++)
168  sum[where[i]] += w[i];
169  for (i=0; i<nparts; i++)
170  if(sum[i] >0){
171  inv_sum[i] = 1.0/sum[i];
172  squared_inv_sum[i] = inv_sum[i]*inv_sum[i];
173  }
174  else
175  inv_sum[i] = squared_inv_sum[i] = 0;
176 
177  /*
178  if (adjwgt == NULL) //if graph has uniform edge weights
179  for (i=0; i<nvtxs; i++){
180  me = where[i];
181  for (j=xadj[i]; j<xadj[i+1]; j++)
182  if (where[adjncy[j]] == me)
183  squared_sum[me] ++;
184  }
185  else*/
186  for (i=0; i<nvtxs; i++){
187  me = where[i];
188  for (j=xadj[i]; j<xadj[i+1]; j++)
189  if (where[adjncy[j]] == me)
190  squared_sum[me] += adjwgt[j];
191  }
192 
193  //note the obj here is not obj. fun. of wkkm, just the second trace value to be maximized
194  for (i=0; i<nparts; i++)
195  if (sum[i] >0)
196  obj += squared_sum[i]*1.0/sum[i];
197 
198  epsilon =.001;
199  linearTerm = imalloc(nparts, "Weighted_kernel_k_means: new_where");
200 
201  do{
202  float min_dist, dist;
203  int min_ind, k;
204  change =0;
205  old_obj = obj;
206  /*
207  if (adjwgt == NULL) // if graph has uniform edge weights
208  for (i=0; i<nvtxs; i++){ // compute linear term in distance from point i to all centers
209  min_ind = me = where[i];
210 
211  for (k=0; k<nparts; k++)
212  linearTerm[k] =0;
213  for (j=xadj[i]; j<xadj[i+1]; j++)
214  linearTerm[where[adjncy[j]]] ++; // this line is the only difference between if and else
215  for (k=0; k<nparts; k++)
216  printf("U%f ", linearTerm[k]*1.0/w[i]);
217  printf("\n");
218  min_dist = squared_sum[me]*w[i]-2*linearTerm[me]*sum[me];
219 
220  for (k=0; k<me; k++){
221  dist = squared_sum[k]*w[i] - 2*linearTerm[k]*sum[k];
222  if(dist*sum[min_ind]*sum[min_ind] < min_dist*sum[k]*sum[k]){
223  min_dist = dist;
224  min_ind = k;
225  }
226  }
227  for (k=me+1; k<nparts; k++){
228  dist = squared_sum[k]*w[i] - 2*linearTerm[k]*sum[k];
229  if(dist*sum[min_ind]*sum[min_ind] < min_dist*sum[k]*sum[k]){
230  min_dist = dist;
231  min_ind = k;
232  }
233  }
234 
235  if(me != min_ind){
236  new_where[i] = min_ind; // note here we can not change where; otherwise we change the center
237  change ++;
238  }
239  }
240  else // if graph weight is various
241  */
242  //printf("iteration of weighted kernel k-means...\n");
243  if(boundary_points == 1)
244  loopend = nbnd;
245  else
246  loopend = nvtxs;
247  //for (i=0; i<nvtxs; i++){ // compute linear term in distance from point i to all centers
248  for (ii=0; ii<loopend; ii++){
249  if(boundary_points == 1)
250  i = bndind[ii];
251  else
252  i = ii;
253  if(w[i] >0){
254  float inv_wi=1.0/w[i];
255  for (k=0; k<nparts; k++)
256  linearTerm[k] =0;
257  for (j=xadj[i]; j<xadj[i+1]; j++)
258  linearTerm[where[adjncy[j]]] += adjwgt[j]; //only difference between if and else
259 
260  min_ind = me = where[i];
261  min_dist = squared_sum[me]*squared_inv_sum[me] - 2*inv_wi*linearTerm[me]*inv_sum[me];
262  /*if (sum[me] >0)
263  min_dist = squared_sum[me]*1.0/(1.0*sum[me]*sum[me])-2.0*linearTerm[me]/(sum[me]*w[i]);
264  */
265  for (k=0; k<me; k++){
266  dist = squared_sum[k]*squared_inv_sum[k] -2*inv_wi*linearTerm[k]*inv_sum[k];
267  /*
268  dist = 0;
269  if (sum[k] >0)
270  dist = squared_sum[k]*1.0/(1.0*sum[k]*sum[k])-2.0*linearTerm[k]/(sum[k]*w[i]);
271  */
272  if(dist < min_dist){
273  //if(dist < min_dist){
274  min_dist = dist;
275  min_ind = k;
276  }
277  }
278  for (k=me+1; k<nparts; k++){
279  dist = squared_sum[k]*squared_inv_sum[k] -2*inv_wi*linearTerm[k]*inv_sum[k];
280  /*
281  dist = 0;
282  if (sum[k] >0)
283  dist = squared_sum[k]*1.0/(1.0*sum[k]*sum[k])-2.0*linearTerm[k]/(sum[k]*w[i]);
284  */
285  if(dist < min_dist){
286  //if(dist < min_dist){
287  min_dist = dist;
288  min_ind = k;
289  }
290  }
291 
292  if(me != min_ind){
293  new_where[i] = min_ind; // note here we can not change where; otherwise we change the center
294  change ++;
295  }
296  //if(i==0)
297  //printf("%d(%d->%d), sum=(%d, %d), linear=(%f, %f), square=(%d, %d), dis=(%f-%f, %f-%f)\n",i, me, min_ind, sum[me], sum[min_ind], linearTerm[me]*1.0/w[i],linearTerm[min_ind]*1.0/w[i],squared_sum[me], squared_sum[min_ind], squared_sum[me]*1.0/(1.0*sum[me]*sum[me]), 2.0*linearTerm[me]/(sum[me]*w[i]), squared_sum[min_ind]*1.0/(1.0*sum[min_ind]*sum[min_ind]), 2.0*linearTerm[min_ind]/(sum[min_ind]*w[i]));
298  }
299  }
300 
301  // update sum and squared_sum
302  for (i=0; i<nparts; i++)
303  sum[i] = squared_sum[i] = 0;
304  for (i=0; i<nvtxs; i++)
305  sum[new_where[i]] += w[i];
306  for (i=0; i<nparts; i++)
307  if(sum[i] >0){
308  inv_sum[i] = 1.0/sum[i];
309  squared_inv_sum[i] = inv_sum[i]*inv_sum[i];
310  }
311  else
312  inv_sum[i] = squared_inv_sum[i] = 0;
313  /*
314  if (adjwgt == NULL)
315  for (i=0; i<nvtxs; i++){
316  me = new_where[i];
317  for (j=xadj[i]; j<xadj[i+1]; j++)
318  if (new_where[adjncy[j]] == me)
319  squared_sum[me] ++;
320  }
321  else
322  */
323  for (i=0; i<nvtxs; i++){
324  me = new_where[i];
325  for (j=xadj[i]; j<xadj[i+1]; j++)
326  if (new_where[adjncy[j]] == me)
327  squared_sum[me] += adjwgt[j];
328  }
329 
330  //update objective function (trace maximizatin)
331  obj=0;
332  for (i=0; i<nparts; i++)
333  if (sum[i] >0)
334  obj += squared_sum[i]*1.0/sum[i];
335  //if matrix is not positive definite
336  if (obj > old_obj)
337  {
338  if(boundary_points == 1)
339  loopend = nbnd;
340  else
341  loopend = nvtxs;
342  //for (i=0; i<nvtxs; i++){
343  for (ii=0; ii<loopend; ii++){
344  if(boundary_points == 1)
345  i = bndind[ii];
346  else
347  i = ii;
348  where[i] = new_where[i];
349  }
350  }
351 
352  }while((obj - old_obj)> epsilon*obj);
353  free(sum); free(squared_sum); free(new_where); free(linearTerm); free(inv_sum); free(squared_inv_sum);
354 }
355 
356 /*
357 int local_search(CtrlType *ctrl, GraphType *graph, int nparts, int chain_length, idxtype *w, float *tpwgts, float ubfactor)
358  //return # of points moved
359 {
360  int nvtxs, nedges, nbnd, me, i, j, k, s, ii;
361  idxtype *sum, *squared_sum, *xadj, *adjncy, *adjwgt, *where, *bndptr, *bndind;
362  float change, obj, epsilon, **kDist, *accum_change;
363  int moves, actual_length, *mark, fidx;
364  Chains *chain;
365 
366  nedges = graph->nedges;
367  nvtxs = graph->nvtxs;
368  xadj = graph->xadj;
369  adjncy = graph->adjncy;
370  adjwgt = graph->adjwgt;
371  where = graph->where;
372  nbnd = graph->nbnd;
373  bndind = graph->bndind;
374  bndptr = graph->bndptr;
375 
376  chain = chainmalloc(chain_length, "Local_search: local search chain");
377  mark = ismalloc(nbnd, 0 , "Local_search: mark");
378  sum = idxsmalloc(nparts,0, "Local_search: weight sum");
379  squared_sum = idxsmalloc(nparts,0,"Local_search: weight squared sum");
380  kDist = f2malloc(nbnd, nparts, "Local_search: distance matrix");
381  accum_change = fmalloc(chain_length+1,"Local_search: accumulated change");
382 
383  //initialization
384  for (i = 0; i<nparts; i++)
385  sum[i] = squared_sum[i] = 0;
386  for (i = 0; i<nbnd; i++)
387  for (j = 0; j<nparts; j++)
388  kDist[i][j] = 0;
389  for (i = 0; i<chain_length+1; i++)
390  accum_change[i] = 0;
391  obj = 0;
392  moves = 0;
393  epsilon =.0001;
394  actual_length = chain_length;
395 
396  for (i=0; i<nvtxs; i++)
397  sum[where[i]] += w[i];
398  for (i=0; i<nvtxs; i++){
399  me = where[i];
400  for (j=xadj[i]; j<xadj[i+1]; j++)
401  if (where[adjncy[j]] == me)
402  squared_sum[me] += adjwgt[j];
403  }
404 
405  //the diagonal entries won't affect the result so diagonal's assumed zero
406  //for (i=0; i<nvtxs; i++)
407  for (ii=0; ii<nbnd; ii++){
408  i = bndind[ii];
409  for (j=xadj[i]; j<xadj[i+1]; j++)
410  //kDist[i][where[adjncy[j]]] += 1.0*adjwgt[j]/w[i];
411  kDist[ii][where[adjncy[j]]] += 1.0*adjwgt[j]/w[i];
412  }
413  for (k=0; k<nparts; k++)
414  if (sum[k] >0)
415  //for (i=0; i<nvtxs; i++)
416  for (ii=0; ii<nbnd; ii++)
417  //kDist[i][k] = squared_sum[k]/(1.0*sum[k]*sum[k]) - 2*kDist[i][k]/sum[k];
418  kDist[ii][k] = squared_sum[k]/(1.0*sum[k]*sum[k]) - 2*kDist[ii][k]/sum[k];
419 
420  for (i=0; i<nparts; i++)
421  if (sum[i] >0)
422  obj += squared_sum[i]*1.0/sum[i];
423 
424  for (i=0; i<chain_length; i++)
425  {
426  float tempMinChange, tempchange, temp_q;
427  int tempid, tempMoveTo, from, to, tempbndind;
428 
429  tempMinChange = obj;
430  tempchange =0;
431  tempid =0;
432  tempMoveTo = where[tempid];
433  tempbndind =0;
434 
435  //for (j=0; j<nvtxs; j++)
436  for (ii=0; ii<nbnd; ii++){
437  j = bndind[ii];
438  if (mark[ii] ==0){
439  me = where[j];
440  if (sum[me] > w[j]) // if this cluster where j belongs is not a singleton
441  for (k=0; k<nparts; k++)
442  if (k != me){
443  //tempchange = -kDist[j][me]*sum[me]*w[j]/(sum[me]-w[j]) + kDist[j][k]*sum[k]*w[j]/(sum[k]+w[j]);
444  tempchange = -kDist[ii][me]*sum[me]*w[j]/(sum[me]-w[j]) + kDist[ii][k]*sum[k]*w[j]/(sum[k]+w[j]);
445  if (tempchange < tempMinChange){
446  tempMinChange = tempchange;
447  tempid = j;
448  tempbndind = ii;
449  tempMoveTo = k;
450  }
451  }
452  }
453  }
454  if ((tempMoveTo == where[tempid]) || (mark[tempbndind] >0)){
455  actual_length = i;
456  break;
457  }
458  else{
459  // record which point is moved from its original cluster to new cluster
460  chain[i].point = tempid;
461  chain[i].from = where[tempid];
462  chain[i].to = tempMoveTo;
463  chain[i].change = tempMinChange;
464  //mark the point moved
465  mark[tempbndind] = 1;
466  // update info
467  accum_change[i+1] = accum_change[i] + tempMinChange;
468  from = chain[i].from;
469  to = chain[i].to;
470  where[tempid] = to;
471  sum[from] -= w[tempid];
472  sum[to] += w[tempid];
473 
474  for (j=xadj[tempid]; j<xadj[tempid+1]; j++)
475  if (where[adjncy[j]] == from)
476  squared_sum[from] -= 2*adjwgt[j];
477  //for (s=0; s<nvtxs; s++){
478  for (ii=0; ii<nbnd; ii++){
479  //kDist[s][from] = 0;
480  kDist[ii][from] = 0;
481  s = bndind[ii];
482  for (j=xadj[s]; j<xadj[s+1]; j++)
483  if (where[adjncy[j]] == from)
484  //kDist[s][from] += adjwgt[j]*1.0/w[s];
485  kDist[ii][from] += adjwgt[j]*1.0/w[s];
486  }
487  temp_q = squared_sum[from]/(1.0*sum[from]*sum[from]);
488 
489  //for (s=0; s<nvtxs; s++)
490  for (ii=0; ii<nbnd; ii++)
491  kDist[ii][from] = temp_q - 2*kDist[ii][from]/sum[from];
492 
493  for (j=xadj[tempid]; j<xadj[tempid+1]; j++)
494  if (where[adjncy[j]] == to)
495  squared_sum[to] += 2*adjwgt[j];
496 
497  //for (s=0; s<nvtxs; s++){
498  for (ii=0; ii<nbnd; ii++){
499  //kDist[s][to] = 0;
500  kDist[ii][to] = 0;
501  s = bndind[ii];
502  for (j=xadj[s]; j<xadj[s+1]; j++)
503  if (where[adjncy[j]] == to)
504  //kDist[s][to] += adjwgt[j]*1.0/w[s];
505  kDist[ii][to] += adjwgt[j]*1.0/w[s];
506  }
507  temp_q = squared_sum[to]/(1.0*sum[to]*sum[to]);
508 
509  //for (s=0; s<nvtxs; s++)
510  for (ii=0; ii<nbnd; ii++)
511  //kDist[s][to] = temp_q - 2*kDist[s][to]/sum[to];
512  kDist[ii][to] = temp_q - 2*kDist[ii][to]/sum[to];
513  }
514  }
515  fidx = samin(actual_length, accum_change);
516  if (accum_change[fidx] < -epsilon * obj){
517  for (i= fidx+1; i<=actual_length; i++)
518  where[chain[i-1].point] = chain[i-1].from;
519  moves = fidx;
520  change = accum_change[fidx];
521  }
522  else{
523  for (i= 0; i<actual_length; i++)
524  where[chain[i].point] = chain[i].from;
525  moves = 0;
526  change = 0;
527  }
528 
529  free(sum); free(squared_sum);free(accum_change); free(chain); free(mark);
530 
531  //for (i= 0; i<nvtxs; i++)
532  for (i= 0; i<nbnd; i++)
533  free(kDist[i]);
534  free(kDist);
535 
536  return moves;
537 }
538 */
539 
540 float onePoint_move(GraphType *graph, int nparts, idxtype *sum, idxtype *squared_sum, idxtype *w, idxtype *self_sim, int **linearTerm, int ii){
541 
542  int k, j, s, i, nbnd, temp, q1, q2, minchange_id, new_squared_sum1, new_squared_sum2, me, nedges, nvtxs;
543  float tempchange, minchange, obj, cut;
544  idxtype *xadj, *adjncy, *adjwgt, *where, *bndptr, *bndind;
545 
546  nedges = graph->nedges;
547  nvtxs = graph->nvtxs;
548  xadj = graph->xadj;
549  adjncy = graph->adjncy;
550  adjwgt = graph->adjwgt;
551  where = graph->where;
552  nbnd = graph->nbnd;
553  bndind = graph->bndind;
554  bndptr = graph->bndptr;
555 
556  //if(boundary_points == 1)
557  // s = bndind[ii];
558  //else
559  s = ii;
560  me= where[s];
561  minchange_id = me;
562  minchange = 0;
563  new_squared_sum1= new_squared_sum2= squared_sum[me];
564 
565  if (sum[me] > w[s]){ // if this cluster where j belongs is not a singleton
566  float inv_sum1 = 1.0/sum[me], inv_sum2 = 1.0/(sum[me]-w[s]);
567 
568  for(k= 0; k<me; k++){
569  q1 = squared_sum[me] - linearTerm[ii][me]*2 + self_sim[ii];
570  q2 = squared_sum[k] + linearTerm[ii][k] *2 + self_sim[ii];
571  if(sum[k] >0)
572  tempchange = squared_sum[me]*inv_sum1 + squared_sum[k]*1.0/sum[k] - q1*inv_sum2- q2*1.0/(sum[k]+w[s]);
573  else if(w[s]>0) // if sum[k] ==0 but w[s] >0
574  tempchange = squared_sum[me]*inv_sum1 - q1*inv_sum2 - q2*1.0/(sum[k]+w[s]);
575  else // if sum[k] == 0 and w[s] ==0
576  tempchange = squared_sum[me]*inv_sum1 - q1*inv_sum2;
577 
578  if(tempchange < minchange){
579  minchange = tempchange;
580  minchange_id = k;
581  new_squared_sum1 = q1;
582  new_squared_sum2 = q2;
583  }
584  }
585  for(k= me+1; k<nparts; k++){
586  q1 = squared_sum[me] - linearTerm[ii][me]*2 +self_sim[ii];
587  q2 = squared_sum[k] + linearTerm[ii][k]*2 + self_sim[ii];
588  if(sum[k] >0)
589  tempchange = squared_sum[me]*inv_sum1 + squared_sum[k]*1.0/sum[k] - q1*inv_sum2- q2*1.0/(sum[k]+w[s]);
590  else if(w[s]>0) // if sum[k] ==0 but w[s] >0
591  tempchange = squared_sum[me]*inv_sum1 - q1*inv_sum2 - q2*1.0/(sum[k]+w[s]);
592  else // if sum[k] == 0 and w[s] ==0
593  tempchange = squared_sum[me]*inv_sum1 - q1*inv_sum2;
594 
595  if(tempchange < minchange){
596  minchange = tempchange;
597  minchange_id = k;
598  new_squared_sum1 = q1;
599  new_squared_sum2 = q2;
600  }
601  }
602  if (minchange < 0){
603  where[s] = minchange_id;
604  sum[me] -= w[s];
605  sum[minchange_id] += w[s];
606  /*
607  for (ii = 0; ii<nbnd; ii++)
608  for (j = 0; j<nparts; j++)
609  linearTerm[ii][j] = 0;
610  */
611  for (j=xadj[s]; j<xadj[s+1]; j++){
612  int boundary, adj_temp;
613  adj_temp = adjncy[j];
614  boundary = bndptr[adj_temp];
615  if(boundary >-1) {
616  //if (where[adj_temp] == me){
617  //linearTerm[ii][me] -= adjwgt[j];
618  linearTerm[boundary][me] -= adjwgt[j];
619  //}
620  //if (where[adj_temp] == minchange_id){
621  //linearTerm[ii][minchange_id] += adjwgt[j];
622  linearTerm[boundary][minchange_id] += adjwgt[j];
623  //}
624  }
625  }
626  /*
627  for (ii =0; ii<nbnd; ii++){
628  i = bndind[ii];
629  for (j=xadj[i]; j<xadj[i+1]; j++)
630  linearTerm[ii][where[adjncy[j]]] += adjwgt[j];
631  }
632  */
633 
634 
635  squared_sum[me] = new_squared_sum1;
636  squared_sum[minchange_id] = new_squared_sum2;
637  }
638  }
639  return minchange;
640 }
641 
642 void move1Point2EmptyCluster(GraphType *graph, int nparts, idxtype *sum, idxtype *squared_sum, idxtype *w, idxtype *self_sim, int **linearTerm, int k){
643  int j, s, ii, nbnd, q1, q2, minchange_id, new_squared_sum1, new_squared_sum2, me, nvtxs, loopend;
644  float tempchange, minchange;
645  idxtype *xadj, *adjncy, *adjwgt, *where, *bndptr, *bndind;
646 
647  nvtxs = graph->nvtxs;
648  xadj = graph->xadj;
649  adjncy = graph->adjncy;
650  adjwgt = graph->adjwgt;
651  where = graph->where;
652  nbnd = graph->nbnd;
653  bndind = graph->bndind;
654  bndptr = graph->bndptr;
655  minchange_id = bndind[0];
656  minchange = FLT_MAX;
657 
658  if(boundary_points == 1)
659  loopend = nbnd;
660  else
661  loopend = nvtxs;
662 
663  for(ii=0; ii<loopend; ii++){
664  if(boundary_points == 1)
665  s = bndind[ii];
666  else
667  s = ii;
668  me= where[s];
669  new_squared_sum1= new_squared_sum2= squared_sum[me];
670 
671  if (sum[me] > w[s]){ // if this cluster where j belongs is not a singleton
672  float inv_sum1 = 1.0/sum[me], inv_sum2 = 1.0/(sum[me]-w[s]);
673 
674  q1 = squared_sum[me] - linearTerm[ii][me]*2 + self_sim[ii];
675  q2 = squared_sum[k] + linearTerm[ii][k] *2 + self_sim[ii];
676  if(w[s]>0) // note that sum[k] ==0; if w[s] >0
677  tempchange = squared_sum[me]*inv_sum1 - q1*inv_sum2 - q2*1.0/(sum[k]+w[s]);
678  else // if sum[k] == 0 and w[s] ==0
679  tempchange = squared_sum[me]*inv_sum1 - q1*inv_sum2;
680 
681  if(tempchange < minchange){
682  minchange = tempchange;
683  minchange_id = s;
684  new_squared_sum1 = q1;
685  new_squared_sum2 = q2;
686  }
687  }
688  }
689 
690  where[minchange_id] = k;
691  sum[me] -= w[minchange_id];
692  sum[k] += w[minchange_id];
693 
694  for (j=xadj[minchange_id]; j<xadj[minchange_id+1]; j++){
695  int boundary, adj_temp;
696  adj_temp = adjncy[j];
697  boundary = bndptr[adj_temp];
698  if(boundary >-1) {
699  linearTerm[boundary][me] -= adjwgt[j];
700  linearTerm[boundary][k] += adjwgt[j];
701  }
702  squared_sum[me] = new_squared_sum1;
703  squared_sum[k] = new_squared_sum2;
704  }
705 }
706 
707 int local_search(CtrlType *ctrl, GraphType *graph, int nparts, int chain_length, idxtype *w, float *tpwgts, float ubfactor)
708  //return # of points moved
709 {
710  int nvtxs, nedges, nbnd, me, i, j, k, s, ii, loopend;
711  idxtype *sum, *squared_sum, *xadj, *adjncy, *adjwgt, *where, *bndptr, *bndind, *self_sim;
712  float change, obj, epsilon, accum_change, minchange;
713  int moves, loopTimes, **linearTerm;
714 
715  nedges = graph->nedges;
716  nvtxs = graph->nvtxs;
717  xadj = graph->xadj;
718  adjncy = graph->adjncy;
719  adjwgt = graph->adjwgt;
720  where = graph->where;
721  nbnd = graph->nbnd;
722  bndind = graph->bndind;
723  bndptr = graph->bndptr;
724 
725  sum = idxsmalloc(nparts,0, "Local_search: weight sum");
726  squared_sum = idxsmalloc(nparts,0,"Local_search: weight squared sum");
727 
728  // EDIT: malloc to nvtxs --Brian
729  self_sim = idxsmalloc(nvtxs, 0, "Local_search: self similarity");
730  linearTerm = i2malloc(nvtxs, nparts, "Local_search: linear term");
731 
732 
733  moves = 0;
734  epsilon =.001;
735 
736  for (i=0; i<nvtxs; i++)
737  sum[where[i]] += w[i];
738  for (i=0; i<nvtxs; i++){
739  me = where[i];
740  for (j=xadj[i]; j<xadj[i+1]; j++)
741  if (where[adjncy[j]] == me)
742  squared_sum[me] += adjwgt[j];
743  }
744 
745  // EDIT here from nbnd to nvtxs
746  for (ii = 0; ii<nvtxs; ii++)
747  for (j = 0; j<nparts; j++)
748  linearTerm[ii][j] = 0;
749 
750  if(boundary_points == 1)
751  loopend = nbnd;
752  else
753  loopend = nvtxs;
754  for (ii =0; ii<loopend; ii++){
755  if(boundary_points == 1)
756  s = bndind[ii];
757  else
758  s = ii;
759  for (j=xadj[s]; j<xadj[s+1]; j++){
760  //kDist[i][where[adjncy[j]]] += 1.0*adjwgt[j]/w[i];
761  linearTerm[ii][where[adjncy[j]]] += adjwgt[j];
762  if (adjncy[j] == s)
763  self_sim[ii] = adjwgt[j];
764  }
765  }
766 
767  //the diagonal entries won't affect the result so diagonal's assumed zero
768  obj = 0;
769  for (i=0; i<nparts; i++)
770  if (sum[i] >0)
771  obj += squared_sum[i]*1.0/sum[i];
772 
773  srand(time(NULL));
774  //temperature = DEFAULT_TEMP;
775  loopTimes = 0;
776 
777  while (loopTimes < chain_length){
778  accum_change =0;
779 
780  if(boundary_points != 1)
781  {
782  for (j=0; j<nvtxs; j++)
783  minchange = onePoint_move(graph, nparts, sum, squared_sum, w, self_sim, linearTerm, j);
784  }
785  else
786  {
787  for (ii=0; ii<nbnd; ii++){
788  minchange = onePoint_move(graph, nparts, sum, squared_sum, w, self_sim, linearTerm, bndind[ii]);
789 
790  }
791  accum_change += minchange;
792  }
793 
794  if (accum_change > -epsilon * obj){
795  break;
796  }
797  moves ++;
798  loopTimes ++;
799  }
800 
801  free(sum); free(squared_sum); free(self_sim);
802 
803  for (i= 0; i<nvtxs; i++)
804  //for (i= 0; i<nbnd; i++)
805  free(linearTerm[i]);
806  free(linearTerm);
807 
808  //printf("moves = %d\n", moves);
809  return moves;
810 }
811 
812 
813 void remove_empty_clusters_l1(CtrlType *ctrl, GraphType *graph, int nparts, idxtype *w, float *tpwgts, float ubfactor){
814  int *clustersize=imalloc(nparts, "remove_empty_clusters: clusterSize");
815  int number_of_empty_cluster=0, i, s;
816 
817  for(i=0; i<nparts; i++)
818  clustersize[i] =0;
819  clusterSize(graph, clustersize);
820  for(i=0; i<nparts; i++)
821  if(clustersize[i] ==0)
822  number_of_empty_cluster ++;
823 
824  if(number_of_empty_cluster>0)
825  local_search(ctrl, graph, nparts, 1, w, tpwgts, ubfactor);
826 
827  free(clustersize);
828 }
829 
830 void remove_empty_clusters_l2(CtrlType *ctrl, GraphType *graph, int nparts, idxtype *w, float *tpwgts, float ubfactor){
831  int *clustersize=imalloc(nparts, "remove_empty_clusters: clusterSize");
832  int number_of_empty_cluster=0, i, s;
833 
834  for(i=0; i<nparts; i++)
835  clustersize[i] =0;
836  clusterSize(graph, clustersize);
837  for(i=0; i<nparts; i++)
838  if(clustersize[i] ==0)
839  number_of_empty_cluster ++;
840  //printf("%d empty clusters; ", number_of_empty_cluster);
841 
842  if(number_of_empty_cluster>0){
843  int nvtxs, me, j, k, ii, loopend;
844  idxtype *sum, *squared_sum, *xadj, *adjncy, *adjwgt, *where, *bndptr, *bndind, *self_sim, nbnd;
845  int **linearTerm;
846 
847  nvtxs = graph->nvtxs;
848  xadj = graph->xadj;
849  adjncy = graph->adjncy;
850  adjwgt = graph->adjwgt;
851  where = graph->where;
852  nbnd = graph->nbnd;
853  bndind = graph->bndind;
854  bndptr = graph->bndptr;
855 
856  sum = idxsmalloc(nparts,0, "Local_search: weight sum");
857  squared_sum = idxsmalloc(nparts,0,"Local_search: weight squared sum");
858  self_sim = idxsmalloc(nbnd, 0, "Local_search: self similarity");
859  linearTerm = i2malloc(nbnd, nparts, "Local_search: linear term");
860 
861  for (i=0; i<nvtxs; i++)
862  sum[where[i]] += w[i];
863  for (i=0; i<nvtxs; i++){
864  me = where[i];
865  for (j=xadj[i]; j<xadj[i+1]; j++)
866  if (where[adjncy[j]] == me)
867  squared_sum[me] += adjwgt[j];
868  }
869 
870  //edit here
871  for (ii = 0; ii<nvtxs; ii++)
872  for (j = 0; j<nparts; j++)
873  linearTerm[ii][j] = 0;
874  if(boundary_points == 1)
875  loopend = nbnd;
876  else
877  loopend = nvtxs;
878  for (ii =0; ii<loopend; ii++){
879  if(boundary_points == 1)
880  s = bndind[ii];
881  else
882  s = ii;
883  for (j=xadj[s]; j<xadj[s+1]; j++){
884  linearTerm[ii][where[adjncy[j]]] += adjwgt[j];
885  if (adjncy[j] == s)
886  self_sim[ii] = adjwgt[j];
887  }
888  }
889  for(k=0; k<nparts; k++)
890  if(clustersize[k] ==0){
891  move1Point2EmptyCluster(graph, nparts, sum, squared_sum, w, self_sim, linearTerm, k);
892  }
893  free(sum); free(squared_sum); free(self_sim);
894 
895  for (i= 0; i<nvtxs; i++)
896  //for (i= 0; i<nbnd; i++)
897  free(linearTerm[i]);
898  free(linearTerm);
899  }
900  /*
901  for(i=0; i<nparts; i++)
902  clustersize[i] =0;
903  number_of_empty_cluster=0;
904  clusterSize(graph, clustersize);
905  for(i=0; i<nparts; i++)
906  if(clustersize[i] ==0)
907  number_of_empty_cluster ++;
908  printf("%d empty clusters\n", number_of_empty_cluster);
909  */
910  free(clustersize);
911 }
912 
913 void MLKKMRefine(CtrlType *ctrl, GraphType *orggraph, GraphType *graph, int nparts, int chain_length, float *tpwgts, float ubfactor)
914 {
915  int i, nlevels, mustfree=0, temp_cl;
916  GraphType *ptr;
917 
918  IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->UncoarsenTmr));
919 
920  /* Compute the parameters of the coarsest graph */
921  ComputeKWayPartitionParams(ctrl, graph, nparts);
922  temp_cl = chain_length;
923 
924  /* Determine how many levels are there */
925  for (ptr=graph, nlevels=0; ptr!=orggraph; ptr=ptr->finer, nlevels++);
926  //printf("Number of levels is %d\n", nlevels);
927 
928  for (i=0; ;i++) {
929  timer tmr;
930  float result;
931 
932  cleartimer(tmr);
933  starttimer(tmr);
934 
935  //pingpong(ctrl, graph, nparts, chain_length, tpwgts, ubfactor);
936  //chain_length /= 1.5;
937  //printf("Level: %d\n", i+1);
938 
939  if (graph == orggraph){
940  //chain_length = chain_length>0 ? chain_length : 1;
941  pingpong(ctrl, graph, nparts, chain_length, tpwgts, ubfactor, 1);
942  break;
943  }
944  else{
945  //pingpong(ctrl, graph, nparts, 0, tpwgts, ubfactor, 0);
946  pingpong(ctrl, graph, nparts, chain_length, tpwgts, ubfactor, 0);
947  //chain_length /= 2;
948  }
949 
950 
951  //pingpong(ctrl, graph, nparts, chain_length, tpwgts, ubfactor);
952 
953  // /* for time and quality each level
954 
955  stoptimer(tmr);
956  //printf("Level %d: %7.3f", i+1, tmr);
957  if (cutType == NCUT){
958  result = ComputeNCut(graph, graph->where, nparts);
959  //printf(" %7f", result);
960  }
961  else{
962  result = ComputeRAsso(graph, graph->where, nparts);
963  //printf(" %7f", result);
964  }
965  //printf(" (%d)\n\n", graph->nvtxs);
966  //ends here*/
967 
968  if (graph == orggraph)
969  break;
970  /*
971  if(i>1)
972  chain_length /= 10;
973  */
974 
975  GKfree((void **) &graph->gdata, LTERM); /* Deallocate the graph related arrays */
976  graph = graph->finer;
977  IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->ProjectTmr));
978  if (graph->vwgt == NULL) {
979  graph->vwgt = idxsmalloc(graph->nvtxs, 1, "RefineKWay: graph->vwgt");
980  graph->adjwgt = idxsmalloc(graph->nedges, 1, "RefineKWay: graph->adjwgt");
981  mustfree = 1;
982  }
983  ProjectKWayPartition(ctrl, graph, nparts);
984  IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->ProjectTmr));
985  }
986 
987  if (mustfree)
988  GKfree((void **) &graph->vwgt, (void **) &graph->adjwgt, LTERM);
989 
990  IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->UncoarsenTmr));
991 }
#define NULL
core::Tensor result
Definition: VtkUtils.cpp:76
float ComputeRAsso(GraphType *graph, idxtype *where, int npart)
Definition: debug.c:20
float ComputeNCut(GraphType *graph, idxtype *where, int npart)
Definition: debug.c:67
#define RCUT
Definition: defs.h:38
#define NCUT
Definition: defs.h:36
#define MAXITERATIONS
Definition: defs.h:42
#define LTERM
Definition: defs.h:23
#define RASSO
Definition: defs.h:37
#define DBG_TIME
Definition: defs.h:174
static double dist(double x1, double y1, double x2, double y2)
Definition: lsd.c:207
#define stoptimer(tmr)
Definition: macros.h:49
#define cleartimer(tmr)
Definition: macros.h:47
#define IFSET(a, flag, cmd)
Definition: macros.h:56
#define starttimer(tmr)
Definition: macros.h:48
int ** i2malloc(int, int, char *)
Definition: util.c:148
void clusterSize(GraphType *graph, int *clustersize)
Definition: util.c:33
#define idxsmalloc
Definition: rename.h:386
#define GKfree
Definition: rename.h:380
#define ComputeKWayPartitionParams
Definition: rename.h:108
#define fmalloc
Definition: rename.h:384
#define ProjectKWayPartition
Definition: rename.h:109
#define imalloc
Definition: rename.h:382
int idxtype
Definition: struct.h:17
double timer
Definition: struct.h:215
int dbglvl
Definition: struct.h:224
timer ProjectTmr
Definition: struct.h:239
timer UncoarsenTmr
Definition: struct.h:238
int nbnd
Definition: struct.h:184
idxtype * adjncy
Definition: struct.h:172
idxtype * bndind
Definition: struct.h:185
idxtype * where
Definition: struct.h:183
int nvtxs
Definition: struct.h:168
idxtype * gdata
Definition: struct.h:164
idxtype * vwgt
Definition: struct.h:170
struct graphdef * finer
Definition: struct.h:205
int nedges
Definition: struct.h:168
idxtype * adjwgt
Definition: struct.h:173
idxtype * bndptr
Definition: struct.h:185
idxtype * xadj
Definition: struct.h:169
int local_search(CtrlType *ctrl, GraphType *graph, int nparts, int chain_length, idxtype *w, float *tpwgts, float ubfactor)
int memory_saving
int boundary_points
void move1Point2EmptyCluster(GraphType *graph, int nparts, idxtype *sum, idxtype *squared_sum, idxtype *w, idxtype *self_sim, int **linearTerm, int k)
void Weighted_kernel_k_means(CtrlType *ctrl, GraphType *graph, int nparts, idxtype *w, float *tpwgts, float ubfactor)
void Compute_Weights(CtrlType *ctrl, GraphType *graph, idxtype *w)
void remove_empty_clusters_l2(CtrlType *ctrl, GraphType *graph, int nparts, idxtype *w, float *tpwgts, float ubfactor)
float onePoint_move(GraphType *graph, int nparts, idxtype *sum, idxtype *squared_sum, idxtype *w, idxtype *self_sim, int **linearTerm, int ii)
void remove_empty_clusters_l1(CtrlType *ctrl, GraphType *graph, int nparts, idxtype *w, float *tpwgts, float ubfactor)
void transform_matrix(CtrlType *ctrl, GraphType *graph, idxtype *w, float *m_adjwgt)
void pingpong(CtrlType *ctrl, GraphType *graph, int nparts, int chain_length, float *tpwgts, float ubfactor, int toplevel)
int cutType
Definition: metis.c:3
void MLKKMRefine(CtrlType *ctrl, GraphType *orggraph, GraphType *graph, int nparts, int chain_length, float *tpwgts, float ubfactor)