ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
wkkm_boundary_only.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  printf("Chain length is %d.\n", chain_length);
107 
108  moves =0;
109  iter =0;
110 
111  //printf("Number of boundary points is %d\n", graph->nbnd);
112  do{
113  //Weighted_kernel_k_means(ctrl, graph, nparts, w, m_adjwgt, tpwgts, ubfactor);
114  Weighted_kernel_k_means(ctrl, graph, nparts, w, tpwgts, ubfactor);
115  if (chain_length>0){
116 
117  //moves = local_search(ctrl, graph, nparts, chain_length, w, m_adjwgt, tpwgts, ubfactor);
118  moves = local_search(ctrl, graph, nparts, chain_length, w, tpwgts, ubfactor);
119  printf("Number of local search moves is %d\n", moves);
120  printf("Number of boundary points is %d\n", graph->nbnd);
121  }
122  iter ++;
123  if (iter > MAXITERATIONS)
124  break;
125  }while(moves >0) ;
126  if(memory_saving ==0){
127  remove_empty_clusters_l1(ctrl, graph, nparts, w, tpwgts, ubfactor);
128  if(toplevel>0)
129  remove_empty_clusters_l2(ctrl, graph, nparts, w, tpwgts, ubfactor);
130  }
131  free(w);
132  //free(m_adjwgt);
133 }
134 
135 void Weighted_kernel_k_means(CtrlType *ctrl, GraphType *graph, int nparts, idxtype *w, float *tpwgts, float ubfactor){
136  // w is the weights
137 
138 
139  int nvtxs, nbnd, nedges, me, i, j;
140  idxtype *squared_sum, *sum, *xadj, *adjncy, *adjwgt, *where, *new_where, *bndptr, *bndind;
141  float obj, old_obj, epsilon, *inv_sum, *squared_inv_sum;
142  int change;
143  int *linearTerm, ii;
144  int loopend;
145 
146  nedges = graph->nedges;
147  nvtxs = graph->nvtxs;
148  nbnd = graph-> nbnd;
149  xadj = graph->xadj;
150  adjncy = graph->adjncy;
151  adjwgt = graph->adjwgt;
152  where = graph->where;
153  bndptr = graph->bndptr;
154  bndind = graph->bndind;
155 
156  // we need new_where because in kernel k-means distance is based on cluster label
157  // if we change a label, distance to that cluster will change
158  new_where = imalloc(nvtxs, "Weighted_kernel_k_means: new_where");
159  for (i=0; i<nvtxs; i++)
160  new_where[i] = where[i];
161 
162  sum = idxsmalloc(nparts,0, "Weighted_kernel_k_means: weight sum");
163  inv_sum = fmalloc(nparts, "Weighted_kernel_k_means: sum inverse");
164  squared_inv_sum = fmalloc(nparts, "Weighted_kernel_k_means: squared sum inverse");
165  squared_sum = idxsmalloc(nparts,0, "Weighted_kernel_k_means: weight squared sum");
166 
167  //initialization
168 
169  obj = old_obj = 0;
170  for (i=0; i<nvtxs; i++)
171  sum[where[i]] += w[i];
172  for (i=0; i<nparts; i++)
173  if(sum[i] >0){
174  inv_sum[i] = 1.0/sum[i];
175  squared_inv_sum[i] = inv_sum[i]*inv_sum[i];
176  }
177  else
178  inv_sum[i] = squared_inv_sum[i] = 0;
179 
180  /*
181  if (adjwgt == NULL) //if graph has uniform edge weights
182  for (i=0; i<nvtxs; i++){
183  me = where[i];
184  for (j=xadj[i]; j<xadj[i+1]; j++)
185  if (where[adjncy[j]] == me)
186  squared_sum[me] ++;
187  }
188  else*/
189  for (i=0; i<nvtxs; i++){
190  me = where[i];
191  for (j=xadj[i]; j<xadj[i+1]; j++)
192  if (where[adjncy[j]] == me)
193  squared_sum[me] += adjwgt[j];
194  }
195 
196  //note the obj here is not obj. fun. of wkkm, just the second trace value to be maximized
197  for (i=0; i<nparts; i++)
198  if (sum[i] >0)
199  obj += squared_sum[i]*1.0/sum[i];
200 
201  epsilon =.001;
202  linearTerm = imalloc(nparts, "Weighted_kernel_k_means: new_where");
203 
204  do{
205  float min_dist, dist;
206  int min_ind, k;
207  change =0;
208  old_obj = obj;
209  /*
210  if (adjwgt == NULL) // if graph has uniform edge weights
211  for (i=0; i<nvtxs; i++){ // compute linear term in distance from point i to all centers
212  min_ind = me = where[i];
213 
214  for (k=0; k<nparts; k++)
215  linearTerm[k] =0;
216  for (j=xadj[i]; j<xadj[i+1]; j++)
217  linearTerm[where[adjncy[j]]] ++; // this line is the only difference between if and else
218  for (k=0; k<nparts; k++)
219  printf("U%f ", linearTerm[k]*1.0/w[i]);
220  printf("\n");
221  min_dist = squared_sum[me]*w[i]-2*linearTerm[me]*sum[me];
222 
223  for (k=0; k<me; k++){
224  dist = squared_sum[k]*w[i] - 2*linearTerm[k]*sum[k];
225  if(dist*sum[min_ind]*sum[min_ind] < min_dist*sum[k]*sum[k]){
226  min_dist = dist;
227  min_ind = k;
228  }
229  }
230  for (k=me+1; k<nparts; k++){
231  dist = squared_sum[k]*w[i] - 2*linearTerm[k]*sum[k];
232  if(dist*sum[min_ind]*sum[min_ind] < min_dist*sum[k]*sum[k]){
233  min_dist = dist;
234  min_ind = k;
235  }
236  }
237 
238  if(me != min_ind){
239  new_where[i] = min_ind; // note here we can not change where; otherwise we change the center
240  change ++;
241  }
242  }
243  else // if graph weight is various
244  */
245  //printf("iteration of weighted kernel k-means...\n");
246  if(boundary_points == 1)
247  loopend = nbnd;
248  else
249  loopend = nvtxs;
250  //for (i=0; i<nvtxs; i++){ // compute linear term in distance from point i to all centers
251  for (ii=0; ii<loopend; ii++){
252  if(boundary_points == 1)
253  i = bndind[ii];
254  else
255  i = ii;
256  if(w[i] >0){
257  float inv_wi=1.0/w[i];
258  for (k=0; k<nparts; k++)
259  linearTerm[k] =0;
260  for (j=xadj[i]; j<xadj[i+1]; j++)
261  linearTerm[where[adjncy[j]]] += adjwgt[j]; //only difference between if and else
262 
263  min_ind = me = where[i];
264  min_dist = squared_sum[me]*squared_inv_sum[me] - 2*inv_wi*linearTerm[me]*inv_sum[me];
265  /*if (sum[me] >0)
266  min_dist = squared_sum[me]*1.0/(1.0*sum[me]*sum[me])-2.0*linearTerm[me]/(sum[me]*w[i]);
267  */
268  for (k=0; k<me; k++){
269  dist = squared_sum[k]*squared_inv_sum[k] -2*inv_wi*linearTerm[k]*inv_sum[k];
270  /*
271  dist = 0;
272  if (sum[k] >0)
273  dist = squared_sum[k]*1.0/(1.0*sum[k]*sum[k])-2.0*linearTerm[k]/(sum[k]*w[i]);
274  */
275  if(dist < min_dist){
276  //if(dist < min_dist){
277  min_dist = dist;
278  min_ind = k;
279  }
280  }
281  for (k=me+1; k<nparts; k++){
282  dist = squared_sum[k]*squared_inv_sum[k] -2*inv_wi*linearTerm[k]*inv_sum[k];
283  /*
284  dist = 0;
285  if (sum[k] >0)
286  dist = squared_sum[k]*1.0/(1.0*sum[k]*sum[k])-2.0*linearTerm[k]/(sum[k]*w[i]);
287  */
288  if(dist < min_dist){
289  //if(dist < min_dist){
290  min_dist = dist;
291  min_ind = k;
292  }
293  }
294 
295  if(me != min_ind){
296  new_where[i] = min_ind; // note here we can not change where; otherwise we change the center
297  change ++;
298  }
299  //if(i==0)
300  //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]));
301  }
302  }
303 
304  // update sum and squared_sum
305  for (i=0; i<nparts; i++)
306  sum[i] = squared_sum[i] = 0;
307  for (i=0; i<nvtxs; i++)
308  sum[new_where[i]] += w[i];
309  for (i=0; i<nparts; i++)
310  if(sum[i] >0){
311  inv_sum[i] = 1.0/sum[i];
312  squared_inv_sum[i] = inv_sum[i]*inv_sum[i];
313  }
314  else
315  inv_sum[i] = squared_inv_sum[i] = 0;
316  /*
317  if (adjwgt == NULL)
318  for (i=0; i<nvtxs; i++){
319  me = new_where[i];
320  for (j=xadj[i]; j<xadj[i+1]; j++)
321  if (new_where[adjncy[j]] == me)
322  squared_sum[me] ++;
323  }
324  else
325  */
326  for (i=0; i<nvtxs; i++){
327  me = new_where[i];
328  for (j=xadj[i]; j<xadj[i+1]; j++)
329  if (new_where[adjncy[j]] == me)
330  squared_sum[me] += adjwgt[j];
331  }
332 
333  //update objective function (trace maximizatin)
334  obj=0;
335  for (i=0; i<nparts; i++)
336  if (sum[i] >0)
337  obj += squared_sum[i]*1.0/sum[i];
338  //if matrix is not positive definite
339  if (obj > old_obj)
340  {
341  if(boundary_points == 1)
342  loopend = nbnd;
343  else
344  loopend = nvtxs;
345  //for (i=0; i<nvtxs; i++){
346  for (ii=0; ii<loopend; ii++){
347  if(boundary_points == 1)
348  i = bndind[ii];
349  else
350  i = ii;
351  where[i] = new_where[i];
352  }
353  }
354 
355  }while((obj - old_obj)> epsilon*obj);
356  free(sum); free(squared_sum); free(new_where); free(linearTerm); free(inv_sum); free(squared_inv_sum);
357 }
358 
359 /*
360 int local_search(CtrlType *ctrl, GraphType *graph, int nparts, int chain_length, idxtype *w, float *tpwgts, float ubfactor)
361  //return # of points moved
362 {
363  int nvtxs, nedges, nbnd, me, i, j, k, s, ii;
364  idxtype *sum, *squared_sum, *xadj, *adjncy, *adjwgt, *where, *bndptr, *bndind;
365  float change, obj, epsilon, **kDist, *accum_change;
366  int moves, actual_length, *mark, fidx;
367  Chains *chain;
368 
369  nedges = graph->nedges;
370  nvtxs = graph->nvtxs;
371  xadj = graph->xadj;
372  adjncy = graph->adjncy;
373  adjwgt = graph->adjwgt;
374  where = graph->where;
375  nbnd = graph->nbnd;
376  bndind = graph->bndind;
377  bndptr = graph->bndptr;
378 
379  chain = chainmalloc(chain_length, "Local_search: local search chain");
380  mark = ismalloc(nbnd, 0 , "Local_search: mark");
381  sum = idxsmalloc(nparts,0, "Local_search: weight sum");
382  squared_sum = idxsmalloc(nparts,0,"Local_search: weight squared sum");
383  kDist = f2malloc(nbnd, nparts, "Local_search: distance matrix");
384  accum_change = fmalloc(chain_length+1,"Local_search: accumulated change");
385 
386  //initialization
387  for (i = 0; i<nparts; i++)
388  sum[i] = squared_sum[i] = 0;
389  for (i = 0; i<nbnd; i++)
390  for (j = 0; j<nparts; j++)
391  kDist[i][j] = 0;
392  for (i = 0; i<chain_length+1; i++)
393  accum_change[i] = 0;
394  obj = 0;
395  moves = 0;
396  epsilon =.0001;
397  actual_length = chain_length;
398 
399  for (i=0; i<nvtxs; i++)
400  sum[where[i]] += w[i];
401  for (i=0; i<nvtxs; i++){
402  me = where[i];
403  for (j=xadj[i]; j<xadj[i+1]; j++)
404  if (where[adjncy[j]] == me)
405  squared_sum[me] += adjwgt[j];
406  }
407 
408  //the diagonal entries won't affect the result so diagonal's assumed zero
409  //for (i=0; i<nvtxs; i++)
410  for (ii=0; ii<nbnd; ii++){
411  i = bndind[ii];
412  for (j=xadj[i]; j<xadj[i+1]; j++)
413  //kDist[i][where[adjncy[j]]] += 1.0*adjwgt[j]/w[i];
414  kDist[ii][where[adjncy[j]]] += 1.0*adjwgt[j]/w[i];
415  }
416  for (k=0; k<nparts; k++)
417  if (sum[k] >0)
418  //for (i=0; i<nvtxs; i++)
419  for (ii=0; ii<nbnd; ii++)
420  //kDist[i][k] = squared_sum[k]/(1.0*sum[k]*sum[k]) - 2*kDist[i][k]/sum[k];
421  kDist[ii][k] = squared_sum[k]/(1.0*sum[k]*sum[k]) - 2*kDist[ii][k]/sum[k];
422 
423  for (i=0; i<nparts; i++)
424  if (sum[i] >0)
425  obj += squared_sum[i]*1.0/sum[i];
426 
427  for (i=0; i<chain_length; i++)
428  {
429  float tempMinChange, tempchange, temp_q;
430  int tempid, tempMoveTo, from, to, tempbndind;
431 
432  tempMinChange = obj;
433  tempchange =0;
434  tempid =0;
435  tempMoveTo = where[tempid];
436  tempbndind =0;
437 
438  //for (j=0; j<nvtxs; j++)
439  for (ii=0; ii<nbnd; ii++){
440  j = bndind[ii];
441  if (mark[ii] ==0){
442  me = where[j];
443  if (sum[me] > w[j]) // if this cluster where j belongs is not a singleton
444  for (k=0; k<nparts; k++)
445  if (k != me){
446  //tempchange = -kDist[j][me]*sum[me]*w[j]/(sum[me]-w[j]) + kDist[j][k]*sum[k]*w[j]/(sum[k]+w[j]);
447  tempchange = -kDist[ii][me]*sum[me]*w[j]/(sum[me]-w[j]) + kDist[ii][k]*sum[k]*w[j]/(sum[k]+w[j]);
448  if (tempchange < tempMinChange){
449  tempMinChange = tempchange;
450  tempid = j;
451  tempbndind = ii;
452  tempMoveTo = k;
453  }
454  }
455  }
456  }
457  if ((tempMoveTo == where[tempid]) || (mark[tempbndind] >0)){
458  actual_length = i;
459  break;
460  }
461  else{
462  // record which point is moved from its original cluster to new cluster
463  chain[i].point = tempid;
464  chain[i].from = where[tempid];
465  chain[i].to = tempMoveTo;
466  chain[i].change = tempMinChange;
467  //mark the point moved
468  mark[tempbndind] = 1;
469  // update info
470  accum_change[i+1] = accum_change[i] + tempMinChange;
471  from = chain[i].from;
472  to = chain[i].to;
473  where[tempid] = to;
474  sum[from] -= w[tempid];
475  sum[to] += w[tempid];
476 
477  for (j=xadj[tempid]; j<xadj[tempid+1]; j++)
478  if (where[adjncy[j]] == from)
479  squared_sum[from] -= 2*adjwgt[j];
480  //for (s=0; s<nvtxs; s++){
481  for (ii=0; ii<nbnd; ii++){
482  //kDist[s][from] = 0;
483  kDist[ii][from] = 0;
484  s = bndind[ii];
485  for (j=xadj[s]; j<xadj[s+1]; j++)
486  if (where[adjncy[j]] == from)
487  //kDist[s][from] += adjwgt[j]*1.0/w[s];
488  kDist[ii][from] += adjwgt[j]*1.0/w[s];
489  }
490  temp_q = squared_sum[from]/(1.0*sum[from]*sum[from]);
491 
492  //for (s=0; s<nvtxs; s++)
493  for (ii=0; ii<nbnd; ii++)
494  kDist[ii][from] = temp_q - 2*kDist[ii][from]/sum[from];
495 
496  for (j=xadj[tempid]; j<xadj[tempid+1]; j++)
497  if (where[adjncy[j]] == to)
498  squared_sum[to] += 2*adjwgt[j];
499 
500  //for (s=0; s<nvtxs; s++){
501  for (ii=0; ii<nbnd; ii++){
502  //kDist[s][to] = 0;
503  kDist[ii][to] = 0;
504  s = bndind[ii];
505  for (j=xadj[s]; j<xadj[s+1]; j++)
506  if (where[adjncy[j]] == to)
507  //kDist[s][to] += adjwgt[j]*1.0/w[s];
508  kDist[ii][to] += adjwgt[j]*1.0/w[s];
509  }
510  temp_q = squared_sum[to]/(1.0*sum[to]*sum[to]);
511 
512  //for (s=0; s<nvtxs; s++)
513  for (ii=0; ii<nbnd; ii++)
514  //kDist[s][to] = temp_q - 2*kDist[s][to]/sum[to];
515  kDist[ii][to] = temp_q - 2*kDist[ii][to]/sum[to];
516  }
517  }
518  fidx = samin(actual_length, accum_change);
519  if (accum_change[fidx] < -epsilon * obj){
520  for (i= fidx+1; i<=actual_length; i++)
521  where[chain[i-1].point] = chain[i-1].from;
522  moves = fidx;
523  change = accum_change[fidx];
524  }
525  else{
526  for (i= 0; i<actual_length; i++)
527  where[chain[i].point] = chain[i].from;
528  moves = 0;
529  change = 0;
530  }
531 
532  free(sum); free(squared_sum);free(accum_change); free(chain); free(mark);
533 
534  //for (i= 0; i<nvtxs; i++)
535  for (i= 0; i<nbnd; i++)
536  free(kDist[i]);
537  free(kDist);
538 
539  return moves;
540 }
541 */
542 
543 float onePoint_move(GraphType *graph, int nparts, idxtype *sum, idxtype *squared_sum, idxtype *w, idxtype *self_sim, int **linearTerm, int ii){
544 
545  int k, j, s, i, nbnd, temp, q1, q2, minchange_id, new_squared_sum1, new_squared_sum2, me, nedges, nvtxs;
546  float tempchange, minchange, obj, cut;
547  idxtype *xadj, *adjncy, *adjwgt, *where, *bndptr, *bndind;
548 
549  nedges = graph->nedges;
550  nvtxs = graph->nvtxs;
551  xadj = graph->xadj;
552  adjncy = graph->adjncy;
553  adjwgt = graph->adjwgt;
554  where = graph->where;
555  nbnd = graph->nbnd;
556  bndind = graph->bndind;
557  bndptr = graph->bndptr;
558 
559  s = bndind[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;
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  for(ii=0; ii<nbnd; ii++){
659  s = bndind[ii];
660  me= where[s];
661  new_squared_sum1= new_squared_sum2= squared_sum[me];
662 
663  if (sum[me] > w[s]){ // if this cluster where j belongs is not a singleton
664  float inv_sum1 = 1.0/sum[me], inv_sum2 = 1.0/(sum[me]-w[s]);
665 
666  q1 = squared_sum[me] - linearTerm[ii][me]*2 + self_sim[ii];
667  q2 = squared_sum[k] + linearTerm[ii][k] *2 + self_sim[ii];
668  if(w[s]>0) // note that sum[k] ==0; if w[s] >0
669  tempchange = squared_sum[me]*inv_sum1 - q1*inv_sum2 - q2*1.0/(sum[k]+w[s]);
670  else // if sum[k] == 0 and w[s] ==0
671  tempchange = squared_sum[me]*inv_sum1 - q1*inv_sum2;
672 
673  if(tempchange < minchange){
674  minchange = tempchange;
675  minchange_id = s;
676  new_squared_sum1 = q1;
677  new_squared_sum2 = q2;
678  }
679  }
680  }
681 
682  where[minchange_id] = k;
683  sum[me] -= w[minchange_id];
684  sum[k] += w[minchange_id];
685 
686  for (j=xadj[minchange_id]; j<xadj[minchange_id+1]; j++){
687  int boundary, adj_temp;
688  adj_temp = adjncy[j];
689  boundary = bndptr[adj_temp];
690  if(boundary >-1) {
691  linearTerm[boundary][me] -= adjwgt[j];
692  linearTerm[boundary][k] += adjwgt[j];
693  }
694  squared_sum[me] = new_squared_sum1;
695  squared_sum[k] = new_squared_sum2;
696  }
697 }
698 
699 int local_search(CtrlType *ctrl, GraphType *graph, int nparts, int chain_length, idxtype *w, float *tpwgts, float ubfactor)
700  //return # of points moved
701 {
702  int nvtxs, nedges, nbnd, me, i, j, k, s, ii;
703  idxtype *sum, *squared_sum, *xadj, *adjncy, *adjwgt, *where, *bndptr, *bndind, *self_sim;
704  float change, obj, epsilon, accum_change, minchange;
705  int moves, loopTimes, **linearTerm;
706 
707  nedges = graph->nedges;
708  nvtxs = graph->nvtxs;
709  xadj = graph->xadj;
710  adjncy = graph->adjncy;
711  adjwgt = graph->adjwgt;
712  where = graph->where;
713  nbnd = graph->nbnd;
714  bndind = graph->bndind;
715  bndptr = graph->bndptr;
716 
717  sum = idxsmalloc(nparts,0, "Local_search: weight sum");
718  squared_sum = idxsmalloc(nparts,0,"Local_search: weight squared sum");
719  self_sim = idxsmalloc(nbnd, 0, "Local_search: self similarity");
720  linearTerm = i2malloc(nbnd, nparts, "Local_search: linear term");
721 
722 
723  moves = 0;
724  epsilon =.001;
725 
726  for (i=0; i<nvtxs; i++)
727  sum[where[i]] += w[i];
728  for (i=0; i<nvtxs; i++){
729  me = where[i];
730  for (j=xadj[i]; j<xadj[i+1]; j++)
731  if (where[adjncy[j]] == me)
732  squared_sum[me] += adjwgt[j];
733  }
734 
735  for (ii = 0; ii<nbnd; ii++)
736  for (j = 0; j<nparts; j++)
737  linearTerm[ii][j] = 0;
738  for (ii =0; ii<nbnd; ii++){
739  s = bndind[ii];
740  for (j=xadj[s]; j<xadj[s+1]; j++){
741  //kDist[i][where[adjncy[j]]] += 1.0*adjwgt[j]/w[i];
742  linearTerm[ii][where[adjncy[j]]] += adjwgt[j];
743  if (adjncy[j] == s)
744  self_sim[ii] = adjwgt[j];
745  }
746  }
747 
748  //the diagonal entries won't affect the result so diagonal's assumed zero
749  obj = 0;
750  for (i=0; i<nparts; i++)
751  if (sum[i] >0)
752  obj += squared_sum[i]*1.0/sum[i];
753 
754  srand(time(NULL));
755  //temperature = DEFAULT_TEMP;
756  loopTimes = 0;
757 
758  while (loopTimes < chain_length){
759  accum_change =0;
760  //for (j=0; j<nvtxs; j++){
761  for (ii=0; ii<nbnd; ii++){
762  minchange = onePoint_move(graph, nparts, sum, squared_sum, w, self_sim, linearTerm, ii);
763  accum_change += minchange;
764  }
765 
766  if (accum_change > -epsilon * obj){
767  break;
768  }
769  moves ++;
770  loopTimes ++;
771  }
772 
773  free(sum); free(squared_sum); free(self_sim);
774 
775  //for (i= 0; i<nvtxs; i++)
776  for (i= 0; i<nbnd; i++)
777  free(linearTerm[i]);
778  free(linearTerm);
779 
780  //printf("moves = %d\n", moves);
781  return moves;
782 }
783 
784 
785 void remove_empty_clusters_l1(CtrlType *ctrl, GraphType *graph, int nparts, idxtype *w, float *tpwgts, float ubfactor){
786  int *clustersize=imalloc(nparts, "remove_empty_clusters: clusterSize");
787  int number_of_empty_cluster=0, i, s;
788 
789  for(i=0; i<nparts; i++)
790  clustersize[i] =0;
791  clusterSize(graph, clustersize);
792  for(i=0; i<nparts; i++)
793  if(clustersize[i] ==0)
794  number_of_empty_cluster ++;
795 
796  if(number_of_empty_cluster>0)
797  local_search(ctrl, graph, nparts, 1, w, tpwgts, ubfactor);
798 
799  free(clustersize);
800 }
801 
802 void remove_empty_clusters_l2(CtrlType *ctrl, GraphType *graph, int nparts, idxtype *w, float *tpwgts, float ubfactor){
803  int *clustersize=imalloc(nparts, "remove_empty_clusters: clusterSize");
804  int number_of_empty_cluster=0, i, s;
805 
806  for(i=0; i<nparts; i++)
807  clustersize[i] =0;
808  clusterSize(graph, clustersize);
809  for(i=0; i<nparts; i++)
810  if(clustersize[i] ==0)
811  number_of_empty_cluster ++;
812  //printf("%d empty clusters; ", number_of_empty_cluster);
813 
814  if(number_of_empty_cluster>0){
815  int nvtxs, me, j, k, ii;
816  idxtype *sum, *squared_sum, *xadj, *adjncy, *adjwgt, *where, *bndptr, *bndind, *self_sim, nbnd;
817  int **linearTerm;
818 
819  nvtxs = graph->nvtxs;
820  xadj = graph->xadj;
821  adjncy = graph->adjncy;
822  adjwgt = graph->adjwgt;
823  where = graph->where;
824  nbnd = graph->nbnd;
825  bndind = graph->bndind;
826  bndptr = graph->bndptr;
827 
828  sum = idxsmalloc(nparts,0, "Local_search: weight sum");
829  squared_sum = idxsmalloc(nparts,0,"Local_search: weight squared sum");
830  self_sim = idxsmalloc(nbnd, 0, "Local_search: self similarity");
831  linearTerm = i2malloc(nbnd, nparts, "Local_search: linear term");
832 
833  for (i=0; i<nvtxs; i++)
834  sum[where[i]] += w[i];
835  for (i=0; i<nvtxs; i++){
836  me = where[i];
837  for (j=xadj[i]; j<xadj[i+1]; j++)
838  if (where[adjncy[j]] == me)
839  squared_sum[me] += adjwgt[j];
840  }
841 
842  for (ii = 0; ii<nbnd; ii++)
843  for (j = 0; j<nparts; j++)
844  linearTerm[ii][j] = 0;
845  for (ii =0; ii<nbnd; ii++){
846  s = bndind[ii];
847  for (j=xadj[s]; j<xadj[s+1]; j++){
848  linearTerm[ii][where[adjncy[j]]] += adjwgt[j];
849  if (adjncy[j] == s)
850  self_sim[ii] = adjwgt[j];
851  }
852  }
853  for(k=0; k<nparts; k++)
854  if(clustersize[k] ==0){
855  move1Point2EmptyCluster(graph, nparts, sum, squared_sum, w, self_sim, linearTerm, k);
856  }
857  free(sum); free(squared_sum); free(self_sim);
858 
859  //for (i= 0; i<nvtxs; i++)
860  for (i= 0; i<nbnd; i++)
861  free(linearTerm[i]);
862  free(linearTerm);
863  }
864  /*
865  for(i=0; i<nparts; i++)
866  clustersize[i] =0;
867  number_of_empty_cluster=0;
868  clusterSize(graph, clustersize);
869  for(i=0; i<nparts; i++)
870  if(clustersize[i] ==0)
871  number_of_empty_cluster ++;
872  printf("%d empty clusters\n", number_of_empty_cluster);
873  */
874  free(clustersize);
875 }
876 
877 void MLKKMRefine(CtrlType *ctrl, GraphType *orggraph, GraphType *graph, int nparts, int chain_length, float *tpwgts, float ubfactor)
878 {
879  int i, nlevels, mustfree=0, temp_cl;
880  GraphType *ptr;
881 
882  IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->UncoarsenTmr));
883 
884  /* Compute the parameters of the coarsest graph */
885  ComputeKWayPartitionParams(ctrl, graph, nparts);
886  temp_cl = chain_length;
887 
888  /* Determine how many levels are there */
889  for (ptr=graph, nlevels=0; ptr!=orggraph; ptr=ptr->finer, nlevels++);
890  //printf("Number of levels is %d\n", nlevels);
891 
892  for (i=0; ;i++) {
893  timer tmr;
894  float result;
895 
896  cleartimer(tmr);
897  starttimer(tmr);
898 
899  //pingpong(ctrl, graph, nparts, chain_length, tpwgts, ubfactor);
900  //chain_length /= 1.5;
901  //printf("Level: %d\n", i+1);
902 
903  if (graph == orggraph){
904  //chain_length = chain_length>0 ? chain_length : 1;
905  pingpong(ctrl, graph, nparts, chain_length, tpwgts, ubfactor, 1);
906  break;
907  }
908  else{
909  //pingpong(ctrl, graph, nparts, 0, tpwgts, ubfactor, 0);
910  pingpong(ctrl, graph, nparts, chain_length, tpwgts, ubfactor, 0);
911  //chain_length /= 2;
912  }
913 
914 
915  //pingpong(ctrl, graph, nparts, chain_length, tpwgts, ubfactor);
916 
917  // /* for time and quality each level
918 
919  stoptimer(tmr);
920  //printf("Level %d: %7.3f", i+1, tmr);
921  if (cutType == NCUT){
922  result = ComputeNCut(graph, graph->where, nparts);
923  //printf(" %7f", result);
924  }
925  else{
926  result = ComputeRAsso(graph, graph->where, nparts);
927  //printf(" %7f", result);
928  }
929  //printf(" (%d)\n\n", graph->nvtxs);
930  //ends here*/
931 
932  if (graph == orggraph)
933  break;
934  /*
935  if(i>1)
936  chain_length /= 10;
937  */
938 
939  GKfree((void **) &graph->gdata, LTERM); /* Deallocate the graph related arrays */
940  graph = graph->finer;
941  IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->ProjectTmr));
942  if (graph->vwgt == NULL) {
943  graph->vwgt = idxsmalloc(graph->nvtxs, 1, "RefineKWay: graph->vwgt");
944  graph->adjwgt = idxsmalloc(graph->nedges, 1, "RefineKWay: graph->adjwgt");
945  mustfree = 1;
946  }
947  ProjectKWayPartition(ctrl, graph, nparts);
948  IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->ProjectTmr));
949  }
950 
951  if (mustfree)
952  GKfree((void **) &graph->vwgt, (void **) &graph->adjwgt, LTERM);
953 
954  IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->UncoarsenTmr));
955 }
#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)