Actual source code: miscoloring.c
petsc-dev 2014-02-02
1: #include <petsc-private/matimpl.h> /*I "petscmat.h" I*/
2: #include <petscsf.h>
4: PETSC_EXTERN PetscErrorCode MatColoringCreateBipartiteGraph(MatColoring,PetscSF *,PetscSF *);
5: PETSC_EXTERN PetscErrorCode MatColoringDiscoverBoundary(MatColoring,PetscSF,PetscSF,PetscInt *,PetscInt**);
7: typedef struct {
8: PetscSF etoc;
9: PetscSF etor;
10: PetscReal *wts;
11: PetscReal *wtsinit;
12: PetscReal *wtscol;
13: PetscReal *wtsrow;
14: PetscReal *wtsleafrow;
15: PetscReal *wtsleafcol;
16: PetscReal *wtsspread;
17: PetscInt *state;
18: PetscInt *statecol;
19: PetscInt *staterow;
20: PetscInt *stateleafcol;
21: PetscInt *stateleafrow;
22: PetscInt *statespread;
23: ISColoringValue *color;
24: } MC_MIS;
28: PetscErrorCode MISCreateWeights_Private(MatColoring mc)
29: {
30: MC_MIS *mis = (MC_MIS *)mc->data;
32: PetscInt i,ncols;
33: PetscRandom rand;
34: PetscReal *wts = mis->wts;
35: PetscReal r;
36: const PetscInt *coldegrees;
37: PetscSF etoc=mis->etoc;
40: /* each weight should be the degree plus a random perturbation */
41: PetscSFGetGraph(etoc,&ncols,NULL,NULL,NULL);
42: PetscSFComputeDegreeBegin(etoc,&coldegrees);
43: PetscSFComputeDegreeEnd(etoc,&coldegrees);
44: PetscRandomCreate(PetscObjectComm((PetscObject)mc),&rand);
45: PetscRandomSetFromOptions(rand);
46: for (i=0;i<ncols;i++) {
47: PetscRandomGetValueReal(rand,&r);
48: wts[i] = coldegrees[i] + PetscAbsReal(r);
49: }
50: PetscRandomDestroy(&rand);
51: return(0);
52: }
56: PetscErrorCode MISInitialize_Private(MatColoring mc)
57: {
58: MC_MIS *mis = (MC_MIS *)mc->data;
59: PetscInt i,croot,cleaf,rroot,rleaf;
63: MatColoringCreateBipartiteGraph(mc,&mis->etoc,&mis->etor);
64: PetscSFGetGraph(mis->etoc,&croot,&cleaf,NULL,NULL);
65: PetscSFGetGraph(mis->etor,&rroot,&rleaf,NULL,NULL);
66: PetscMalloc7(croot,&mis->wts,
67: croot,&mis->wtsinit,
68: croot,&mis->wtscol,
69: rroot,&mis->wtsrow,
70: croot,&mis->wtsspread,
71: cleaf,&mis->wtsleafcol,
72: rleaf,&mis->wtsleafrow);
73: PetscMalloc6(croot,&mis->state,
74: croot,&mis->statecol,
75: rroot,&mis->staterow,
76: croot,&mis->statespread,
77: cleaf,&mis->stateleafcol,
78: rleaf,&mis->stateleafrow);
79: PetscMalloc(sizeof(ISColoringValue)*croot,&mis->color);
80: for (i=0;i<croot;i++) {
81: mis->color[i] = IS_COLORING_MAX;
82: }
83: return(0);
84: }
88: PetscErrorCode MatColoringDestroy_MIS(MatColoring mc)
89: {
93: PetscFree(mc->data);
94: return(0);
95: }
99: PetscErrorCode MISTearDown_Private(MatColoring mc)
100: {
101: MC_MIS *mis = (MC_MIS *)mc->data;
105: PetscSFDestroy(&mis->etoc);
106: PetscSFDestroy(&mis->etor);
107: PetscFree7(mis->wts,
108: mis->wtsinit,
109: mis->wtscol,
110: mis->wtsrow,
111: mis->wtsspread,
112: mis->wtsleafcol,
113: mis->wtsleafrow);
114: PetscFree6(mis->state,
115: mis->statecol,
116: mis->staterow,
117: mis->statespread,
118: mis->stateleafcol,
119: mis->stateleafrow);
120: return(0);
121: }
125: PetscErrorCode MISGreatestWeight_Private(MatColoring mc,PetscReal *wtsin,PetscReal *maxwts)
126: {
127: MC_MIS *mis = (MC_MIS *)mc->data;
128: PetscInt nrows,ncols,nentries,idx,dist=mc->dist;
129: PetscInt i,j,k;
130: const PetscInt *degrees;
131: PetscReal *ewts,*wtsrow=mis->wtsrow,*wtscol=mis->wtscol;
132: PetscSF etoc=mis->etoc,etor=mis->etor;
136: nentries=0;
137: PetscSFGetGraph(etor,&nrows,NULL,NULL,NULL);
138: PetscSFGetGraph(etoc,&ncols,NULL,NULL,NULL);
139: for (i=0;i<ncols;i++) {
140: wtscol[i] = wtsin[i];
141: }
142: for (k=0;k<dist;k++) {
143: if (k%2 == 1) {
144: /* second step takes the row weights to the column weights */
145: PetscLogEventBegin(Mat_Coloring_Comm,mc,0,0,0);
146: PetscSFComputeDegreeBegin(etor,°rees);
147: PetscSFComputeDegreeEnd(etor,°rees);
148: PetscLogEventEnd(Mat_Coloring_Comm,mc,0,0,0);
149: nentries=0;
150: for(i=0;i<nrows;i++) {
151: nentries += degrees[i];
152: }
153: idx=0;
154: ewts = mis->wtsleafrow;
155: for(i=0;i<nrows;i++) {
156: for (j=0;j<degrees[i];j++) {
157: ewts[idx] = wtsrow[i];
158: idx++;
159: }
160: wtscol[i]=0.;
161: }
162: if (idx != nentries) SETERRQ2(PetscObjectComm((PetscObject)mc),PETSC_ERR_NOT_CONVERGED,"Bad number of entries %d vs %d",idx,nentries);
163: PetscLogEventBegin(Mat_Coloring_Comm,mc,0,0,0);
164: PetscSFReduceBegin(etoc,MPI_DOUBLE,ewts,wtscol,MPI_MAX);
165: PetscSFReduceEnd(etoc,MPI_DOUBLE,ewts,wtscol,MPI_MAX);
166: PetscLogEventEnd(Mat_Coloring_Comm,mc,0,0,0);
167: } else {
168: /* first step takes the column weights to the row weights */
169: PetscSFComputeDegreeBegin(etoc,°rees);
170: PetscSFComputeDegreeEnd(etoc,°rees);
171: nentries=0;
172: for(i=0;i<ncols;i++) {
173: nentries += degrees[i];
174: }
175: ewts = mis->wtsleafcol;
176: idx=0;
177: for(i=0;i<ncols;i++) {
178: for (j=0;j<degrees[i];j++) {
179: ewts[idx] = wtscol[i];
180: idx++;
181: }
182: wtsrow[i]=0.;
183: }
184: if (idx != nentries) SETERRQ2(PetscObjectComm((PetscObject)mc),PETSC_ERR_NOT_CONVERGED,"Bad number of entries %d vs %d",idx,nentries);
185: PetscLogEventBegin(Mat_Coloring_Comm,mc,0,0,0);
186: PetscSFReduceBegin(etor,MPI_DOUBLE,ewts,wtsrow,MPI_MAX);
187: PetscSFReduceEnd(etor,MPI_DOUBLE,ewts,wtsrow,MPI_MAX);
188: PetscLogEventEnd(Mat_Coloring_Comm,mc,0,0,0);
189: }
190: }
191: if (mc->dist % 2 == 1) {
192: /* if it's an odd number of steps, copy out the square part */
193: for (i=0;i<ncols;i++) {
194: if (i < nrows) {
195: maxwts[i] = wtsrow[i];
196: } else {
197: maxwts[i] = 0;
198: }
199: }
200: } else {
201: for (i=0;i<ncols;i++) {
202: maxwts[i] = wtscol[i];
203: }
204: }
205: return(0);
206: }
210: PetscErrorCode MISSpreadState_Private(MatColoring mc,PetscInt *statein,PetscInt *stateout)
211: {
212: MC_MIS *mis = (MC_MIS *)mc->data;
213: PetscInt nrows,ncols,nentries,idx,dist=mc->dist;
214: PetscInt i,j,k;
215: const PetscInt *degrees;
216: PetscInt *estate;
217: PetscInt *staterow=mis->staterow,*statecol=mis->statecol;
218: PetscSF etoc=mis->etoc,etor=mis->etor;
222: PetscSFGetGraph(etoc,&ncols,NULL,NULL,NULL);
223: PetscSFGetGraph(etor,&nrows,NULL,NULL,NULL);
224: for (i=0;i<ncols;i++) {
225: statecol[i] = statein[i];
226: }
227: for (k=0;k<dist;k++) {
228: if (k%2 == 1) {
229: PetscLogEventBegin(Mat_Coloring_Comm,mc,0,0,0);
230: PetscSFComputeDegreeBegin(etor,°rees);
231: PetscSFComputeDegreeEnd(etor,°rees);
232: PetscLogEventEnd(Mat_Coloring_Comm,mc,0,0,0);
233: nentries=0;
234: for(i=0;i<nrows;i++) {
235: nentries += degrees[i];
236: }
237: estate = mis->stateleafrow;
238: idx=0;
239: for(i=0;i<nrows;i++) {
240: for (j=0;j<degrees[i];j++) {
241: estate[idx] = staterow[i];
242: idx++;
243: }
244: statecol[i]=0;
245: }
246: if (idx != nentries) SETERRQ2(PetscObjectComm((PetscObject)mc),PETSC_ERR_NOT_CONVERGED,"Bad number of entries %d vs %d",idx,nentries);
247: PetscLogEventBegin(Mat_Coloring_Comm,etoc,0,0,0);
248: PetscSFReduceBegin(etoc,MPIU_INT,estate,statecol,MPIU_MAX);
249: PetscSFReduceEnd(etoc,MPIU_INT,estate,statecol,MPIU_MAX);
250: PetscLogEventEnd(Mat_Coloring_Comm,etoc,0,0,0);
251: } else {
252: PetscLogEventBegin(Mat_Coloring_Comm,etoc,0,0,0);
253: PetscSFComputeDegreeBegin(etoc,°rees);
254: PetscSFComputeDegreeEnd(etoc,°rees);
255: PetscLogEventEnd(Mat_Coloring_Comm,etoc,0,0,0);
256: nentries=0;
257: for(i=0;i<ncols;i++) {
258: nentries += degrees[i];
259: }
260: idx=0;
261: estate = mis->stateleafcol;
262: for(i=0;i<ncols;i++) {
263: for (j=0;j<degrees[i];j++) {
264: estate[idx] = statecol[i];
265: idx++;
266: }
267: staterow[i]=0;
268: }
269: if (idx != nentries) SETERRQ2(PetscObjectComm((PetscObject)mc),PETSC_ERR_NOT_CONVERGED,"Bad number of entries %d vs %d",idx,nentries);
270: PetscLogEventBegin(Mat_Coloring_Comm,etor,0,0,0);
271: PetscSFReduceBegin(etor,MPIU_INT,estate,staterow,MPI_MAX);
272: PetscSFReduceEnd(etor,MPIU_INT,estate,staterow,MPI_MAX);
273: PetscLogEventEnd(Mat_Coloring_Comm,etor,0,0,0);
274: }
275: }
276: if (mc->dist % 2 == 1) {
277: /* if it's an odd number of steps, copy out the square part */
278: for (i=0;i<ncols;i++) {
279: if (i < nrows) {
280: stateout[i] = staterow[i];
281: } else {
282: stateout[i] = 0;
283: }
284: }
285: } else {
286: for (i=0;i<ncols;i++) {
287: stateout[i] = statecol[i];
288: }
289: }
290: return(0);
291: }
295: PetscErrorCode MISCompute_Private(MatColoring mc,ISColoringValue curcolor,PetscInt *nadded_global)
296: {
297: MC_MIS *mis = (MC_MIS *)mc->data;
298: PetscInt nr,nc,i;
299: PetscInt *state=mis->state,*spreadstate=mis->statespread;
300: PetscErrorCode ierr;
301: PetscReal *wts=mis->wts,*wtsinit=mis->wtsinit,*wtsspread=mis->wtsspread;
302: PetscInt nadded,misadded,misadded_global;
303: PetscSF etoc=mis->etoc,etor=mis->etor;
304: ISColoringValue *colors = mis->color;
307: nadded=0;
308: misadded_global=1;
309: PetscSFGetGraph(etor,&nr,NULL,NULL,NULL);
310: PetscSFGetGraph(etoc,&nc,NULL,NULL,NULL);
311: for (i=0;i<nc;i++) {
312: if (colors[i] == IS_COLORING_MAX) {
313: wtsinit[i] = wts[i];
314: } else {
315: /* already has a color and thus isn't in the graph any longer */
316: wtsinit[i] = 0.;
317: }
318: state[i]=0;
319: wtsspread[i]=0.;
320: spreadstate[i]=0;
321: }
322: while (misadded_global > 0) {
323: MISGreatestWeight_Private(mc,wtsinit,wtsspread);
324: misadded = 0;
325: for (i=0;i<nc;i++) {
326: if (wtsinit[i] >= wtsspread[i] && wtsinit[i] != 0.) {
327: /* pick this one */
328: colors[i] = curcolor;
329: nadded++;
330: state[i] = 1;
331: wtsinit[i] = 0.;
332: misadded++;
333: } else {
334: state[i] = 0;
335: }
336: }
337: misadded_global = 0;
338: MPI_Allreduce(&misadded,&misadded_global,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mc));
339: MISSpreadState_Private(mc,state,spreadstate);
340: for (i=0;i<nc;i++) {
341: /* eliminated */
342: if (colors[i] == IS_COLORING_MAX && state[i] == 0 && spreadstate[i] == 1) {
343: wtsinit[i] = 0.;
344: }
345: }
346: }
347: *nadded_global=0;
348: MPI_Allreduce(&nadded,nadded_global,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mc));
349: return(0);
350: }
354: PETSC_EXTERN PetscErrorCode MatColoringApply_MIS(MatColoring mc,ISColoring *iscoloring)
355: {
356: MC_MIS *mis=(MC_MIS*)mc->data;
357: PetscErrorCode ierr;
358: ISColoringValue curcolor,finalcolor;
359: ISColoringValue *color;
360: PetscInt i,nadded,nadded_total,ncolstotal,ncols;
363: nadded=1;
364: nadded_total=0;
365: MatGetSize(mc->mat,NULL,&ncolstotal);
366: MatGetLocalSize(mc->mat,NULL,&ncols);
367: MISInitialize_Private(mc);
368: color = mis->color;
369: MISCreateWeights_Private(mc);
370: curcolor=0;
371: for (i=0;(i<mc->maxcolors || mc->maxcolors == 0) && (nadded_total < ncolstotal);i++) {
372: MISCompute_Private(mc,curcolor,&nadded);
373: nadded_total += nadded;
374: if (!nadded && nadded_total != ncolstotal) {SETERRQ(PetscObjectComm((PetscObject)mc),PETSC_ERR_NOT_CONVERGED,"MatColoringApply_MIS made no progress");}
375: curcolor++;
376: }
377: finalcolor = curcolor;
378: for (i=0;i<ncols;i++) {
379: /* set up a dummy color if the coloring has been truncated */
380: if (color[i] == IS_COLORING_MAX) {
381: color[i] = curcolor;
382: finalcolor = curcolor+1;
383: }
384: }
385: ISColoringCreate(PetscObjectComm((PetscObject)mc),finalcolor,ncols,color,iscoloring);
386: MISTearDown_Private(mc);
387: return(0);
388: }
392: /*MC
393: MATCOLORINGMIS - Maximal Independent Set based Matrix Coloring
395: Level: beginner
397: Notes: This algorithm uses a Luby-type method to create a series of independent sets that may be combined into a
398: maximal independent set. This is repeated on the induced subgraph of uncolored vertices until every column of the
399: matrix is assigned a color. This algorithm supports arbitrary distance. If the maximum number of colors is set to
400: one, it will create a maximal independent set.
402: .seealso: MatColoringCreate(), MatColoring, MatColoringSetType()
403: M*/
404: PETSC_EXTERN PetscErrorCode MatColoringCreate_MIS(MatColoring mc)
405: {
406: MC_MIS *mis;
410: PetscNewLog(mc,&mis);
411: mc->data = mis;
412: mc->ops->apply = MatColoringApply_MIS;
413: mc->ops->view = NULL;
414: mc->ops->destroy = MatColoringDestroy_MIS;
415: mc->ops->setfromoptions = NULL;
416: return(0);
417: }