|
|
1.1 ! root 1: #include "draw_dag.h" ! 2: ! 3: #include <sys/types.h> ! 4: #include <sys/times.h> ! 5: #define TIC 60 ! 6: ! 7: ! 8: /* ! 9: Assign horizontal positions to nodes ! 10: */ ! 11: ! 12: // Edge factors depend on their adjacent nodes. ! 13: // The weight system chosen below encourages straight long edges and paths. ! 14: // The node naming scheme is: ! 15: // s: a real node with <=1 in-edge and <=1 out-edge ! 16: // v: a virtual node ! 17: // e: anything else. ! 18: static const int C_ee = 1, ! 19: C_es = 1, ! 20: C_ev = 1, ! 21: C_vs = 2, ! 22: C_ss = 2, ! 23: C_vv = 8; ! 24: ! 25: static int *Selfwidth; // width of nodes with self edges ! 26: ! 27: static void levelposition(int), ! 28: bestposition(), ! 29: goodposition(), ! 30: smoothedges(); ! 31: static int rlength(int*, int*); ! 32: static inline int widthof(int); ! 33: ! 34: ! 35: #ifdef DEBUG ! 36: static void checkpos(int *nodepos) ! 37: { ! 38: for(int l = 0; l <= Maxlevel; ++l) ! 39: for(int *r = Rank[l]+1; *r != -1; ++r) ! 40: if((nodepos[r[-1]]+widthof(r[-1])/2+Nodesep) > ! 41: (nodepos[r[0]]-widthof(r[0])/2)) ! 42: panic("Bad position assignment"); ! 43: } ! 44: #endif ! 45: ! 46: ! 47: // ranksepar = 0 for full flexibility ! 48: // 1 for forcing all ranks be separate by a max amount ! 49: // computed to avoid edge/node intersections ! 50: // >1 for fixing at user's requested separation ! 51: ! 52: void dag_positions(int ranksepar, int opt_level) ! 53: { ! 54: struct tms begtm, endtm; ! 55: if(Verbose) ! 56: { ! 57: #ifndef TIMING ! 58: fprintf(stderr,"Assign positions\n"); ! 59: #endif ! 60: times(&begtm); ! 61: } ! 62: ! 63: // additional widths for nodes with self edges ! 64: if(N_self_edges > 0) ! 65: { ! 66: Selfwidth = new int[N_nodes]; ! 67: for(int i = 0; i < N_real_nodes; ++i) ! 68: { ! 69: if(Rank[Level[i]][Invert[i]+1] == -1) ! 70: continue; ! 71: ! 72: for(edge_t *e = Noedges[i]; e; e = e->next) ! 73: if(e->node == i) ! 74: break; ! 75: if(e) ! 76: Selfwidth[i] = e->width + Nodesep; ! 77: } ! 78: } ! 79: ! 80: // compute node positions ! 81: Nodepos = new int[N_nodes]; ! 82: if(opt_level >= 1) ! 83: bestposition(); ! 84: else goodposition(); ! 85: ! 86: // readjust node positions if there are self edges ! 87: if(N_self_edges > 0) ! 88: { ! 89: for(int i = 0; i < N_real_nodes; ++i) ! 90: if(Selfwidth[i] > 0) ! 91: Nodepos[i] -= Selfwidth[i]/2; ! 92: delete Selfwidth; ! 93: } ! 94: ! 95: // compute layer position ! 96: Levelpos = new int[Maxlevel+1]; ! 97: levelposition(ranksepar); ! 98: ! 99: // smooth out little turns in long edges ! 100: Deleted = new int[N_nodes]; ! 101: smoothedges(); ! 102: ! 103: // readjust positions to start from 0 ! 104: int minx = Maxint; ! 105: for(int i = 0; i <= Maxlevel; ++i) ! 106: if(Nodepos[Rank[i][0]] < minx) ! 107: minx = Nodepos[Rank[i][0]]; ! 108: if(minx != 0) ! 109: for(i = 0; i < N_nodes; ++i) ! 110: Nodepos[i] -= minx; ! 111: ! 112: if(Verbose) ! 113: { ! 114: times(&endtm); ! 115: int total = (endtm.tms_utime-begtm.tms_utime) + ! 116: (endtm.tms_stime-begtm.tms_stime); ! 117: int percent = (total - (total/TIC)*TIC)*100/TIC; ! 118: #ifdef TIMING ! 119: fprintf(stderr,"%d.%02d\t",total/TIC, percent); ! 120: #else ! 121: fprintf(stderr,"Time in coordinates assignment: %d.%02ds\n", ! 122: total/TIC, percent); ! 123: #endif ! 124: } ! 125: } ! 126: ! 127: ! 128: ! 129: // for an edge top->bot and the horizontal assignment of nodes, ! 130: // compute the separation between respective layers that would ! 131: // guarantee that the edge does not intersect any drawings of other ! 132: // nodes. ! 133: ! 134: static int vsepar(int top, int bot, int *toprank, int *botrank, int separ) ! 135: { ! 136: int xtop = Nodepos[top]; ! 137: int xbot = Nodepos[bot]; ! 138: int minx = min(xtop,xbot); ! 139: int maxx = max(xtop,xbot); ! 140: int htop = top < N_real_nodes ? Height[top]/2 : Levelheight[Level[top]]/2; ! 141: int hbot = bot < N_real_nodes ? Height[bot]/2 : Levelheight[Level[bot]]/2; ! 142: ! 143: if(maxx-minx < Nodesep) ! 144: return separ; ! 145: ! 146: for(; *toprank != -1; ++toprank) ! 147: if(Nodepos[*toprank] > minx && *toprank < N_real_nodes) ! 148: break; ! 149: for(; *toprank != -1; ++toprank) ! 150: { ! 151: if(Nodepos[*toprank] >= maxx) ! 152: break; ! 153: if(*toprank >= N_real_nodes) ! 154: continue; ! 155: ! 156: // the side of the box that may intersect with the edge ! 157: int x = Nodepos[*toprank] + (Width[*toprank]/2)*(xtop>xbot ? 1:-1); ! 158: if(x == xtop) ! 159: continue; ! 160: ! 161: // the height of that side ! 162: int h = Height[*toprank]+Nodesep; ! 163: ! 164: // the separation required ! 165: int s = (int)((double)((htop*(xbot-x)+h*(xtop-xbot)))/(xtop-x)); ! 166: if((s += hbot) >= separ) ! 167: separ = s; ! 168: } ! 169: for(; *botrank != -1; ++botrank) ! 170: if(Nodepos[*botrank] > minx && *botrank < N_real_nodes) ! 171: break; ! 172: for(; *botrank != -1; ++botrank) ! 173: { ! 174: if(Nodepos[*botrank] >= maxx) ! 175: break; ! 176: if(*botrank >= N_real_nodes) ! 177: continue; ! 178: int x = Nodepos[*botrank] + (Width[*botrank]/2)*(xbot>xtop ? 1:-1); ! 179: if(x == xbot) ! 180: continue; ! 181: int h = Height[*botrank]+Nodesep; ! 182: int s = (int)((double)((hbot*(x-xtop)+h*(xtop-xbot)))/(x-xbot)); ! 183: if((s += htop) > separ) ! 184: separ = s; ! 185: } ! 186: ! 187: return separ; ! 188: } ! 189: ! 190: ! 191: ! 192: static void levelposition(int ranksepar) ! 193: { ! 194: int maxsep = 0; ! 195: Levelpos[0] = Levelheight[0]/2; ! 196: for(int i = 1; i <= Maxlevel; ++i) ! 197: { ! 198: int h_min = Levelsep + (Levelheight[i-1]+Levelheight[i])/2; ! 199: int h_max = h_min+Levelsep; ! 200: ! 201: // reduce edge/node intersections by raising level separations ! 202: if(ranksepar < 2) ! 203: { ! 204: for(int *vp = Rank[i-1]; *vp != -1; ++vp) ! 205: for(edge_t *e = Outedges[*vp]; e; e = e->next) ! 206: h_min = vsepar(*vp,e->node,Rank[i-1],Rank[i],h_min); ! 207: if(ranksepar == 1) ! 208: maxsep = max(maxsep,min(h_max,h_min)); ! 209: } ! 210: ! 211: if(ranksepar != 1) ! 212: Levelpos[i] = Levelpos[i-1] + min(h_max,h_min); ! 213: } ! 214: ! 215: if(ranksepar == 1) ! 216: for(i = 1; i <= Maxlevel; ++i) ! 217: Levelpos[i] = Levelpos[i-1]+maxsep; ! 218: } ! 219: ! 220: // see if a node is part of a path ! 221: static int pathdegree(int n) ! 222: { ! 223: int deg = 0; ! 224: if(Inedges[n]) ! 225: { ! 226: deg += 1; ! 227: if(Inedges[n]->next) ! 228: deg += 3; ! 229: } ! 230: if(Outedges[n]) ! 231: { ! 232: deg += 1; ! 233: if(Outedges[n]->next) ! 234: deg += 3; ! 235: } ! 236: return deg; ! 237: } ! 238: ! 239: // multiplicative factor for different type of edges ! 240: static int edgefactor(int v, int w) ! 241: { ! 242: #define V_BIT 001 ! 243: #define S_BIT 002 ! 244: #define C_EE 000 /* 0000 */ ! 245: #define C_VE 004 /* 0100 */ ! 246: #define C_SE 010 /* 1000 */ ! 247: #define C_EV 001 /* 0001 */ ! 248: #define C_VV 005 /* 0101 */ ! 249: #define C_SV 011 /* 1001 */ ! 250: #define C_ES 002 /* 0010 */ ! 251: #define C_VS 006 /* 0110 */ ! 252: #define C_SS 012 /* 1010 */ ! 253: ! 254: int v_type = 0; ! 255: if(v >= N_real_nodes) ! 256: v_type |= V_BIT; ! 257: else if(pathdegree(v) <= 2) ! 258: v_type |= S_BIT; ! 259: ! 260: int w_type = 0; ! 261: if(w >= N_real_nodes) ! 262: w_type |= V_BIT; ! 263: else if(pathdegree(w) <= 2) ! 264: w_type |= S_BIT; ! 265: ! 266: switch((v_type<<2)|w_type) ! 267: { ! 268: default: ! 269: case C_EE: ! 270: return C_ee; ! 271: case C_VE: ! 272: return C_ev; ! 273: case C_EV: ! 274: return C_ev; ! 275: case C_SE: ! 276: return C_es; ! 277: case C_ES: ! 278: return C_es; ! 279: case C_VS: ! 280: return C_vs; ! 281: case C_SV: ! 282: return C_vs; ! 283: case C_SS: ! 284: return C_ss; ! 285: case C_VV: ! 286: return C_vv; ! 287: } ! 288: } ! 289: ! 290: // define width of a node ! 291: static inline int widthof(int node) ! 292: { ! 293: int width = max(Width[node],Nodesep); ! 294: if(N_self_edges > 0) ! 295: width += Selfwidth[node]; ! 296: return width; ! 297: } ! 298: ! 299: // solve LP to get the positions ! 300: static void bestposition() ! 301: { ! 302: // calculate # of rows and cols ! 303: int jumpcnt = N_nodes - Maxlevel - 1; ! 304: int rows = N_edges + jumpcnt; ! 305: int cols = N_nodes + 2*N_edges + jumpcnt + 1; ! 306: ! 307: // allocate simplex arrays ! 308: long *weight = new long[N_edges]; ! 309: long *objf = new long[cols]; ! 310: long *auxf = new long[cols]; ! 311: long **arrp = new long*[rows]; ! 312: for(int i = 0; i < rows; ++i) ! 313: arrp[i] = new long[cols]; ! 314: ! 315: // fill in first N_edges rows of the constraint array ! 316: int k = 0; ! 317: for(i = 0; i < N_nodes; i++) ! 318: { ! 319: for(edge_t *e = Outedges[i]; e; e = e->next) ! 320: { ! 321: arrp[k][N_nodes+k] = 1; ! 322: arrp[k][N_nodes+N_edges+k] = -1; ! 323: arrp[k][e->node] = -1; ! 324: arrp[k][i] = 1; ! 325: weight[k] = e->weight*edgefactor(i,e->node); ! 326: k++; ! 327: } ! 328: } ! 329: ! 330: // fill in last jumpcnt rows of constraint array ! 331: k = N_edges; ! 332: for(i = 0; i <= Maxlevel; i++) ! 333: { ! 334: for(int j = 0; j < N_level[i]-1; j++) ! 335: { ! 336: int v = Rank[i][j]; ! 337: int w = Rank[i][j+1]; ! 338: int vwidth = widthof(v); ! 339: int wwidth = widthof(w); ! 340: ! 341: arrp[k][cols-1] = (vwidth+wwidth)/2 + Nodesep; ! 342: arrp[k][v] = -1; ! 343: arrp[k][w] = 1; ! 344: arrp[k][N_nodes+N_edges+k] = -1; ! 345: ! 346: k++; ! 347: } ! 348: } ! 349: ! 350: // fill in last columns of objective function. ! 351: k = N_nodes+N_edges; ! 352: for(i = 0; i < N_edges; i++, k++) ! 353: objf[k] = 2*weight[i]; ! 354: ! 355: // fill in last columns of auxiliary function ! 356: for(i = 0; i < jumpcnt; i++) ! 357: auxf[N_nodes + 2*N_edges + i] = 1; ! 358: auxf[cols-1] = -jumpcnt; ! 359: ! 360: // fill in first N_nodes columns of objective and aux functions ! 361: for(i = 0; i < N_nodes; i++) ! 362: { ! 363: long sum = 0; ! 364: for(k = 0; k < N_edges; ++k) ! 365: sum += arrp[k][i]*weight[k]; ! 366: objf[i] = -sum; ! 367: ! 368: sum = 0; ! 369: for(int j = 0; j < jumpcnt; j++) ! 370: sum += arrp[N_edges + j][i]; ! 371: auxf[i] = -sum; ! 372: } ! 373: ! 374: dag_simplex(rows,cols,arrp,auxf,objf,N_nodes,Nodepos); ! 375: ! 376: // restore space used by simplex ! 377: delete weight; ! 378: delete objf; ! 379: delete auxf; ! 380: for(i = 0; i < rows; ++i) ! 381: delete arrp[i]; ! 382: delete arrp; ! 383: } ! 384: ! 385: ! 386: // try to straighten parts of a long edge ! 387: // the main for loop works from outside in to preserve any inherent symmetry ! 388: // in the part of the edge being worked on. ! 389: ! 390: static int straight(int n_nodes,int *nodes,int *minx,int *maxx,int *pos) ! 391: { ! 392: int n_done = 0; ! 393: if(n_nodes > 4) ! 394: { ! 395: int top = nodes[0], bot = nodes[n_nodes-1]; ! 396: int top_lx = Nodepos[top] - Width[top]/2; ! 397: int top_rx = Nodepos[top] + Width[top]/2; ! 398: int bot_lx = Nodepos[bot] - Width[bot]/2; ! 399: int bot_rx = Nodepos[bot] + Width[bot]/2; ! 400: int d_top = Nodepos[top] - Nodepos[nodes[1]]; ! 401: int d_bot = Nodepos[bot] - Nodepos[nodes[n_nodes-2]]; ! 402: if(d_top*d_bot > 0) ! 403: { ! 404: for(int t = 1; t < n_nodes-1; ++t) ! 405: if(d_top*(Nodepos[nodes[t]]-Nodepos[nodes[t+1]]) <= 0) ! 406: break; ! 407: for(int b = n_nodes-2; b > t; --b) ! 408: if(d_bot*(Nodepos[nodes[b]]-Nodepos[nodes[b-1]]) <= 0) ! 409: break; ! 410: if(Nodepos[nodes[t]] >= top_lx && Nodepos[nodes[t]] <= top_rx) ! 411: t = 0; ! 412: if(Nodepos[nodes[b]] >= bot_lx && Nodepos[nodes[b]] <= bot_rx) ! 413: b = n_nodes-1; ! 414: if(t > 0 || b < n_nodes-1) ! 415: { ! 416: if(t >= 2) ! 417: n_done = straight(t+1,nodes,minx,maxx,pos); ! 418: if(b <= n_nodes-3) ! 419: n_done += straight(n_nodes-b,nodes+b, ! 420: minx+b,maxx+b,pos); ! 421: if((b-t) >= 2) ! 422: n_done += straight(b-t+1,nodes+t, ! 423: minx+t,maxx+t,pos); ! 424: return n_done; ! 425: } ! 426: } ! 427: } ! 428: // try to straighten all sub-intervals ! 429: for(int t = 0; t < n_nodes-2;) ! 430: { ! 431: for(int b = n_nodes-1; b > t+1; --b) ! 432: { ! 433: int vt = nodes[t]; ! 434: int vb = nodes[b]; ! 435: int xt = Nodepos[vt]; ! 436: int xb = Nodepos[vb]; ! 437: int yt = Levelpos[Level[vt]]; ! 438: int yb = Levelpos[Level[vb]]; ! 439: ! 440: // interpolate top/bottom nodes and compute new positions ! 441: int linear = 1; ! 442: for(int i = t+1, lev = Level[nodes[i]]; i < b; ++i, ++lev) ! 443: { ! 444: // new position of point ! 445: int cury = Levelpos[lev]; ! 446: int curx = Nodepos[nodes[i]]; ! 447: int newx = (xb-xt)*(cury-yb); ! 448: newx = (int)(((double)newx)/(yb-yt) + xb + .5); ! 449: ! 450: // easy case ! 451: if(newx == curx) ! 452: { ! 453: pos[i] = curx; ! 454: continue; ! 455: } ! 456: ! 457: // node width ! 458: int w = widthof(nodes[i])/2; ! 459: ! 460: // check constraints ! 461: int violated = 0; ! 462: if(newx-w < minx[i] || newx+w > maxx[i]) ! 463: violated = 1; ! 464: ! 465: // make sure that yanking this straight ! 466: // won't cause node intersections ! 467: if(!violated) ! 468: { ! 469: int y = cury - Levelheight[lev]/2; ! 470: int x = (xb-xt)*(y-yb); ! 471: x = (int)(((double)x)/(yb-yt) + xb + .5); ! 472: if(x-w < minx[i] || x+w > maxx[i]) ! 473: violated = 1; ! 474: } ! 475: if(!violated) ! 476: { ! 477: int y = cury + Levelheight[lev]; ! 478: int x = (xb-xt)*(y-yb); ! 479: x = (int)(((double)x)/(yb-yt) + xb + .5); ! 480: if(x-w < minx[i] || x+w > maxx[i]) ! 481: violated = 1; ! 482: } ! 483: if(violated && (b-t) > 2) ! 484: break; ! 485: else if(violated) ! 486: { ! 487: linear = 0; ! 488: int midx = (minx[i]+maxx[i])/2; ! 489: if((curx < midx && midx < newx) || ! 490: (curx > midx && midx > newx)) ! 491: newx = midx; ! 492: if(newx-w < minx[i] || newx+w > maxx[i]) ! 493: break; ! 494: } ! 495: pos[i] = newx; ! 496: } ! 497: ! 498: // if the whole segment can be straightened ! 499: if(i == b) ! 500: { ! 501: for(i = t+1; i < b; ++i) ! 502: { ! 503: Nodepos[nodes[i]] = pos[i]; ! 504: Deleted[nodes[i]] = linear ? 1 : 0; ! 505: } ! 506: Deleted[nodes[t]] = Deleted[nodes[b]] = 0; ! 507: n_done += b-t; ! 508: ! 509: // back to main loop ! 510: break; ! 511: } ! 512: } ! 513: ! 514: // start with the rest of the interval ! 515: t = b > t+1 ? b-1 : b; ! 516: } ! 517: return n_done; ! 518: } ! 519: ! 520: ! 521: // run thru all the edges once and try to straighten them out if ! 522: // no constraints are violated ! 523: static void setbounds(int *nodes, int n_nodes, int *minx, int *maxx) ! 524: { ! 525: for(int k = 1; k < n_nodes-1; ++k) ! 526: { ! 527: int v = nodes[k]; ! 528: int i = Invert[v]; ! 529: int *rank = Rank[Level[v]]; ! 530: int a = rank[i+1]; ! 531: maxx[k] = a < 0 ? Maxint : (Nodepos[a]-widthof(a)/2) - 5*Nodesep/4; ! 532: a = i > 0 ? rank[i-1] : -1; ! 533: minx[k] = a < 0 ? -Maxint : (Nodepos[a]+widthof(a)/2) + 5*Nodesep/4; ! 534: } ! 535: } ! 536: ! 537: static void smoothedges() ! 538: { ! 539: int *nodes = new int[Maxlevel+1]; ! 540: int *pos = new int[Maxlevel+1]; ! 541: int *minx = new int[Maxlevel+1]; ! 542: int *maxx = new int[Maxlevel+1]; ! 543: ! 544: int counter = 0; ! 545: int improving = 1; ! 546: while(improving) ! 547: { ! 548: improving = 0; ! 549: int dir = counter%2 ? -1 : 1; ! 550: for(int i = 0; i < Maxlevel; ++i) ! 551: { ! 552: int *begp = Rank[i]; ! 553: int *endp = Rank[i]+N_level[i]-1; ! 554: int *vp = counter%2 ? endp : begp; ! 555: for(; vp >= begp && vp <= endp; vp += dir) ! 556: { ! 557: if(*vp >= N_real_nodes) ! 558: continue; ! 559: for(edge_t *e = Outedges[*vp]; e; e = e->next) ! 560: { ! 561: if(e->node < N_real_nodes) ! 562: continue; ! 563: ! 564: // get all the nodes ! 565: int n_nodes = 0; ! 566: nodes[n_nodes++] = *vp; ! 567: for(edge_t *f = e; f; f = f->chain) ! 568: nodes[n_nodes++] = f->node; ! 569: ! 570: // bounds for intermediate nodes ! 571: setbounds(nodes,n_nodes,minx,maxx); ! 572: int n = straight(n_nodes,nodes,minx,maxx,pos); ! 573: if(n > 2*n_nodes/3) ! 574: { ! 575: improving++; ! 576: e->node = -(e->node); ! 577: } ! 578: // need these to separate parallel edges ! 579: if(n > 0 && e->count > 1) ! 580: Deleted[nodes[1]] = ! 581: Deleted[nodes[n_nodes-2]] = 0; ! 582: } ! 583: } ! 584: } ! 585: } ! 586: ! 587: // reset signs of nodes ! 588: for(int v = 0; v < N_real_nodes; ++v) ! 589: for(edge_t *e = Outedges[v]; e; e = e->next) ! 590: if(e->node < 0) ! 591: e->node = -(e->node); ! 592: delete nodes; ! 593: delete pos; ! 594: delete minx; ! 595: delete maxx; ! 596: } ! 597: ! 598: ! 599: /* ! 600: Fast routines to assign positions. ! 601: The basic idea is to iteratively assign node positions based ! 602: on the median(s) of adjacent nodes. This heuristic is aided ! 603: with other heuristics that pack nodes closer based on local ! 604: improvements. ! 605: */ ! 606: ! 607: // compute total edge length for a set of nodes ! 608: static int rlength(int *nodepos, int *node) ! 609: { ! 610: int length = 0; ! 611: for(; *node != -1; ++node) ! 612: for(edge_t *e = Outedges[*node]; e; e = e->next) ! 613: length += iabs(nodepos[*node]-nodepos[e->node])*e->weight; ! 614: if(length < 0) ! 615: panic("Integer overflow"); ! 616: return length; ! 617: } ! 618: ! 619: // compute the length of all edges incident on a node givenits position ! 620: static int vlength(int v, int pos, int *nodepos) ! 621: { ! 622: int length = 0; ! 623: for(edge_t *e = Outedges[v]; e; e = e->next) ! 624: length += iabs(pos-nodepos[e->node])*e->weight; ! 625: for(e = Inedges[v]; e; e = e->next) ! 626: length += iabs(pos-nodepos[e->node])*e->weight; ! 627: return length; ! 628: } ! 629: ! 630: ! 631: // structures and functions for median computations ! 632: static struct MEDIAN ! 633: { ! 634: int position; ! 635: int weight; ! 636: int node; ! 637: }; ! 638: static MEDIAN *Median; ! 639: ! 640: static struct PAIR ! 641: { ! 642: int left; ! 643: int right; ! 644: }; ! 645: ! 646: static int *Priority; ! 647: static int prioritycmp(register int *one, register int *two) ! 648: { ! 649: return Priority[*two]-Priority[*one]; ! 650: } ! 651: ! 652: ! 653: // compute the weighted median of a bunch of nodes ! 654: static int mediancmp(register MEDIAN *one, register MEDIAN *two) ! 655: { ! 656: return one->position - two->position; ! 657: } ! 658: static void wmedian(int n, PAIR *p) ! 659: { ! 660: if(n <= 0) ! 661: { ! 662: p->left = p->right = -1; ! 663: return; ! 664: } ! 665: if(n == 1) ! 666: { ! 667: p->left = p->right = 0; ! 668: return; ! 669: } ! 670: ! 671: // median weight; ! 672: int w_total = 0; ! 673: for(int i = 0; i < n; ++i) ! 674: w_total += Median[i].weight; ! 675: int w_median = (w_total+1)/2; ! 676: ! 677: // sort and the median ! 678: qsort((char*)Median,n,sizeof(Median[0]),(qsortcmpfun)mediancmp); ! 679: int w_accum = 0; ! 680: for(i = 0; i < n; ++i) ! 681: { ! 682: w_accum += Median[i].weight; ! 683: if(w_accum >= w_median) ! 684: break; ! 685: } ! 686: if(i == n) ! 687: panic("Bad median"); ! 688: if(i < n-1 && (w_total%2) == 0 && w_accum == w_median) ! 689: { ! 690: p->left = i; ! 691: p->right = i+1; ! 692: } ! 693: else p->left = p->right = i; ! 694: } ! 695: ! 696: // assign position for nodes in a rank relative to an adjacent rank ! 697: static void assignpos(int *pos, int *node, int *rank, PAIR *median, int *priority) ! 698: { ! 699: for(; *node != -1; ++node) ! 700: { ! 701: // boundary in which the node must appear ! 702: int maxx = Maxint, minx = -Maxint; ! 703: int here = Invert[*node]; ! 704: for(register int k = here+1; rank[k] != -1; ++k) ! 705: if(priority[rank[k]] > priority[*node]) ! 706: break; ! 707: if(rank[k] != -1) ! 708: { ! 709: maxx = pos[rank[k]]; ! 710: for(int n = k-1; n > here; --n) ! 711: maxx -= widthof(rank[n]); ! 712: maxx -= (k-here)*Nodesep; ! 713: maxx -= (widthof(*node)+widthof(rank[k]))/2; ! 714: } ! 715: for(k = here-1; k >= 0; --k) ! 716: if(priority[rank[k]] > priority[*node]) ! 717: break; ! 718: if(k >= 0) ! 719: { ! 720: minx = pos[rank[k]]; ! 721: for(int n = k+1; n < here; ++n) ! 722: minx += widthof(rank[n]); ! 723: minx += (here-k)*Nodesep; ! 724: minx += (widthof(*node)+widthof(rank[k]))/2; ! 725: } ! 726: if(maxx <= minx) ! 727: { ! 728: pos[*node] = minx; ! 729: continue; ! 730: } ! 731: ! 732: // compute new position ! 733: int set = 0; ! 734: PAIR *p = median + *node; ! 735: if(p->left >= 0) ! 736: { ! 737: int newx = (pos[p->left]+pos[p->right]+1)/2; ! 738: if(newx >= minx && newx <= maxx) ! 739: { ! 740: pos[*node] = newx; ! 741: ++set; ! 742: } ! 743: } ! 744: if(!set) ! 745: { ! 746: int curx = pos[*node]; ! 747: if(curx < minx) ! 748: pos[*node] = minx; ! 749: else if(curx > maxx) ! 750: pos[*node] = maxx; ! 751: //else pos[*node] = curx; ! 752: } ! 753: } ! 754: } ! 755: ! 756: ! 757: // reassign positions using medians. ! 758: // Nodes are considered in decreasing priority ! 759: static void medianpos(int *pos, int **order, int *priority, PAIR *median, int isdown) ! 760: { ! 761: for(int l = 1; l <= Maxlevel; ++l) ! 762: { ! 763: int lev = isdown ? l : Maxlevel-l; ! 764: assignpos(pos,order[l],Rank[l],median,priority); ! 765: } ! 766: } ! 767: ! 768: ! 769: // same as medianpos, but for edges ! 770: static void minedge(int *nodepos) ! 771: { ! 772: for(int v = 0; v < N_real_nodes; ++v) ! 773: for(edge_t *e = Outedges[v]; e; e = e->next) ! 774: { ! 775: int w = e->node; ! 776: if(w >= N_real_nodes || nodepos[w] != nodepos[v]) ! 777: continue; ! 778: ! 779: // interval in which the edge can move ! 780: int v_min, v_max; ! 781: int i = Invert[v]; ! 782: int *rank = Rank[Level[v]]; ! 783: int a = i > 0 ? rank[i-1] : -1; ! 784: v_min = a<0 ? -Maxint : nodepos[a]+(widthof(v)+widthof(a))/2 + Nodesep; ! 785: a = rank[i+1]; ! 786: v_max = a<0 ? Maxint : nodepos[a]-(widthof(v)+widthof(a))/2 - Nodesep; ! 787: rank = Rank[Level[v]+1]; ! 788: ! 789: int minx, maxx; ! 790: i = Invert[w]; ! 791: a = i > 0 ? rank[i-1] : -1; ! 792: minx = a<0 ? -Maxint : nodepos[a]+(widthof(w)+widthof(a))/2 + Nodesep; ! 793: a = rank[i+1]; ! 794: maxx = a<0 ? Maxint : nodepos[a]-(widthof(w)+widthof(a))/2 - Nodesep; ! 795: minx = max(minx,v_min); ! 796: maxx = min(maxx,v_max); ! 797: if(maxx <= minx) ! 798: continue; ! 799: ! 800: // make list of adjacent nodes ! 801: MEDIAN *m = Median; ! 802: int count = 0; ! 803: for(int top = 0; top < 2; ++top) ! 804: { ! 805: int here = top ? v : w; ! 806: int there = top ? w : v; ! 807: for(int in = 0; in < 2; ++in) ! 808: { ! 809: edge_t *e = in ? Inedges[here] : Outedges[here]; ! 810: for(; e; e = e->next) ! 811: { ! 812: if(e->node == there) ! 813: continue; ! 814: m->position = nodepos[e->node]; ! 815: m->weight = e->weight; ! 816: ++m; ! 817: ++count; ! 818: } ! 819: } ! 820: } ! 821: if(count <= 0) ! 822: continue; ! 823: ! 824: // get the median(s) ! 825: PAIR p; ! 826: wmedian(count,&p); ! 827: int newx = (Median[p.left].position+Median[p.right].position+1)/2; ! 828: if(newx >= minx && newx <= maxx) ! 829: { ! 830: nodepos[v] = newx; ! 831: nodepos[w] = newx; ! 832: } ! 833: } ! 834: } ! 835: ! 836: ! 837: // local improvement for each node based on its entire adjacent nodes ! 838: // This is the same as doing a descent from the current assignment to ! 839: // improve the objective function. This is why the algorithm will ! 840: // terminate. ! 841: static void minnode(int *nodepos, int *marked, int *queue) ! 842: { ! 843: // local inline functions ! 844: #define ENQUEUE(x) queue[tail] = x; if(++tail >= N_nodes+1) tail = 0; ! 845: #define DEQUEUE(x) x = queue[head]; if(++head >= N_nodes+1) head = 0; ! 846: #define NOTNULL() head != tail ! 847: ! 848: // marked[] and queue[] have the set of nodes to be considered ! 849: for(int n = 0; n < N_nodes; ++n) ! 850: { ! 851: marked[n] = 1; ! 852: queue[n] = n; ! 853: } ! 854: ! 855: int head = 0, tail = N_nodes; ! 856: while(NOTNULL()) ! 857: { ! 858: int here; ! 859: ! 860: DEQUEUE(here); ! 861: marked[here] = 0; ! 862: ! 863: // boundary in which the node must appear ! 864: int here_w = widthof(here); ! 865: n = Invert[here]; ! 866: int *rank = Rank[Level[here]]; ! 867: int l = n <= 0 ? -1 : rank[n-1]; ! 868: int r = rank[n+1]; ! 869: int minx = l < 0 ? -Maxint : nodepos[l]+Nodesep+(here_w+widthof(l))/2; ! 870: int maxx = r < 0 ? Maxint : nodepos[r]-Nodesep-(here_w+widthof(r))/2; ! 871: if(maxx <= minx) ! 872: continue; ! 873: ! 874: int cnt = 0; ! 875: MEDIAN *median = Median; ! 876: for(int down = 0; down < 2; ++down) ! 877: { ! 878: edge_t *e = down ? Outedges[here] : Inedges[here]; ! 879: for(; e; e = e->next) ! 880: { ! 881: median->position = nodepos[e->node]; ! 882: median->weight = e->weight; ! 883: median->node = -1; ! 884: cnt++; ! 885: median++; ! 886: } ! 887: } ! 888: if(cnt == 0) ! 889: continue; ! 890: ! 891: PAIR p; ! 892: wmedian(cnt,&p); ! 893: int newx = (Median[p.left].position+Median[p.right].position+1)/2; ! 894: int correction = 0; ! 895: if(newx < minx || newx > maxx) ! 896: { ! 897: correction = 1; ! 898: newx = newx < minx ? minx : maxx; ! 899: } ! 900: if(newx == nodepos[here]) ! 901: continue; ! 902: ! 903: int newlength = vlength(here,newx,nodepos); ! 904: int oldlength = vlength(here,nodepos[here],nodepos); ! 905: if(newlength > oldlength || (newlength == oldlength && correction)) ! 906: continue; ! 907: ! 908: // update position and mark neighbors for consideration ! 909: nodepos[here] = newx; ! 910: if(newlength < oldlength) ! 911: { ! 912: for(down = 0; down < 2; ++down) ! 913: { ! 914: int adj = down ? l : r; ! 915: if(adj >= 0 && !marked[adj]) ! 916: { ! 917: marked[adj] = 1; ! 918: ENQUEUE(adj); ! 919: } ! 920: edge_t *e = down ? Outedges[here] : Inedges[here]; ! 921: for(; e; e = e->next) ! 922: { ! 923: adj = e->node; ! 924: if(marked[adj]) ! 925: continue; ! 926: marked[adj] = 1; ! 927: ENQUEUE(adj); ! 928: } ! 929: } ! 930: } ! 931: } ! 932: #undef ENQUEUE ! 933: #undef DEQUEUE ! 934: #undef NOTNULL ! 935: } ! 936: ! 937: // pack cuts that are not tight ! 938: static int *_nodepos; ! 939: static int rightcmp(int *p1, int *p2) ! 940: { ! 941: int right1 = _nodepos[*p1] + widthof(*p1)/2; ! 942: int right2 = _nodepos[*p2] + widthof(*p2)/2; ! 943: return right1-right2; ! 944: } ! 945: static int leftcmp(int *p1, int *p2) ! 946: { ! 947: int left1 = _nodepos[*p1] - widthof(*p1)/2; ! 948: int left2 = _nodepos[*p2] - widthof(*p2)/2; ! 949: return left1-left2; ! 950: } ! 951: static void verticalcut(int *nodepos, int *nodes, int maxwidth) ! 952: { ! 953: // sort vertices by their positions ! 954: _nodepos = nodepos; ! 955: qsort((char*)nodes,N_nodes,sizeof(nodes[0]),(qsortcmpfun)rightcmp); ! 956: ! 957: // go thru each possible cut ! 958: for(int i = 0; i+1 < N_nodes; ++i) ! 959: { ! 960: int v = nodes[i]; ! 961: int cut = nodepos[v] + widthof(v)/2 + Nodesep; ! 962: ! 963: int leftside = Maxint; ! 964: for(int k = i+1; k < N_nodes; ++k) ! 965: { ! 966: int w = nodes[k]; ! 967: ! 968: // don't need to check further ! 969: if((nodepos[w]-2*(maxwidth+Nodesep)) > leftside) ! 970: break; ! 971: ! 972: // define leftside ! 973: int wleft = nodepos[w] - widthof(w)/2; ! 974: if(wleft < leftside) ! 975: leftside = wleft; ! 976: if(leftside <= cut) ! 977: break; ! 978: } ! 979: // can improve ! 980: int shift = leftside-cut; ! 981: if(shift > 0) ! 982: for(k = i+1; k < N_nodes; ++k) ! 983: nodepos[nodes[k]] -= shift; ! 984: } ! 985: } ! 986: ! 987: static void mincut(int *nodepos, int *marked, int *queue, int *nodes, int dir) ! 988: { ! 989: #define ENQUEUE(x) queue[tail] = x; if(++tail >= N_nodes) tail = 0; ! 990: #define DEQUEUE(x) x = queue[head]; if(++head >= N_nodes) head = 0; ! 991: #define NOTNULL() head != tail ! 992: ! 993: _nodepos = nodepos; ! 994: qsort((char*)nodes,N_nodes,sizeof(nodes[0]),(dir < 0 ? (qsortcmpfun)leftcmp : (qsortcmpfun)rightcmp)); ! 995: int cut, lastcut = Maxint; ! 996: int n = dir > 0 ? 0 : N_nodes-1; ! 997: for(; n >= 0 && n < N_nodes; n += dir, lastcut = cut) ! 998: { ! 999: if(nodes[n] >= N_real_nodes) ! 1000: continue; ! 1001: ! 1002: // where the graph is being cut ! 1003: cut = nodepos[nodes[n]]+dir*(widthof(nodes[n])/2+Nodesep); ! 1004: if((dir > 0 && cut <= lastcut) || (dir < 0 && cut >= lastcut)) ! 1005: continue; ! 1006: ! 1007: // try to shift connected components in the right of the cut ! 1008: for(int i = 0; i < N_nodes; ++i) ! 1009: marked[i] = 0; ! 1010: int component = 1; ! 1011: for(int m = n+dir; m >= 0 && m < N_nodes; m += dir) ! 1012: { ! 1013: int v = nodes[m]; ! 1014: if(marked[v]) ! 1015: continue; ! 1016: int side = nodepos[v] - dir*widthof(v)/2; ! 1017: if((dir > 0 && side <= cut) || (dir < 0 && side >= cut)) ! 1018: continue; ! 1019: ! 1020: // bf-search for all nodes in this component ! 1021: int head = 0, tail = 0; ! 1022: ENQUEUE(v); ! 1023: marked[v] = component; ! 1024: while(NOTNULL()) ! 1025: { ! 1026: int here; ! 1027: DEQUEUE(here); ! 1028: for(int in = 0; in < 2; ++in) ! 1029: { ! 1030: edge_t *e = in ? Inedges[here]:Outedges[here]; ! 1031: for(; e; e = e->next) ! 1032: { ! 1033: int w = e->node; ! 1034: if(marked[w]) ! 1035: continue; ! 1036: int side = nodepos[w]-dir*widthof(w)/2; ! 1037: if((dir > 0 && side <= cut) || ! 1038: (dir < 0 && side >= cut)) ! 1039: continue; ! 1040: ENQUEUE(w); ! 1041: marked[w] = component; ! 1042: } ! 1043: } ! 1044: } ! 1045: ! 1046: int shift = Maxint; ! 1047: for(i = 0; i < tail; ++i) ! 1048: { ! 1049: int v = queue[i]; ! 1050: int a = Invert[v]; ! 1051: if(dir > 0) ! 1052: a = a <= 0 ? -1 : Rank[Level[v]][a-1]; ! 1053: else a = Rank[Level[v]][a+1]; ! 1054: if(a < 0 || marked[v] == marked[a]) ! 1055: continue; ! 1056: int side = nodepos[a] + dir*(widthof(a)/2+Nodesep); ! 1057: if((dir > 0 && side < cut) || (dir < 0 && side > cut)) ! 1058: side = cut; ! 1059: int slack = nodepos[v] - dir*(widthof(v)/2); ! 1060: slack = dir > 0 ? slack-side : side-slack; ! 1061: if(slack < shift) ! 1062: shift = slack; ! 1063: if(shift <= 0) ! 1064: break; ! 1065: } ! 1066: if(shift < Maxint && shift > 0) ! 1067: for(i = 0; i < tail; ++i) ! 1068: nodepos[queue[i]] -= dir*shift; ! 1069: component++; ! 1070: } ! 1071: } ! 1072: } ! 1073: ! 1074: // straighten paths ! 1075: static void getminmax(int *nodepos, int v, int& minx, int& maxx) ! 1076: { ! 1077: int *rank = Rank[Level[v]]; ! 1078: int i = Invert[v]; ! 1079: int l = i > 0 ? rank[i-1] : -1; ! 1080: int r = rank[i+1]; ! 1081: minx = l < 0 ? -Maxint : nodepos[l] + (widthof(l)+widthof(v))/2 + Nodesep; ! 1082: maxx = r < 0 ? Maxint : nodepos[r] - (widthof(r)+widthof(v))/2 - Nodesep; ! 1083: } ! 1084: ! 1085: static void minpath(int *nodepos, int *nodes) ! 1086: { ! 1087: for(int lev = 0; lev < Maxlevel; ++lev) ! 1088: for(int *rank = Rank[lev]; *rank >= 0; ++rank) ! 1089: for(edge_t *e = Outedges[*rank]; e; e = e->next) ! 1090: { ! 1091: // find a straightenable path from v ! 1092: int n_nodes = 0; ! 1093: int minx = -Maxint, maxx = Maxint; ! 1094: int v = *rank, w = e->node; ! 1095: if(pathdegree(v) == 1 && !Inedges[v]) ! 1096: { ! 1097: nodes[n_nodes++] = v; ! 1098: getminmax(nodepos,v,minx,maxx); ! 1099: } ! 1100: edge_t *f = e; ! 1101: while(1) ! 1102: { ! 1103: w = f->node; ! 1104: if(pathdegree(w) > 2) ! 1105: break; ! 1106: ! 1107: int lx, rx; ! 1108: getminmax(nodepos,w,lx,rx); ! 1109: if(lx > maxx || rx < minx) ! 1110: break; ! 1111: ! 1112: minx = max(minx,lx); ! 1113: maxx = min(maxx,rx); ! 1114: nodes[n_nodes++] = w; ! 1115: if(!Outedges[w]) ! 1116: break; ! 1117: else f = Outedges[w]; ! 1118: } ! 1119: if(n_nodes <= 0 || minx > maxx) ! 1120: continue; ! 1121: ! 1122: // new position ! 1123: int vx = nodepos[v]; ! 1124: int wx = nodepos[w]; ! 1125: vx = vx < minx ? minx : (vx > maxx ? maxx : vx); ! 1126: wx = wx < minx ? minx : (wx > maxx ? maxx : wx); ! 1127: int newx; ! 1128: if(v == nodes[0] && w != nodes[n_nodes-1]) ! 1129: newx = wx; ! 1130: else if(w == nodes[n_nodes-1] && v != nodes[0]) ! 1131: newx = vx; ! 1132: else newx = e->weight > f->weight ? vx : ! 1133: (f->weight > e->weight ? wx : (vx+wx+1)/2); ! 1134: for(int i = 0; i < n_nodes; ++i) ! 1135: nodepos[nodes[i]] = newx; ! 1136: } ! 1137: } ! 1138: ! 1139: ! 1140: // define median pointers to help medianpos(). ! 1141: // The observation here is that since the relative order of ! 1142: // adjacent nodes of a node in the next or last level is always ! 1143: // maintained, the median node is known regardless of its position. ! 1144: // So we compute it once and avoid doing qsorts during position ! 1145: // reassignment. ! 1146: ! 1147: static void define_median(PAIR *median, edge_t **edges) ! 1148: { ! 1149: for(int i = 0; i < N_nodes; ++i) ! 1150: { ! 1151: int cnt = 0; ! 1152: MEDIAN *mp = Median; ! 1153: for(edge_t *e = edges[i]; e; e = e->next) ! 1154: { ! 1155: mp->weight = e->weight; ! 1156: mp->position = Invert[e->node]; ! 1157: mp->node = e->node; ! 1158: ++mp; ! 1159: ++cnt; ! 1160: } ! 1161: if(cnt == 0) ! 1162: median[i].left = median[i].right = -1; ! 1163: else ! 1164: { ! 1165: PAIR p; ! 1166: wmedian(cnt,&p); ! 1167: median[i].left = Median[p.left].node; ! 1168: median[i].right = Median[p.right].node; ! 1169: } ! 1170: } ! 1171: } ! 1172: ! 1173: // compute starting positions ! 1174: static void startpos(int *pos, int **u_order, PAIR *u_median, int *u_prior, ! 1175: int **d_order, PAIR *d_median, int *d_prior) ! 1176: { ! 1177: int maxrank = -1, maxwidth = 0; ! 1178: for(int i = 0; i <= Maxlevel; ++i) ! 1179: { ! 1180: int wlast = 0; ! 1181: int xlast = -Nodesep; ! 1182: for(int *rank = Rank[i]; *rank >= 0; ++rank) ! 1183: { ! 1184: int wnow = widthof(*rank); ! 1185: xlast += Nodesep+(wlast+wnow)/2; ! 1186: pos[*rank] = xlast; ! 1187: wlast = wnow; ! 1188: } ! 1189: if(xlast+wlast/2 > maxwidth) ! 1190: { ! 1191: maxrank = i; ! 1192: maxwidth = xlast+wlast/2; ! 1193: } ! 1194: } ! 1195: for(i = maxrank-1; i >= 0; --i) ! 1196: assignpos(pos,u_order[i],Rank[i],u_median,u_prior); ! 1197: for(i = maxrank+1; i <= Maxlevel; ++i) ! 1198: assignpos(pos,d_order[i],Rank[i],d_median,d_prior); ! 1199: } ! 1200: ! 1201: // define orders ! 1202: static void define_order(int *u_prior, int **u_order, int *d_prior, int **d_order) ! 1203: { ! 1204: for(int i = 0; i <= Maxlevel; ++i) ! 1205: { ! 1206: int n_rank = N_level[i]; ! 1207: int *rank = Rank[i]; ! 1208: int *up = u_order[i]; ! 1209: int *down = d_order[i]; ! 1210: ! 1211: for(int k = n_rank; k >= 0; --k) ! 1212: up[k] = down[k] = rank[k]; ! 1213: for(k = 0; rank[k] != -1;) ! 1214: { ! 1215: for(int ek = k+1; rank[ek] != -1; ++ek) ! 1216: if(Component[rank[ek]] != Component[rank[ek-1]]) ! 1217: break; ! 1218: Priority = u_prior; ! 1219: qsort((char*)(up+k),ek-k,sizeof(up[0]),(qsortcmpfun)prioritycmp); ! 1220: Priority = d_prior; ! 1221: qsort((char*)(down+k),ek-k,sizeof(down[0]),(qsortcmpfun)prioritycmp); ! 1222: ! 1223: k = ek; ! 1224: } ! 1225: for(k = 0; rank[k] != -1; ++k, --n_rank) ! 1226: { ! 1227: u_prior[up[k]] = n_rank; ! 1228: d_prior[down[k]] = n_rank; ! 1229: } ! 1230: } ! 1231: } ! 1232: ! 1233: static void goodposition() ! 1234: { ! 1235: const int Maxiter = 8, Minquit = 4; ! 1236: ! 1237: // set priorities of nodes ! 1238: int *d_prior = new int[N_nodes]; ! 1239: int *u_prior = new int[N_nodes]; ! 1240: for(int i = 0; i < N_nodes; ++i) ! 1241: { ! 1242: d_prior[i] = u_prior[i] = 0; ! 1243: for(edge_t *e = Inedges[i]; e; e = e->next) ! 1244: d_prior[i] += (e->weight *= edgefactor(e->node,i)); ! 1245: for(e = Outedges[i]; e; e = e->next) ! 1246: u_prior[i] += (e->weight *= edgefactor(i,e->node)); ! 1247: } ! 1248: ! 1249: // construct the order in which positions are assigned to nodes ! 1250: int **u_order = new int*[Maxlevel+1]; ! 1251: int **d_order = new int*[Maxlevel+1]; ! 1252: for(i = 0; i <= Maxlevel; ++i) ! 1253: { ! 1254: u_order[i] = new int[N_level[i]+1]; ! 1255: d_order[i] = new int[N_level[i]+1]; ! 1256: } ! 1257: define_order(u_prior,u_order,d_prior,d_order); ! 1258: ! 1259: // compute the median pointers ! 1260: Median = new MEDIAN[N_nodes]; ! 1261: int *nodepos = new int[N_nodes]; ! 1262: PAIR *u_median = new PAIR[N_nodes]; ! 1263: PAIR *d_median = new PAIR[N_nodes]; ! 1264: define_median(d_median,Inedges); ! 1265: define_median(u_median,Outedges); ! 1266: ! 1267: // temp space for graph search ! 1268: int *marked = new int[N_nodes]; ! 1269: int *queue = new int[N_nodes+1]; ! 1270: int *nodes = new int[N_nodes]; ! 1271: int maxwidth = 0; ! 1272: for(i = 0; i < N_nodes; ++i) ! 1273: { ! 1274: nodes[i] = i; ! 1275: maxwidth = max(maxwidth,widthof(i)); ! 1276: } ! 1277: ! 1278: long bestlength = -1; ! 1279: int improved = 0; ! 1280: for(int upfirst = 1; upfirst >= 0; --upfirst) ! 1281: { ! 1282: // compute starting positions ! 1283: startpos(nodepos,u_order,u_median,u_prior,d_order,d_median,d_prior); ! 1284: int counter = 1; ! 1285: for(int iter = 0; iter < Maxiter; ++iter) ! 1286: { ! 1287: if(upfirst) ! 1288: { ! 1289: if(iter%2 == 0) ! 1290: medianpos(nodepos,u_order,u_prior,u_median,0); ! 1291: else medianpos(nodepos,d_order,d_prior,d_median,1); ! 1292: } ! 1293: else ! 1294: { ! 1295: if(iter%2 == 0) ! 1296: medianpos(nodepos,d_order,d_prior,d_median,1); ! 1297: else medianpos(nodepos,u_order,u_prior,u_median,0); ! 1298: } ! 1299: ! 1300: // local optimization ! 1301: minedge(nodepos); ! 1302: minnode(nodepos,marked,queue); ! 1303: minpath(nodepos,queue); ! 1304: verticalcut(nodepos,nodes,maxwidth); ! 1305: ! 1306: long curlength = 0; ! 1307: for(i = 0; i < Maxlevel; ++i) ! 1308: curlength += rlength(nodepos,Rank[i]); ! 1309: if(bestlength < 0 || curlength < bestlength) ! 1310: { ! 1311: bestlength = curlength; ! 1312: for(i = 0; i < N_nodes; ++i) ! 1313: Nodepos[i] = nodepos[i]; ! 1314: improved++; ! 1315: counter = 1; ! 1316: } ! 1317: else if(counter++ > Minquit) ! 1318: break; ! 1319: } ! 1320: } ! 1321: ! 1322: mincut(Nodepos,marked,queue,nodes,1); ! 1323: mincut(Nodepos,marked,queue,nodes,-1); ! 1324: minedge(Nodepos); ! 1325: minnode(Nodepos,marked,queue); ! 1326: minpath(Nodepos,queue); ! 1327: ! 1328: // reclaim space ! 1329: for(i = 0; i <= Maxlevel; ++i) ! 1330: { ! 1331: delete u_order[i]; ! 1332: delete d_order[i]; ! 1333: } ! 1334: delete u_order; ! 1335: delete d_order; ! 1336: delete u_prior; ! 1337: delete d_prior; ! 1338: delete u_median; ! 1339: delete d_median; ! 1340: delete marked; ! 1341: delete queue; ! 1342: delete nodes; ! 1343: delete nodepos; ! 1344: delete Median; ! 1345: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.