Actual source code: weights.c
petsc-3.7.1 2016-05-15
Report Typos and Errors

      1: #include <petsc/private/matimpl.h>      /*I "petscmat.h"  I*/
      2: #include <../src/mat/impls/aij/seq/aij.h>

      6: PetscErrorCode MatColoringCreateLexicalWeights(MatColoring mc,PetscReal *weights)
      7: {
      9:   PetscInt       i,s,e;
     10:   Mat            G=mc->mat;

     13:   MatGetOwnershipRange(G,&s,&e);
     14:   for (i=s;i<e;i++) {
     15:     weights[i-s] = i;
     16:   }
     17:   return(0);
     18: }

     22: PetscErrorCode MatColoringCreateRandomWeights(MatColoring mc,PetscReal *weights)
     23: {
     25:   PetscInt       i,s,e;
     26:   PetscRandom    rand;
     27:   PetscReal      r;
     28:   Mat            G = mc->mat;

     31:   /* each weight should be the degree plus a random perturbation */
     32:   PetscRandomCreate(PetscObjectComm((PetscObject)mc),&rand);
     33:   PetscRandomSetFromOptions(rand);
     34:   MatGetOwnershipRange(G,&s,&e);
     35:   for (i=s;i<e;i++) {
     36:     PetscRandomGetValueReal(rand,&r);
     37:     weights[i-s] = PetscAbsReal(r);
     38:   }
     39:   PetscRandomDestroy(&rand);
     40:   return(0);
     41: }

     45: PetscErrorCode MatColoringGetDegrees(Mat G,PetscInt distance,PetscInt *degrees)
     46: {
     47:   PetscInt       j,i,s,e,n,ln,lm,degree,bidx,idx,dist;
     48:   Mat            lG,*lGs;
     49:   IS             ris;
     51:   PetscInt       *seen;
     52:   const PetscInt *gidx;
     53:   PetscInt       *idxbuf;
     54:   PetscInt       *distbuf;
     55:   PetscInt       ncols;
     56:   const PetscInt *cols;
     57:   PetscBool      isSEQAIJ;
     58:   Mat_SeqAIJ     *aij;
     59:   PetscInt       *Gi,*Gj;

     62:   MatGetOwnershipRange(G,&s,&e);
     63:   n=e-s;
     64:   ISCreateStride(PetscObjectComm((PetscObject)G),n,s,1,&ris);
     65:   MatIncreaseOverlap(G,1,&ris,distance);
     66:   ISSort(ris);
     67:   MatGetSubMatrices(G,1,&ris,&ris,MAT_INITIAL_MATRIX,&lGs);
     68:   lG = lGs[0];
     69:   PetscObjectTypeCompare((PetscObject)lG,MATSEQAIJ,&isSEQAIJ);
     70:   if (!isSEQAIJ) SETERRQ(PetscObjectComm((PetscObject)G),PETSC_ERR_SUP,"Requires an MPI/SEQAIJ Matrix");
     71:   MatGetSize(lG,&ln,&lm);
     72:   aij = (Mat_SeqAIJ*)lG->data;
     73:   Gi = aij->i;
     74:   Gj = aij->j;
     75:   PetscMalloc3(lm,&seen,lm,&idxbuf,lm,&distbuf);
     76:   for (i=0;i<ln;i++) {
     77:     seen[i]=-1;
     78:   }
     79:   ISGetIndices(ris,&gidx);
     80:   for (i=0;i<ln;i++) {
     81:     if (gidx[i] >= e || gidx[i] < s) continue;
     82:     bidx=-1;
     83:     ncols = Gi[i+1]-Gi[i];
     84:     cols = &(Gj[Gi[i]]);
     85:     degree = 0;
     86:     /* place the distance-one neighbors on the queue */
     87:     for (j=0;j<ncols;j++) {
     88:       bidx++;
     89:       seen[cols[j]] = i;
     90:       distbuf[bidx] = 1;
     91:       idxbuf[bidx] = cols[j];
     92:     }
     93:     while (bidx >= 0) {
     94:       /* pop */
     95:       idx = idxbuf[bidx];
     96:       dist = distbuf[bidx];
     97:       bidx--;
     98:       degree++;
     99:       if (dist < distance) {
    100:         ncols = Gi[idx+1]-Gi[idx];
    101:         cols = &(Gj[Gi[idx]]);
    102:         for (j=0;j<ncols;j++) {
    103:           if (seen[cols[j]] != i) {
    104:             bidx++;
    105:             seen[cols[j]] = i;
    106:             idxbuf[bidx] = cols[j];
    107:             distbuf[bidx] = dist+1;
    108:           }
    109:         }
    110:       }
    111:     }
    112:     degrees[gidx[i]-s] = degree;
    113:   }
    114:   ISRestoreIndices(ris,&gidx);
    115:   ISDestroy(&ris);
    116:   PetscFree3(seen,idxbuf,distbuf);
    117:   MatDestroyMatrices(1,&lGs);
    118:   return(0);
    119: }

    123: PetscErrorCode MatColoringCreateLargestFirstWeights(MatColoring mc,PetscReal *weights)
    124: {
    126:   PetscInt       i,s,e,n,ncols;
    127:   PetscRandom    rand;
    128:   PetscReal      r;
    129:   PetscInt       *degrees;
    130:   Mat            G = mc->mat;

    133:   /* each weight should be the degree plus a random perturbation */
    134:   PetscRandomCreate(PetscObjectComm((PetscObject)mc),&rand);
    135:   PetscRandomSetFromOptions(rand);
    136:   MatGetOwnershipRange(G,&s,&e);
    137:   n=e-s;
    138:   PetscMalloc1(n,&degrees);
    139:   MatColoringGetDegrees(G,mc->dist,degrees);
    140:   for (i=s;i<e;i++) {
    141:     MatGetRow(G,i,&ncols,NULL,NULL);
    142:     PetscRandomGetValueReal(rand,&r);
    143:     weights[i-s] = ncols + PetscAbsReal(r);
    144:     MatRestoreRow(G,i,&ncols,NULL,NULL);
    145:   }
    146:   PetscRandomDestroy(&rand);
    147:   PetscFree(degrees);
    148:   return(0);
    149: }

    153: PetscErrorCode MatColoringCreateSmallestLastWeights(MatColoring mc,PetscReal *weights)
    154: {
    155:   PetscInt       *degrees,*degb,*llprev,*llnext;
    156:   PetscInt       j,i,s,e,n,nin,ln,lm,degree,maxdegree=0,bidx,idx,dist,distance=mc->dist;
    157:   Mat            lG,*lGs;
    158:   IS             ris;
    160:   PetscInt       *seen;
    161:   const PetscInt *gidx;
    162:   PetscInt       *idxbuf;
    163:   PetscInt       *distbuf;
    164:   PetscInt       ncols,nxt,prv,cur;
    165:   const PetscInt *cols;
    166:   PetscBool      isSEQAIJ;
    167:   Mat_SeqAIJ     *aij;
    168:   PetscInt       *Gi,*Gj,*rperm;
    169:   Mat            G = mc->mat;
    170:   PetscReal      *lweights,r;
    171:   PetscRandom    rand;

    174:   MatGetOwnershipRange(G,&s,&e);
    175:   n=e-s;
    176:   ISCreateStride(PetscObjectComm((PetscObject)G),n,s,1,&ris);
    177:   MatIncreaseOverlap(G,1,&ris,distance+1);
    178:   ISSort(ris);
    179:   MatGetSubMatrices(G,1,&ris,&ris,MAT_INITIAL_MATRIX,&lGs);
    180:   lG = lGs[0];
    181:   PetscObjectTypeCompare((PetscObject)lG,MATSEQAIJ,&isSEQAIJ);
    182:   if (!isSEQAIJ) SETERRQ(PetscObjectComm((PetscObject)G),PETSC_ERR_ARG_WRONGSTATE,"Requires an MPI/SEQAIJ Matrix");
    183:   MatGetSize(lG,&ln,&lm);
    184:   aij = (Mat_SeqAIJ*)lG->data;
    185:   Gi = aij->i;
    186:   Gj = aij->j;
    187:   PetscMalloc3(lm,&seen,lm,&idxbuf,lm,&distbuf);
    188:   PetscMalloc1(lm,&degrees);
    189:   PetscMalloc1(lm,&lweights);
    190:   for (i=0;i<ln;i++) {
    191:     seen[i]=-1;
    192:     lweights[i] = 1.;
    193:   }
    194:   ISGetIndices(ris,&gidx);
    195:   for (i=0;i<ln;i++) {
    196:     bidx=-1;
    197:     ncols = Gi[i+1]-Gi[i];
    198:     cols = &(Gj[Gi[i]]);
    199:     degree = 0;
    200:     /* place the distance-one neighbors on the queue */
    201:     for (j=0;j<ncols;j++) {
    202:       bidx++;
    203:       seen[cols[j]] = i;
    204:       distbuf[bidx] = 1;
    205:       idxbuf[bidx] = cols[j];
    206:     }
    207:     while (bidx >= 0) {
    208:       /* pop */
    209:       idx = idxbuf[bidx];
    210:       dist = distbuf[bidx];
    211:       bidx--;
    212:       degree++;
    213:       if (dist < distance) {
    214:         ncols = Gi[idx+1]-Gi[idx];
    215:         cols = &(Gj[Gi[idx]]);
    216:         for (j=0;j<ncols;j++) {
    217:           if (seen[cols[j]] != i) {
    218:             bidx++;
    219:             seen[cols[j]] = i;
    220:             idxbuf[bidx] = cols[j];
    221:             distbuf[bidx] = dist+1;
    222:           }
    223:         }
    224:       }
    225:     }
    226:     degrees[i] = degree;
    227:     if (degree > maxdegree) maxdegree = degree;
    228:   }
    229:   /* bucket by degree by some random permutation */
    230:   PetscRandomCreate(PetscObjectComm((PetscObject)mc),&rand);
    231:   PetscRandomSetFromOptions(rand);
    232:   PetscMalloc1(ln,&rperm);
    233:   for (i=0;i<ln;i++) {
    234:       PetscRandomGetValueReal(rand,&r);
    235:       lweights[i] = r;
    236:       rperm[i]=i;
    237:   }
    238:   PetscSortRealWithPermutation(lm,lweights,rperm);
    239:   PetscMalloc1(maxdegree+1,&degb);
    240:   PetscMalloc2(ln,&llnext,ln,&llprev);
    241:   for (i=0;i<maxdegree+1;i++) {
    242:     degb[i] = -1;
    243:   }
    244:   for (i=0;i<ln;i++) {
    245:     llnext[i] = -1;
    246:     llprev[i] = -1;
    247:     seen[i] = -1;
    248:   }
    249:   for (i=0;i<ln;i++) {
    250:     idx = rperm[i];
    251:     llnext[idx] = degb[degrees[idx]];
    252:     if (degb[degrees[idx]] > 0) llprev[degb[degrees[idx]]] = idx;
    253:     degb[degrees[idx]] = idx;
    254:   }
    255:   PetscFree(rperm);
    256:   /* remove the lowest degree one */
    257:   i=0;
    258:   nin=0;
    259:   while (i != maxdegree+1) {
    260:     for (i=1;i<maxdegree+1; i++) {
    261:       if (degb[i] > 0) {
    262:         cur = degb[i];
    263:         nin++;
    264:         degrees[cur] = 0;
    265:         degb[i] = llnext[cur];
    266:         bidx=-1;
    267:         ncols = Gi[cur+1]-Gi[cur];
    268:         cols = &(Gj[Gi[cur]]);
    269:         /* place the distance-one neighbors on the queue */
    270:         for (j=0;j<ncols;j++) {
    271:           if (cols[j] != cur) {
    272:             bidx++;
    273:             seen[cols[j]] = i;
    274:             distbuf[bidx] = 1;
    275:             idxbuf[bidx] = cols[j];
    276:           }
    277:         }
    278:         while (bidx >= 0) {
    279:           /* pop */
    280:           idx = idxbuf[bidx];
    281:           dist = distbuf[bidx];
    282:           bidx--;
    283:           nxt=llnext[idx];
    284:           prv=llprev[idx];
    285:           if (degrees[idx] > 0) {
    286:             /* change up the degree of the neighbors still in the graph */
    287:             if (lweights[idx] <= lweights[cur]) lweights[idx] = lweights[cur]+1;
    288:             if (nxt > 0) {
    289:               llprev[nxt] = prv;
    290:             }
    291:             if (prv > 0) {
    292:               llnext[prv] = nxt;
    293:             } else {
    294:               degb[degrees[idx]] = nxt;
    295:             }
    296:             degrees[idx]--;
    297:             llnext[idx] = degb[degrees[idx]];
    298:             llprev[idx] = -1;
    299:             if (degb[degrees[idx]] >= 0) {
    300:               llprev[degb[degrees[idx]]] = idx;
    301:             }
    302:             degb[degrees[idx]] = idx;
    303:             if (dist < distance) {
    304:               ncols = Gi[idx+1]-Gi[idx];
    305:               cols = &(Gj[Gi[idx]]);
    306:               for (j=0;j<ncols;j++) {
    307:                 if (seen[cols[j]] != i) {
    308:                   bidx++;
    309:                   seen[cols[j]] = i;
    310:                   idxbuf[bidx] = cols[j];
    311:                   distbuf[bidx] = dist+1;
    312:                 }
    313:               }
    314:             }
    315:           }
    316:         }
    317:         break;
    318:       }
    319:     }
    320:   }
    321:   for (i=0;i<lm;i++) {
    322:     if (gidx[i] >= s && gidx[i] < e) {
    323:       weights[gidx[i]-s] = lweights[i];
    324:     }
    325:   }
    326:   PetscRandomDestroy(&rand);
    327:   PetscFree(degb);
    328:   PetscFree2(llnext,llprev);
    329:   PetscFree(degrees);
    330:   PetscFree(lweights);
    331:   ISRestoreIndices(ris,&gidx);
    332:   ISDestroy(&ris);
    333:   PetscFree3(seen,idxbuf,distbuf);
    334:   MatDestroyMatrices(1,&lGs);
    335:   return(0);
    336: }

    340: PetscErrorCode MatColoringCreateWeights(MatColoring mc,PetscReal **weights,PetscInt **lperm)
    341: {
    343:   PetscInt       i,s,e,n;
    344:   PetscReal      *wts;

    347:   /* create weights of the specified type */
    348:   MatGetOwnershipRange(mc->mat,&s,&e);
    349:   n=e-s;
    350:   PetscMalloc1(n,&wts);
    351:   switch(mc->weight_type) {
    352:   case MAT_COLORING_WEIGHT_RANDOM:
    353:     MatColoringCreateRandomWeights(mc,wts);
    354:     break;
    355:   case MAT_COLORING_WEIGHT_LEXICAL:
    356:     MatColoringCreateLexicalWeights(mc,wts);
    357:     break;
    358:   case MAT_COLORING_WEIGHT_LF:
    359:     MatColoringCreateLargestFirstWeights(mc,wts);
    360:     break;
    361:   case MAT_COLORING_WEIGHT_SL:
    362:     MatColoringCreateSmallestLastWeights(mc,wts);
    363:     break;
    364:   }
    365:   if (lperm) {
    366:     PetscMalloc1(n,lperm);
    367:     for (i=0;i<n;i++) {
    368:       (*lperm)[i] = i;
    369:     }
    370:     PetscSortRealWithPermutation(n,wts,*lperm);
    371:     for (i=0;i<n/2;i++) {
    372:       PetscInt swp;
    373:       swp = (*lperm)[i];
    374:       (*lperm)[i] = (*lperm)[n-1-i];
    375:       (*lperm)[n-1-i] = swp;
    376:     }
    377:   }
    378:   if (weights) *weights = wts;
    379:   return(0);
    380: }

    384: PetscErrorCode MatColoringSetWeights(MatColoring mc,PetscReal *weights,PetscInt *lperm)
    385: {
    387:   PetscInt       i,s,e,n;

    390:   MatGetOwnershipRange(mc->mat,&s,&e);
    391:   n=e-s;
    392:   if (weights) {
    393:     PetscMalloc2(n,&mc->user_weights,n,&mc->user_lperm);
    394:     for (i=0;i<n;i++) {
    395:       mc->user_weights[i]=weights[i];
    396:     }
    397:     if (!lperm) {
    398:       for (i=0;i<n;i++) {
    399:         mc->user_lperm[i]=i;
    400:       }
    401:       PetscSortRealWithPermutation(n,mc->user_weights,mc->user_lperm);
    402:       for (i=0;i<n/2;i++) {
    403:         PetscInt swp;
    404:         swp = mc->user_lperm[i];
    405:         mc->user_lperm[i] = mc->user_lperm[n-1-i];
    406:         mc->user_lperm[n-1-i] = swp;
    407:       }
    408:     } else {
    409:       for (i=0;i<n;i++) {
    410:         mc->user_lperm[i]=lperm[i];
    411:       }
    412:     }
    413:   } else {
    414:     mc->user_weights = NULL;
    415:     mc->user_lperm = NULL;
    416:   }
    417:   return(0);
    418: }