ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
wkkm_old.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  * $Id: weighted kernel k-means,v 1.0 2005/1/10 $
12  *
13  */
14 
15 #include "metis.h"
16 
17 extern int cutType;
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, D^-1*A*D^-1*/
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 transform_matrix_half(CtrlType *ctrl, GraphType *graph, idxtype *w, float *m_adjwgt)
91  /* normalized the adjacency matrix for Ncut only, D^-.5*A*D^-.5*/
92 {
93  int nvtxs, i, j;
94  idxtype *xadj, *adjncy, *adjwgt, *where;
95 
96  nvtxs = graph->nvtxs;
97  xadj = graph->xadj;
98  adjncy = graph->adjncy;
99  adjwgt = graph->adjwgt;
100 
101  if (cutType == RASSO){ // ratio asso.
102  if (adjwgt == NULL)
103  for (i=0; i<nvtxs; i++)
104  for (j=xadj[i]; j<xadj[i+1]; j++)
105  m_adjwgt[j] =1;
106  else
107  for (i=0; i<nvtxs; i++)
108  for (j=xadj[i]; j<xadj[i+1]; j++)
109  m_adjwgt[j] = adjwgt[j];
110  }
111  else{ //normalize rows and columns
112  if (adjwgt == NULL){
113  for (i=0; i<nvtxs; i++)
114  for (j=xadj[i]; j<xadj[i+1]; j++)
115  if (w[i]>0)
116  m_adjwgt[j] = 1.0/sqrt(w[i]);
117  for (i=0; i<nvtxs; i++)
118  for (j=xadj[i]; j<xadj[i+1]; j++)
119  if (w[i]>0)
120  m_adjwgt[j] /= sqrt(w[adjncy[j]]);
121  }
122  else{
123  for (i=0; i<nvtxs; i++)
124  for (j=xadj[i]; j<xadj[i+1]; j++)
125  if (w[i]>0)
126  m_adjwgt[j] = adjwgt[j] *1.0/sqrt(w[i]);
127  else
128  m_adjwgt[j] = 0;
129  for (i=0; i<nvtxs; i++)
130  for (j=xadj[i]; j<xadj[i+1]; j++)
131  if (w[i]>0)
132  m_adjwgt[j] /= sqrt(w[adjncy[j]]);
133  }
134  }
135 }
136 
137 
138 void pingpong(CtrlType *ctrl, GraphType *graph, int nparts, int chain_length, float *tpwgts, float ubfactor)
139  // do batch-local search; chain_length is the search length
140 {
141 
142  int nvtxs, nedges, moves, iter;
143  idxtype *w;
144  float *m_adjwgt;
145 
146  nedges = graph->nedges;
147  nvtxs = graph->nvtxs;
148 
149  w = idxsmalloc(nvtxs, 0, "pingpong: weight");
150  Compute_Weights(ctrl, graph, w);
151  m_adjwgt = fmalloc(nedges, "pingpong: normalized matrix");
152  transform_matrix(ctrl, graph, w, m_adjwgt);
153 
154  moves =0;
155  iter =0;
156 
157  do{
158  Weighted_kernel_k_means(ctrl, graph, nparts, w, m_adjwgt, tpwgts, ubfactor);
159  if (chain_length>0)
160  moves = local_search(ctrl, graph, nparts, chain_length, w, m_adjwgt, tpwgts, ubfactor);
161  iter ++;
162  if (iter > MAXITERATIONS)
163  break;
164  }while(moves >0) ;
165 
166  free(w); free(m_adjwgt);
167 }
168 
169 
170 void Weighted_kernel_k_means(CtrlType *ctrl, GraphType *graph, int nparts, idxtype *w, float *m_adjwgt, float *tpwgts, float ubfactor)
171  // w is the weights and m_adjwgt is the kernel matrix
172 {
173 
174  int nvtxs, nedges, me, i, j;
175  idxtype *xadj, *adjncy, *adjwgt, *where, *new_where;
176  float *sum, *squared_sum, obj, old_obj, epsilon;
177  int change;
178 
179  nedges = graph->nedges;
180  nvtxs = graph->nvtxs;
181  xadj = graph->xadj;
182  adjncy = graph->adjncy;
183  adjwgt = graph->adjwgt;
184  where = graph->where;
185 
186  // we need new_where because in kernel k-means distance is based on cluster label
187  // if we change a label, distance to that cluster will change
188  new_where = imalloc(nvtxs, "Weighted_kernel_k_means: new_where");
189  for (i=0; i<nvtxs; i++)
190  new_where[i] = where[i];
191 
192  sum = fmalloc(nparts,"Weighted_kernel_k_means: weight sum");
193  squared_sum = fmalloc(nparts,"Weighted_kernel_k_means: weight squared sum");
194 
195  //initialization
196  for (i=0; i<nparts; i++)
197  sum[i] = squared_sum[i] =0;
198 
199  obj = old_obj = 0;
200  for (i=0; i<nvtxs; i++)
201  sum[where[i]] += w[i];
202  for (i=0; i<nvtxs; i++){
203  me = where[i];
204  for (j=xadj[i]; j<xadj[i+1]; j++)
205  if (where[adjncy[j]] == me)
206  squared_sum[me] += w[i]*w[adjncy[j]]*m_adjwgt[j];
207  }
208 
209  //note the obj here is not obj. fun. of wkkm, just the second trace value to be maximized
210  for (i=0; i<nparts; i++)
211  if (sum[i] >0)
212  obj += squared_sum[i]/sum[i];
213 
214  epsilon =.001;
215  /*
216  for (int i=0; i<nvtxs; i++)
217  printf("%d ", where[i]);
218  printf("$ ");
219  printf("start: %f\n", obj);
220  */
221  do{
222  float dist, temp, min_dist;
223  int min_ind, *temp_where, k;
224  change =0;
225  old_obj = obj;
226 
227  //printf(" Obj: %f\n", obj);
228 
229  // for each point, find its closest center
230  for (i=0; i<nvtxs; i++){
231  // compute distance from a point to its own center
232  min_ind = me = where[i];
233  min_dist = 0;
234  if (sum[me] >0){
235  temp =0;
236  for (j=xadj[i]; j<xadj[i+1]; j++)
237  if (where[adjncy[j]] == me)
238  temp +=w[adjncy[j]]*m_adjwgt[j];
239  min_dist = squared_sum[me]/(sum[me]*sum[me])-2*temp/sum[me];
240  }
241 
242  // compute distance from the point to other centers
243  for (k=0; k<me; k++){
244  dist =0;
245  if (sum[k] >0){
246  temp =0;
247  for (j=xadj[i]; j<xadj[i+1]; j++)
248  if (where[adjncy[j]] == k)
249  temp +=w[adjncy[j]]*m_adjwgt[j];
250  dist = squared_sum[k]/(sum[k]*sum[k])-2*temp/sum[k];
251  }
252 
253  if (dist <min_dist){
254  min_dist = dist;
255  min_ind = k;
256  }
257  }
258  for (k=me+1; k<nparts; k++){
259  dist =0;
260  if (sum[k] >0){
261  temp =0;
262  for (j=xadj[i]; j<xadj[i+1]; j++)
263  if (where[adjncy[j]] == k)
264  temp +=w[adjncy[j]]*m_adjwgt[j];
265  dist = squared_sum[k]/(sum[k]*sum[k])-2*temp/sum[k];
266  }
267 
268  if (dist <min_dist){
269  min_dist = dist;
270  min_ind = k;
271  }
272  }
273  if(me != min_ind){
274  new_where[i] = min_ind; // note here we can not change where; otherwise we change the center
275  change ++;
276  }
277  }
278 
279  // update sum and squared_sum
280  for (i=0; i<nparts; i++)
281  sum[i] = squared_sum[i] =0;
282  for (i=0; i<nvtxs; i++)
283  sum[new_where[i]] += w[i];
284  for (i=0; i<nvtxs; i++){
285  me = new_where[i];
286  for (j=xadj[i]; j<xadj[i+1]; j++)
287  if (new_where[adjncy[j]] == me)
288  squared_sum[me] += w[i]*w[adjncy[j]]*m_adjwgt[j];
289  }
290 
291  //update objective function (trace maximizatin)
292  obj=0;
293  for (i=0; i<nparts; i++)
294  if (sum[i] >0)
295  obj += squared_sum[i]/sum[i];
296  //if matrix is not positive definite
297  if (obj > old_obj)
298  for (i=0; i<nvtxs; i++)
299  where[i] = new_where[i];
300 
301  }while((obj - old_obj)> epsilon*obj);
302  /*
303  for (int i=0; i<nvtxs; i++)
304  printf("%d ", where[i]);
305  printf("$ ");
306  printf("stop: %f\n", obj);
307  */
308  free(sum); free(squared_sum); free(new_where);
309 }
310 
311 
312 int local_search(CtrlType *ctrl, GraphType *graph, int nparts, int chain_length, idxtype *w, float *m_adjwgt, float *tpwgts, float ubfactor)
313  //return # of points moved
314 {
315  int nvtxs, nedges, me, i, j, k, s;
316  idxtype *xadj, *adjncy, *adjwgt, *where;
317  float change, *sum, *squared_sum, obj, epsilon, **kDist, *accum_change;
318  int moves, actual_length, *mark, fidx;
319  Chains *chain;
320 
321  nedges = graph->nedges;
322  nvtxs = graph->nvtxs;
323  xadj = graph->xadj;
324  adjncy = graph->adjncy;
325  adjwgt = graph->adjwgt;
326  where = graph->where;
327 
328  chain = chainmalloc(chain_length, "Local_search: local search chain");
329  mark = ismalloc(nvtxs, 0 , "Local_search: mark");
330  sum = fmalloc(nparts,"Local_search: weight sum");
331  squared_sum = fmalloc(nparts,"Local_search: weight squared sum");
332  kDist = f2malloc(nvtxs, nparts, "Local_search: distance matrix");
333  accum_change = fmalloc(chain_length+1,"Local_search: accumulated change");
334 
335  //initialization
336  for (i = 0; i<nparts; i++)
337  sum[i] = squared_sum[i] = 0;
338  for (i = 0; i<nvtxs; i++)
339  for (j = 0; j<nparts; j++)
340  kDist[i][j] = 0;
341  for (i = 0; i<chain_length+1; i++)
342  accum_change[i] = 0;
343  obj = 0;
344  moves = 0;
345  epsilon =.0001;
346  actual_length = chain_length;
347 
348  for (i=0; i<nvtxs; i++)
349  sum[where[i]] += w[i];
350  for (i=0; i<nvtxs; i++){
351  me = where[i];
352  for (j=xadj[i]; j<xadj[i+1]; j++)
353  if (where[adjncy[j]] == me)
354  squared_sum[me] += w[i]*w[adjncy[j]]*m_adjwgt[j];
355  }
356 
357  //note this distance is only for METIS matrix, i.e., zero diagonal matrix
358  for (i=0; i<nvtxs; i++)
359  for (j=xadj[i]; j<xadj[i+1]; j++)
360  kDist[i][where[adjncy[j]]] +=w[adjncy[j]]*m_adjwgt[j];
361  for (k=0; k<nparts; k++)
362  if (sum[k] >0)
363  for (i=0; i<nvtxs; i++)
364  kDist[i][k] = squared_sum[k]/(sum[k]*sum[k]) - 2*kDist[i][k]/sum[k];
365 
366  for (i=0; i<nparts; i++)
367  if (sum[i] >0)
368  obj += squared_sum[i]/sum[i];
369 
370  for (i=0; i<chain_length; i++)
371  {
372  float tempMinChange, tempchange, temp_q;
373  int tempid, tempMoveTo, from, to;
374 
375  tempMinChange = obj;
376  tempchange =0;
377  tempid =0;
378  tempMoveTo = where[tempid];
379 
380  for (j=0; j<nvtxs; j++)
381  if (mark[j] ==0){
382  me = where[j];
383  if (sum[me] > w[j]) // if this cluster where j belongs is not a singleton
384  for (k=0; k<nparts; k++)
385  if (k != me){
386  tempchange = -sum[me]*w[j]/(sum[me]-w[j])*kDist[j][me]+sum[k]*w[j]/(sum[k]+w[j])*kDist[j][k];
387  if (tempchange < tempMinChange){
388  tempMinChange = tempchange;
389  tempid = j;
390  tempMoveTo = k;
391  }
392  }
393  }
394 
395  if ((tempMoveTo == where[tempid]) || (mark[tempid] >0)){
396  actual_length = i;
397  break;
398  }
399  else{
400  // record which point is moved from its original cluster to new cluster
401  chain[i].point = tempid;
402  chain[i].from = where[tempid];
403  chain[i].to = tempMoveTo;
404  chain[i].change = tempMinChange;
405  //mark the point moved
406  mark[tempid] = 1;
407  // update info
408  accum_change[i+1] = accum_change[i] + tempMinChange;
409  from = chain[i].from;
410  to = chain[i].to;
411  where[tempid] = to;
412  sum[from] -= w[tempid];
413  sum[to] += w[tempid];
414 
415  for (j=xadj[tempid]; j<xadj[tempid+1]; j++)
416  if (where[adjncy[j]] == from)
417  squared_sum[from] -= 2*w[tempid]*w[adjncy[j]]*m_adjwgt[j];
418  for (s=0; s<nvtxs; s++){
419  kDist[s][from] = 0;
420  for (j=xadj[s]; j<xadj[s+1]; j++)
421  if (where[adjncy[j]] == from)
422  kDist[s][from] += w[adjncy[j]]*m_adjwgt[j];
423  }
424  temp_q = squared_sum[from]/(sum[from]*sum[from]);
425  for (s=0; s<nvtxs; s++)
426  kDist[s][from] = temp_q - 2*kDist[s][from]/sum[from];
427 
428  for (j=xadj[tempid]; j<xadj[tempid+1]; j++)
429  if (where[adjncy[j]] == to)
430  squared_sum[to] += 2*w[tempid]*w[adjncy[j]]*m_adjwgt[j];
431  for (s=0; s<nvtxs; s++){
432  kDist[s][to] = 0;
433  for (j=xadj[s]; j<xadj[s+1]; j++)
434  if (where[adjncy[j]] == to)
435  kDist[s][to] += w[adjncy[j]]*m_adjwgt[j];
436  }
437  temp_q = squared_sum[to]/(sum[to]*sum[to]);
438  for (s=0; s<nvtxs; s++)
439  kDist[s][to] = temp_q - 2*kDist[s][to]/sum[to];
440  }
441  }
442  fidx = samin(actual_length, accum_change);
443  if (accum_change[fidx] < -epsilon * obj){
444  for (i= fidx+1; i<=actual_length; i++)
445  where[chain[i-1].point] = chain[i-1].from;
446  moves = fidx;
447  change = accum_change[fidx];
448  }
449  else{
450  for (i= 0; i<actual_length; i++)
451  where[chain[i].point] = chain[i].from;
452  moves = 0;
453  change = 0;
454  }
455 
456  free(sum); free(squared_sum);free(accum_change); free(chain); free(mark);
457  for (i= 0; i<nvtxs; i++)
458  free(kDist[i]);
459  free(kDist);
460 
461  return moves;
462 }
463 
464 void MLKKMRefine(CtrlType *ctrl, GraphType *orggraph, GraphType *graph, int nparts, int chain_length, float *tpwgts, float ubfactor)
465 {
466  int i, nlevels, mustfree=0, temp_cl;
467  GraphType *ptr;
468 
469  IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->UncoarsenTmr));
470 
471  /* Compute the parameters of the coarsest graph */
472  ComputeKWayPartitionParams(ctrl, graph, nparts);
473  temp_cl = chain_length;
474 
475  /* Determine how many levels are there */
476  for (ptr=graph, nlevels=0; ptr!=orggraph; ptr=ptr->finer, nlevels++);
477 
478  for (i=0; ;i++) {
479  timer tmr;
480  float result;
481 
482  cleartimer(tmr);
483  starttimer(tmr);
484 
485  //pingpong(ctrl, graph, nparts, chain_length, tpwgts, ubfactor);
486  //chain_length /= 1.5;
487  //printf("Level: %d\n", i+1);
488  /*
489  if (graph == orggraph){
490  pingpong(ctrl, graph, nparts, temp_cl, tpwgts, ubfactor);
491  break;
492  }
493  else{
494  pingpong(ctrl, graph, nparts, 0, tpwgts, ubfactor);
495  //chain_length /= 2;
496  }
497  */
498 
499  pingpong(ctrl, graph, nparts, chain_length, tpwgts, ubfactor);
500 
501  /* for time and quality each level
502 
503  stoptimer(tmr);
504  printf("\nLevel %d: %7.3f", i+1, tmr);
505  if (cutType == NCUT){
506  result = ComputeNCut(graph, graph->where, nparts);
507  printf(" %7f", result);
508  }
509  else{
510  result = ComputeRAsso(graph, graph->where, nparts);
511  printf(" %7f", result);
512  }
513  printf(" (%d)", graph->nvtxs);
514  ends here*/
515 
516  if (graph == orggraph)
517  break;
518  /*
519  if(i>1)
520  chain_length /= 10;
521  */
522 
523  GKfree((void **) &graph->gdata, LTERM); /* Deallocate the graph related arrays */
524  graph = graph->finer;
525  IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->ProjectTmr));
526  if (graph->vwgt == NULL) {
527  graph->vwgt = idxsmalloc(graph->nvtxs, 1, "RefineKWay: graph->vwgt");
528  graph->adjwgt = idxsmalloc(graph->nedges, 1, "RefineKWay: graph->adjwgt");
529  mustfree = 1;
530  }
531  ProjectKWayPartition(ctrl, graph, nparts);
532  IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->ProjectTmr));
533  }
534 
535  if (mustfree)
536  GKfree((void **) &graph->vwgt, (void **) &graph->adjwgt, LTERM);
537 
538  IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->UncoarsenTmr));
539 }
#define NULL
core::Tensor result
Definition: VtkUtils.cpp:76
#define RCUT
Definition: defs.h:38
#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
Chains * chainmalloc(int n, char *msg)
Definition: util.c:121
float ** f2malloc(int n, int m, char *msg)
Definition: util.c:132
#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 samin
Definition: rename.h:398
#define ProjectKWayPartition
Definition: rename.h:109
#define imalloc
Definition: rename.h:382
#define ismalloc
Definition: rename.h:385
int point
Definition: struct.h:25
int from
Definition: struct.h:26
float change
Definition: struct.h:28
int to
Definition: struct.h:27
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
idxtype * adjncy
Definition: struct.h:172
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 * xadj
Definition: struct.h:169
Definition: lsd.c:149
void Compute_Weights(CtrlType *ctrl, GraphType *graph, idxtype *w)
Definition: wkkm_old.c:19
void Weighted_kernel_k_means(CtrlType *ctrl, GraphType *graph, int nparts, idxtype *w, float *m_adjwgt, float *tpwgts, float ubfactor)
Definition: wkkm_old.c:170
void transform_matrix(CtrlType *ctrl, GraphType *graph, idxtype *w, float *m_adjwgt)
Definition: wkkm_old.c:43
void pingpong(CtrlType *ctrl, GraphType *graph, int nparts, int chain_length, float *tpwgts, float ubfactor)
Definition: wkkm_old.c:138
int local_search(CtrlType *ctrl, GraphType *graph, int nparts, int chain_length, idxtype *w, float *m_adjwgt, float *tpwgts, float ubfactor)
Definition: wkkm_old.c:312
int cutType
Definition: metis.c:3
void MLKKMRefine(CtrlType *ctrl, GraphType *orggraph, GraphType *graph, int nparts, int chain_length, float *tpwgts, float ubfactor)
Definition: wkkm_old.c:464
void transform_matrix_half(CtrlType *ctrl, GraphType *graph, idxtype *w, float *m_adjwgt)
Definition: wkkm_old.c:90