00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "metislib.h"
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 void genmmd(idx_t neqns, idx_t *xadj, idx_t *adjncy, idx_t *invp, idx_t *perm,
00054 idx_t delta, idx_t *head, idx_t *qsize, idx_t *list, idx_t *marker,
00055 idx_t maxint, idx_t *ncsub)
00056 {
00057 idx_t ehead, i, mdeg, mdlmt, mdeg_node, nextmd, num, tag;
00058
00059 if (neqns <= 0)
00060 return;
00061
00062
00063 xadj--; adjncy--; invp--; perm--; head--; qsize--; list--; marker--;
00064
00065
00066 *ncsub = 0;
00067 mmdint(neqns, xadj, adjncy, head, invp, perm, qsize, list, marker);
00068
00069
00070 num = 1;
00071
00072
00073 nextmd = head[1];
00074 while (nextmd > 0) {
00075 mdeg_node = nextmd;
00076 nextmd = invp[mdeg_node];
00077 marker[mdeg_node] = maxint;
00078 invp[mdeg_node] = -num;
00079 num = num + 1;
00080 }
00081
00082
00083
00084 if (num > neqns)
00085 goto n1000;
00086 tag = 1;
00087 head[1] = 0;
00088 mdeg = 2;
00089
00090
00091 while (1) {
00092 while (head[mdeg] <= 0)
00093 mdeg++;
00094
00095
00096
00097 mdlmt = mdeg + delta;
00098 ehead = 0;
00099
00100 n500:
00101 mdeg_node = head[mdeg];
00102 while (mdeg_node <= 0) {
00103 mdeg++;
00104
00105 if (mdeg > mdlmt)
00106 goto n900;
00107 mdeg_node = head[mdeg];
00108 };
00109
00110
00111 nextmd = invp[mdeg_node];
00112 head[mdeg] = nextmd;
00113 if (nextmd > 0)
00114 perm[nextmd] = -mdeg;
00115 invp[mdeg_node] = -num;
00116 *ncsub += mdeg + qsize[mdeg_node] - 2;
00117 if ((num+qsize[mdeg_node]) > neqns)
00118 goto n1000;
00119
00120
00121
00122 tag++;
00123 if (tag >= maxint) {
00124 tag = 1;
00125 for (i = 1; i <= neqns; i++)
00126 if (marker[i] < maxint)
00127 marker[i] = 0;
00128 };
00129
00130 mmdelm(mdeg_node, xadj, adjncy, head, invp, perm, qsize, list, marker, maxint, tag);
00131
00132 num += qsize[mdeg_node];
00133 list[mdeg_node] = ehead;
00134 ehead = mdeg_node;
00135 if (delta >= 0)
00136 goto n500;
00137
00138 n900:
00139
00140
00141 if (num > neqns)
00142 goto n1000;
00143 mmdupd( ehead, neqns, xadj, adjncy, delta, &mdeg, head, invp, perm, qsize, list, marker, maxint, &tag);
00144 };
00145
00146 n1000:
00147 mmdnum( neqns, perm, invp, qsize );
00148
00149
00150 xadj++; adjncy++; invp++; perm++; head++; qsize++; list++; marker++;
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 void mmdelm(idx_t mdeg_node, idx_t *xadj, idx_t *adjncy, idx_t *head, idx_t *forward,
00172 idx_t *backward, idx_t *qsize, idx_t *list, idx_t *marker, idx_t maxint, idx_t tag)
00173 {
00174 idx_t element, i, istop, istart, j,
00175 jstop, jstart, link,
00176 nabor, node, npv, nqnbrs, nxnode,
00177 pvnode, rlmt, rloc, rnode, xqnbr;
00178
00179
00180
00181 marker[mdeg_node] = tag;
00182 istart = xadj[mdeg_node];
00183 istop = xadj[mdeg_node+1] - 1;
00184
00185
00186
00187
00188 element = 0;
00189 rloc = istart;
00190 rlmt = istop;
00191 for ( i = istart; i <= istop; i++ ) {
00192 nabor = adjncy[i];
00193 if ( nabor == 0 ) break;
00194 if ( marker[nabor] < tag ) {
00195 marker[nabor] = tag;
00196 if ( forward[nabor] < 0 ) {
00197 list[nabor] = element;
00198 element = nabor;
00199 } else {
00200 adjncy[rloc] = nabor;
00201 rloc++;
00202 };
00203 };
00204 };
00205
00206
00207 while ( element > 0 ) {
00208 adjncy[rlmt] = -element;
00209 link = element;
00210
00211 n400:
00212 jstart = xadj[link];
00213 jstop = xadj[link+1] - 1;
00214 for ( j = jstart; j <= jstop; j++ ) {
00215 node = adjncy[j];
00216 link = -node;
00217 if ( node < 0 ) goto n400;
00218 if ( node == 0 ) break;
00219 if ((marker[node]<tag)&&(forward[node]>=0)) {
00220 marker[node] = tag;
00221
00222 while ( rloc >= rlmt ) {
00223 link = -adjncy[rlmt];
00224 rloc = xadj[link];
00225 rlmt = xadj[link+1] - 1;
00226 };
00227 adjncy[rloc] = node;
00228 rloc++;
00229 };
00230 };
00231 element = list[element];
00232 };
00233 if ( rloc <= rlmt ) adjncy[rloc] = 0;
00234
00235 link = mdeg_node;
00236
00237 n1100:
00238 istart = xadj[link];
00239 istop = xadj[link+1] - 1;
00240 for ( i = istart; i <= istop; i++ ) {
00241 rnode = adjncy[i];
00242 link = -rnode;
00243 if ( rnode < 0 ) goto n1100;
00244 if ( rnode == 0 ) return;
00245
00246
00247 pvnode = backward[rnode];
00248 if (( pvnode != 0 ) && ( pvnode != (-maxint) )) {
00249
00250 nxnode = forward[rnode];
00251 if ( nxnode > 0 ) backward[nxnode] = pvnode;
00252 if ( pvnode > 0 ) forward[pvnode] = nxnode;
00253 npv = -pvnode;
00254 if ( pvnode < 0 ) head[npv] = nxnode;
00255 };
00256
00257
00258 jstart = xadj[rnode];
00259 jstop = xadj[rnode+1] - 1;
00260 xqnbr = jstart;
00261 for ( j = jstart; j <= jstop; j++ ) {
00262 nabor = adjncy[j];
00263 if ( nabor == 0 ) break;
00264 if ( marker[nabor] < tag ) {
00265 adjncy[xqnbr] = nabor;
00266 xqnbr++;
00267 };
00268 };
00269
00270
00271 nqnbrs = xqnbr - jstart;
00272 if ( nqnbrs <= 0 ) {
00273
00274 qsize[mdeg_node] += qsize[rnode];
00275 qsize[rnode] = 0;
00276 marker[rnode] = maxint;
00277 forward[rnode] = -mdeg_node;
00278 backward[rnode] = -maxint;
00279 } else {
00280
00281
00282 forward[rnode] = nqnbrs + 1;
00283 backward[rnode] = 0;
00284 adjncy[xqnbr] = mdeg_node;
00285 xqnbr++;
00286 if ( xqnbr <= jstop ) adjncy[xqnbr] = 0;
00287 };
00288 };
00289 return;
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 idx_t mmdint(idx_t neqns, idx_t *xadj, idx_t *adjncy, idx_t *head, idx_t *forward,
00306 idx_t *backward, idx_t *qsize, idx_t *list, idx_t *marker)
00307 {
00308 idx_t fnode, ndeg, node;
00309
00310 for ( node = 1; node <= neqns; node++ ) {
00311 head[node] = 0;
00312 qsize[node] = 1;
00313 marker[node] = 0;
00314 list[node] = 0;
00315 };
00316
00317
00318 for ( node = 1; node <= neqns; node++ ) {
00319 ndeg = xadj[node+1] - xadj[node];
00320 if (ndeg == 0)
00321 ndeg = 1;
00322 fnode = head[ndeg];
00323 forward[node] = fnode;
00324 head[ndeg] = node;
00325 if ( fnode > 0 ) backward[fnode] = node;
00326 backward[node] = -ndeg;
00327 };
00328 return 0;
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348 void mmdnum(idx_t neqns, idx_t *perm, idx_t *invp, idx_t *qsize)
00349 {
00350 idx_t father, nextf, node, nqsize, num, root;
00351
00352 for ( node = 1; node <= neqns; node++ ) {
00353 nqsize = qsize[node];
00354 if ( nqsize <= 0 ) perm[node] = invp[node];
00355 if ( nqsize > 0 ) perm[node] = -invp[node];
00356 };
00357
00358
00359 for ( node = 1; node <= neqns; node++ ) {
00360 if ( perm[node] <= 0 ) {
00361
00362
00363
00364 father = node;
00365 while ( perm[father] <= 0 )
00366 father = - perm[father];
00367
00368
00369 root = father;
00370 num = perm[root] + 1;
00371 invp[node] = -num;
00372 perm[root] = num;
00373
00374
00375 father = node;
00376 nextf = - perm[father];
00377 while ( nextf > 0 ) {
00378 perm[father] = -root;
00379 father = nextf;
00380 nextf = -perm[father];
00381 };
00382 };
00383 };
00384
00385
00386 for ( node = 1; node <= neqns; node++ ) {
00387 num = -invp[node];
00388 invp[node] = num;
00389 perm[num] = node;
00390 };
00391 return;
00392 }
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 void mmdupd(idx_t ehead, idx_t neqns, idx_t *xadj, idx_t *adjncy, idx_t delta, idx_t *mdeg,
00413 idx_t *head, idx_t *forward, idx_t *backward, idx_t *qsize, idx_t *list,
00414 idx_t *marker, idx_t maxint, idx_t *tag)
00415 {
00416 idx_t deg, deg0, element, enode, fnode, i, iq2, istop,
00417 istart, j, jstop, jstart, link, mdeg0, mtag, nabor,
00418 node, q2head, qxhead;
00419
00420 mdeg0 = *mdeg + delta;
00421 element = ehead;
00422
00423 n100:
00424 if ( element <= 0 ) return;
00425
00426
00427
00428 mtag = *tag + mdeg0;
00429 if ( mtag >= maxint ) {
00430 *tag = 1;
00431 for ( i = 1; i <= neqns; i++ )
00432 if ( marker[i] < maxint ) marker[i] = 0;
00433 mtag = *tag + mdeg0;
00434 };
00435
00436
00437
00438
00439
00440 q2head = 0;
00441 qxhead = 0;
00442 deg0 = 0;
00443 link =element;
00444
00445 n400:
00446 istart = xadj[link];
00447 istop = xadj[link+1] - 1;
00448 for ( i = istart; i <= istop; i++ ) {
00449 enode = adjncy[i];
00450 link = -enode;
00451 if ( enode < 0 ) goto n400;
00452 if ( enode == 0 ) break;
00453 if ( qsize[enode] != 0 ) {
00454 deg0 += qsize[enode];
00455 marker[enode] = mtag;
00456
00457
00458 if ( backward[enode] == 0 ) {
00459
00460 if ( forward[enode] != 2 ) {
00461 list[enode] = qxhead;
00462 qxhead = enode;
00463 } else {
00464 list[enode] = q2head;
00465 q2head = enode;
00466 };
00467 };
00468 };
00469 };
00470
00471
00472 enode = q2head;
00473 iq2 = 1;
00474
00475 n900:
00476 if ( enode <= 0 ) goto n1500;
00477 if ( backward[enode] != 0 ) goto n2200;
00478 (*tag)++;
00479 deg = deg0;
00480
00481
00482 istart = xadj[enode];
00483 nabor = adjncy[istart];
00484 if ( nabor == element ) nabor = adjncy[istart+1];
00485 link = nabor;
00486 if ( forward[nabor] >= 0 ) {
00487
00488 deg += qsize[nabor];
00489 goto n2100;
00490 };
00491
00492
00493
00494 n1000:
00495 istart = xadj[link];
00496 istop = xadj[link+1] - 1;
00497 for ( i = istart; i <= istop; i++ ) {
00498 node = adjncy[i];
00499 link = -node;
00500 if ( node != enode ) {
00501 if ( node < 0 ) goto n1000;
00502 if ( node == 0 ) goto n2100;
00503 if ( qsize[node] != 0 ) {
00504 if ( marker[node] < *tag ) {
00505
00506 marker[node] = *tag;
00507 deg += qsize[node];
00508 } else {
00509 if ( backward[node] == 0 ) {
00510 if ( forward[node] == 2 ) {
00511
00512
00513 qsize[enode] += qsize[node];
00514 qsize[node] = 0;
00515 marker[node] = maxint;
00516 forward[node] = -enode;
00517 backward[node] = -maxint;
00518 } else {
00519
00520 if (backward[node]==0) backward[node] = -maxint;
00521 };
00522 };
00523 };
00524 };
00525 };
00526 };
00527 goto n2100;
00528
00529 n1500:
00530
00531 enode = qxhead;
00532 iq2 = 0;
00533
00534 n1600: if ( enode <= 0 ) goto n2300;
00535 if ( backward[enode] != 0 ) goto n2200;
00536 (*tag)++;
00537 deg = deg0;
00538
00539
00540 istart = xadj[enode];
00541 istop = xadj[enode+1] - 1;
00542 for ( i = istart; i <= istop; i++ ) {
00543 nabor = adjncy[i];
00544 if ( nabor == 0 ) break;
00545 if ( marker[nabor] < *tag ) {
00546 marker[nabor] = *tag;
00547 link = nabor;
00548 if ( forward[nabor] >= 0 )
00549
00550 deg += qsize[nabor];
00551 else {
00552 n1700:
00553
00554
00555 jstart = xadj[link];
00556 jstop = xadj[link+1] - 1;
00557 for ( j = jstart; j <= jstop; j++ ) {
00558 node = adjncy[j];
00559 link = -node;
00560 if ( node < 0 ) goto n1700;
00561 if ( node == 0 ) break;
00562 if ( marker[node] < *tag ) {
00563 marker[node] = *tag;
00564 deg += qsize[node];
00565 };
00566 };
00567 };
00568 };
00569 };
00570
00571 n2100:
00572
00573
00574 deg = deg - qsize[enode] + 1;
00575 fnode = head[deg];
00576 forward[enode] = fnode;
00577 backward[enode] = -deg;
00578 if ( fnode > 0 ) backward[fnode] = enode;
00579 head[deg] = enode;
00580 if ( deg < *mdeg ) *mdeg = deg;
00581
00582 n2200:
00583
00584 enode = list[enode];
00585 if ( iq2 == 1 ) goto n900;
00586 goto n1600;
00587
00588 n2300:
00589
00590 *tag = mtag;
00591 element = list[element];
00592 goto n100;
00593 }