Annotation of researchv10no/cmd/dag/dag_pos.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.