Actual source code: miscoloring.c

petsc-dev 2014-02-02
Report Typos and Errors
  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,&degrees);
147:       PetscSFComputeDegreeEnd(etor,&degrees);
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,&degrees);
170:       PetscSFComputeDegreeEnd(etoc,&degrees);
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,&degrees);
231:       PetscSFComputeDegreeEnd(etor,&degrees);
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,&degrees);
254:       PetscSFComputeDegreeEnd(etoc,&degrees);
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: }