Annotation of researchv10no/cmd/dag/dag_ranks.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:        Create an ordering of nodes on each level.
                      9:        The ordering attempts to minimize edge crossing
                     10: */
                     11: static float   Convergence = .005;     // convergence rate
                     12: static int     Maxiter = 24;           // max number of iterations
                     13: static int     Minquit = 10;           // quit after this many iterations
                     14:                                        // if not improved
                     15: static int     **List;         // temp space for rank construction
                     16: static int     *Count,         // to aid rcross()      
                     17:                *Cross,         // current numbers of crossings between levels
                     18:                *Levelmarked;   // used in transpose()
                     19: static edge_t  **Flatedges;    // transitive closure of flat edges
                     20: static int     *Flatindeg;     // in-degree of nodes using Flatedges
                     21: 
                     22: static long    *Median;
                     23: static int     *Medadj;
                     24: 
                     25: static void    decompose(),
                     26:                flatclosure(),
                     27:                removestem(),
                     28:                installstem(int**,int);
                     29: static int     cross_stat(int**), rcross(int*,int*),
                     30:                buildrank(int**,int**,int);
                     31: extern void    inversion(int**);
                     32: 
                     33: void dag_ranks()
                     34: {
                     35:        struct tms      begtm, endtm;
                     36:        int             startcross = 0;
                     37: 
                     38:        if(Verbose)
                     39:        {
                     40: #ifndef TIMING
                     41:                fprintf(stderr,"Minimize edge crossing\n");
                     42: #endif
                     43:                times(&begtm);
                     44:        }
                     45: #ifdef TIMING
                     46:        Maxiter = 20;
                     47:        Minquit = 20;
                     48:        Convergence = .0001;
                     49: #else
                     50:        // reset parameters for speed
                     51:        if(N_real_nodes > 500)
                     52:        {
                     53:                float density = ((float) N_edges)/N_nodes;
                     54:                if(density >= 2.)
                     55:                {
                     56:                        Maxiter = N_real_nodes <= 1000 ? 8 : 4;
                     57:                        Minquit = N_real_nodes <= 1000 ? 4 : 2;
                     58:                        Convergence = N_real_nodes <= 1000 ? .01 : .1;
                     59:                }
                     60:        }
                     61: #endif
                     62: 
                     63:        // number of nodes in each level
                     64:        N_level = new int[Maxlevel+1];
                     65:        for(int i = 0; i < N_nodes; i++)
                     66:                N_level[Level[i]] += 1;
                     67: 
                     68:        // create space for node lists
                     69:        List = new int*[Maxlevel+1];
                     70:        Rank = new int*[Maxlevel+1];
                     71:        int **tryout = new int*[Maxlevel+1];
                     72:        int **target = new int*[Maxlevel+1];
                     73:        for(i = 0; i <= Maxlevel; ++i)
                     74:        {
                     75:                List[i] = new int[N_level[i]+1];
                     76:                tryout[i] = new int[N_level[i]+1];
                     77:                Rank[i] = new int[N_level[i]+1];
                     78:                Rank[i][0] = -1;
                     79:        }
                     80: 
                     81:        // space for intermediate calculations
                     82:        Invert = new int[N_nodes];
                     83:        Count = new int[N_nodes];
                     84:        Cross = new int[Maxlevel];
                     85:        Levelmarked = new int[Maxlevel+1];
                     86:        Median = new long[N_nodes];
                     87:        Medadj = new int[N_nodes+N_repeat_edges];
                     88: 
                     89:        // compute the transitive closure of the set of flat edges
                     90:        if(N_flat_edges > 0)
                     91:        {
                     92:                Flatedges = new edge_t*[N_real_nodes];
                     93:                Flatindeg = new int[N_real_nodes];
                     94:                flatclosure();
                     95:        }
                     96: 
                     97:        // detect connected components
                     98:        Component = new int[N_nodes];
                     99:        decompose();
                    100: 
                    101:        // build up the ordering component by component
                    102:        for(int component = 1; component <= N_component; ++component)
                    103:        {
                    104:                for(i = 0; i <= Maxlevel; ++i)
                    105:                {
                    106:                        for(int k = 0; ; ++k)
                    107:                                if(Rank[i][k] == -1)
                    108:                                        break;
                    109:                        target[i] = Rank[i]+k;
                    110:                }
                    111:                startcross += buildrank(target,tryout,component);
                    112:        }
                    113:        inversion(Rank);
                    114: 
                    115:        if(Verbose)
                    116:        {
                    117:                times(&endtm);
                    118:                int total = (endtm.tms_utime - begtm.tms_utime)+
                    119:                            (endtm.tms_stime - begtm.tms_stime);
                    120:                int percent = (total - (total/TIC)*TIC)*100/TIC;
                    121:                int bestcross = cross_stat(Rank);
                    122: #ifdef TIMING
                    123:                fprintf(stderr,"%d\t%d\t%d.%02d\t",
                    124:                        startcross,bestcross,total/TIC,percent);
                    125: #else
                    126:                fprintf(stderr,"Starting crossing number = %d\n",startcross);
                    127:                fprintf(stderr,"Crossings between ranks:\n");
                    128:                for(i = 0; i < Maxlevel; ++i)
                    129:                        fprintf(stderr,"(%2d,%2d):\tx=%d\n",i,i+1,Cross[i]);
                    130:                fprintf(stderr,"Ending crossing number = %d\n",bestcross);
                    131:                fprintf(stderr,"Time in minimizing crossing: %d.%02ds\n",
                    132:                                total/TIC, percent);
                    133: #endif
                    134:        }
                    135: 
                    136:        // release temp space
                    137:        delete Median;
                    138:        delete Medadj;
                    139:        delete Levelmarked;
                    140:        delete Cross;
                    141:        delete Count;
                    142:        for(i = 0; i <= Maxlevel; ++i)
                    143:        {
                    144:                delete List[i];
                    145:                delete tryout[i];
                    146:        }
                    147:        delete List;
                    148:        delete tryout;
                    149:        delete target;
                    150:        if(N_flat_edges > 0)
                    151:                deledges(N_real_nodes,Flatedges);
                    152: }
                    153: 
                    154: // compute the transitive closure of flat edges
                    155: // and remove resulting bidirectional edges.
                    156: // The final graph defines a partial order on the nodes.
                    157: static void flatedges(int root, int here, int *marked)
                    158: {
                    159:        marked[here] = 1;
                    160: 
                    161:        for(edge_t *e = Noedges[here]; e; e = e->next)
                    162:        if(e->weight > 0 && !marked[e->node])
                    163:        {
                    164:                // check for bi-directional edges
                    165:                edge_t *lastf = NULL, *f = Flatedges[e->node];
                    166:                for(; f != NULL; lastf = f, f = f->next)
                    167:                        if(f->node == root)
                    168:                                break;
                    169: 
                    170:                // remove bidirectional edges
                    171:                if(f != NULL)
                    172:                {
                    173:                        if(lastf)
                    174:                                lastf->next = f->next;
                    175:                        else    Flatedges[e->node] = f->next;
                    176:                        delete f;
                    177:                }
                    178:                // add a new edge
                    179:                else    Flatedges[root] =
                    180:                                new edge_t(e->node,0,0,0,Flatedges[root]);
                    181: 
                    182:                flatedges(root,e->node,marked);
                    183:        }
                    184: }
                    185: 
                    186: static void flatclosure()
                    187: {
                    188:        int *marked = Count;
                    189:        for(int v = 0; v < N_real_nodes; ++v)
                    190:        {
                    191:                for(int i = 0; i < N_real_nodes; ++i)
                    192:                        marked[i] = 0;
                    193:                flatedges(v,v,marked);
                    194:        }
                    195: 
                    196:        for(v = 0; v < N_real_nodes; ++v)
                    197:                for(edge_t *e = Flatedges[v]; e; e = e->next)
                    198:                        Flatindeg[e->node]++;
                    199: }
                    200: 
                    201: // assign component numbers to nodes so that nodes in the same
                    202: // connected component get the same number.
                    203: static void decompose()
                    204: {
                    205:        // make a reverse flat edge list
                    206:        edge_t **noedges = NULL;
                    207:        if(N_flat_edges > 0)
                    208:        {
                    209:                noedges = new edge_t*[N_real_nodes];
                    210:                for(int v = 0; v < N_real_nodes; ++v)
                    211:                for(edge_t *e = Noedges[v]; e; e = e->next)
                    212:                {
                    213:                        int w = e->node;
                    214:                        if(w != v)
                    215:                                noedges[w] = new edge_t(v,0,0,0,noedges[w]);
                    216:                }
                    217:        }
                    218: 
                    219:        // all adjacent edge lists
                    220:        edge_t **adjlist[5];
                    221:        adjlist[0] = Outedges;
                    222:        adjlist[1] = Inedges;
                    223:        adjlist[2] = N_flat_edges > 0 ? Noedges : NULL;
                    224:        adjlist[3] = N_flat_edges > 0 ? noedges : NULL;
                    225:        adjlist[4] = NULL;
                    226: 
                    227:        // space for the breadth-first search
                    228:        int *queue = new int[N_nodes];
                    229: 
                    230:        N_component = 0;
                    231:        for(int n = 0; n < N_nodes; ++n)
                    232:        {
                    233:                if(Component[n] > 0)
                    234:                        continue;
                    235: 
                    236:                // initialize for component search
                    237:                N_component += 1;
                    238:                Component[n] = N_component;
                    239: 
                    240:                // breadth-first search
                    241:                int first = 0, last = 1;
                    242:                queue[0] = n;
                    243:                while(first < last)
                    244:                {
                    245:                        int v = queue[first++];
                    246:                        for(int i = 0; adjlist[i] != NULL; ++i)
                    247:                        {
                    248:                                if(v >= N_real_nodes && i >= 2)
                    249:                                        continue;
                    250:                                for(edge_t *e = adjlist[i][v]; e; e = e->next)
                    251:                                {
                    252:                                        int w = e->node;
                    253:                                        if(Component[w] != 0)
                    254:                                                continue;
                    255:                                        Component[w] = N_component;
                    256:                                        queue[last++] = w;
                    257:                                }
                    258:                        }
                    259:                }
                    260:        }
                    261: 
                    262:        delete queue;
                    263:        if(N_flat_edges > 0)
                    264:                deledges(N_real_nodes,noedges);
                    265: }
                    266: 
                    267: // copy a ranking to another
                    268: static void copyrank(int **from, int **to)
                    269: {
                    270:        for(int i = 0; i <= Maxlevel; ++i)
                    271:        {
                    272:                register int *frp = from[i], *top = to[i];
                    273:                while(*frp != -1)
                    274:                        *top++ = *frp++;
                    275:                *top = -1;
                    276:        }
                    277: }
                    278: 
                    279: // see if one vertex must be left of another
                    280: static int left2right(int v, int w)
                    281: {
                    282:        if(v >= N_real_nodes || w >= N_real_nodes)
                    283:                return 0;
                    284: 
                    285:        for(edge_t *e = Flatedges[v]; e; e = e->next)
                    286:                if(e->node == w)
                    287:                        return 1;
                    288:        return 0;
                    289: }
                    290: 
                    291: // construct nodes reachable from 'here' in post-order.
                    292: // This is the same as doing a topological sort in reverse order.
                    293: static void postorder(int here,int *marked,int *list, int &n_search)
                    294: {
                    295:        marked[here] = 1;
                    296:        for(edge_t *e = Flatedges[here]; e; e = e->next)
                    297:                if(!marked[e->node])
                    298:                        postorder(e->node,marked,list,n_search);
                    299:        list[n_search++] = here;
                    300: }
                    301: 
                    302: static void reorder(int *list, int *marked, int *temp)
                    303: {
                    304:        for(int i = 0; list[i] >= 0; ++i)
                    305:                marked[list[i]] = 0;
                    306: 
                    307:        int n_temp = 0;
                    308:        for(i = 0; list[i] >= 0; ++i)
                    309:        {
                    310:                // dummy nodes
                    311:                if(list[i] >= N_real_nodes)
                    312:                        temp[n_temp++] = list[i];
                    313:                // real nodes
                    314:                else if(!marked[list[i]] && Flatindeg[list[i]] == 0)
                    315:                {
                    316:                        int n_search = 0;
                    317:                        postorder(list[i],marked,temp+n_temp,n_search);
                    318:                        int *left = temp+n_temp, *right = left+n_search-1;
                    319:                        for(; left < right; ++left, --right)
                    320:                        {
                    321:                                int t = *left;
                    322:                                *left = *right;
                    323:                                *right = t;
                    324:                        }
                    325:                        n_temp += n_search;
                    326:                }
                    327:        }
                    328: 
                    329:        // recopy the list
                    330:        for(i = 0; list[i] >= 0; ++i)
                    331:                list[i] = temp[i];
                    332: }
                    333: 
                    334: // Compute an initial ordering of nodes belonging to some connected component.
                    335: static void initrank(int *rank[], int component, int isdown)
                    336: {
                    337:        // use breadth-first search to build the list
                    338:        int *marked = new int[N_nodes];
                    339:        int *queue = new int[N_nodes];
                    340:        int *n_lev = new int[Maxlevel+1];
                    341: 
                    342:        // now do the rank partitioning by components
                    343:        edge_t **those = isdown ? Inedges : Outedges;
                    344:        edge_t **these = isdown ? Outedges : Inedges;
                    345:        for(int n = 0; n < N_nodes; ++n)
                    346:        {
                    347:                if(marked[n] || those[n] || Component[n] != component ||
                    348:                   (n < N_real_nodes && N_flat_edges <= 0 && Stems[n]))
                    349:                        continue;
                    350: 
                    351:                marked[n] = 1;
                    352:                queue[0] = n;
                    353:                int first = 0, last = 1;
                    354:                while(first < last)
                    355:                {
                    356:                        int node = queue[first++];
                    357:                        rank[Level[node]][n_lev[Level[node]]++] = node;
                    358:                        for(edge_t *e = these[node]; e; e = e->next)
                    359:                        {
                    360:                                if(!marked[e->node])
                    361:                                {
                    362:                                        marked[e->node] = 1;
                    363:                                        queue[last++] = e->node;
                    364:                                }
                    365:                        }
                    366:                }
                    367:        }
                    368: 
                    369:        for(n = 0; n <= Maxlevel; ++n)
                    370:        {
                    371:                rank[n][n_lev[n]] = -1;
                    372: 
                    373:                // make sure that implicit left-to-right orders are satisfied
                    374:                if(N_flat_edges > 0)
                    375:                        reorder(rank[n],marked,queue);
                    376:        }
                    377: 
                    378:        delete marked;
                    379:        delete queue;
                    380:        delete n_lev;
                    381: }
                    382: 
                    383: // Compute the crossing of two levels.
                    384: // We'll assume that edges point from top to bot.
                    385: static int rcross(int *top, int *bot)
                    386: {
                    387:        // clear up work space
                    388:        for (int i = 0; bot[i] != -1; i++)
                    389:                Count[i] = 0;
                    390: 
                    391:        register int cross = 0; // the crossing count
                    392:        int max = 0;    // index we have to sum to during counting
                    393:        for (i = 0; top[i] != -1; i++)
                    394:        {
                    395:                register edge_t *e;
                    396: 
                    397:                if (max > 0)
                    398:                {
                    399:                        /* iterate over each edge */
                    400:                        for (e = Outedges[top[i]]; e; e = e->next)
                    401:                                for(int k = Invert[e->node]+1; k <= max; k++)
                    402:                                        cross += Count[k]*e->count;
                    403:                }
                    404: 
                    405:                /* update the counts */
                    406:                for (e = Outedges[top[i]]; e; e = e->next)
                    407:                {
                    408:                        register int inv = Invert[e->node];
                    409:                        if (inv > max)
                    410:                                max = inv;
                    411:                        Count[inv] += e->count;
                    412:                }
                    413:        }
                    414:        return cross;
                    415: }
                    416: 
                    417: // compute the inverted indices of all vertices in their rank lists
                    418: // and the crossing statistics between ranks.
                    419: static void inversion(int **ranks)
                    420: {
                    421:        for(int i = 0; i <= Maxlevel; ++i)
                    422:        {
                    423:                int *rank = ranks[i];
                    424:                for(int k = 0; rank[k] != -1; ++k)
                    425:                        Invert[rank[k]] = k;
                    426:        }
                    427: }
                    428: 
                    429: static int cross_stat(int **ranks)
                    430: {
                    431:        int cross = 0;
                    432:        for(int i = 0; i < Maxlevel; ++i)
                    433:                cross += (Cross[i] = rcross(ranks[i],ranks[i+1]));
                    434:        return cross;
                    435: }
                    436: 
                    437: // Compute the crossing of incident edges of two vertices
                    438: static int vcross(edge_t *adj1, edge_t *adj2)
                    439: {
                    440:        register int cross = 0;
                    441:        for (register edge_t *e2 = adj2; e2; e2 = e2->next)
                    442:        {
                    443:                register int inv = Invert[e2->node];
                    444:                register int cnt = e2->count;
                    445:                for(register edge_t *e1 = adj1; e1; e1 = e1->next)
                    446:                        if(Invert[e1->node] > inv)
                    447:                                cross += e1->count * cnt;
                    448:        }
                    449:        return cross;
                    450: }
                    451: 
                    452: // Reduce crossings by adjacent tranpositions of vertices
                    453: static void transpose(int **ranks, int revert)
                    454: {
                    455:        // current number of crossings
                    456:        int curcross = 0;
                    457:        for(int l = 0; l < Maxlevel; ++l)
                    458:        {
                    459:                curcross += Cross[l];
                    460:                Levelmarked[l] = 1;
                    461:        }
                    462:        if(curcross == 0)
                    463:                return;
                    464:        else    Levelmarked[l] = 1;
                    465: 
                    466:        while(1)
                    467:        {
                    468:                int     delta = 0;
                    469:                for (int lev = 0; lev <= Maxlevel; lev++)
                    470:                if(Levelmarked[lev])
                    471:                {
                    472:                        int *rank = ranks[lev];
                    473:                        if(rank[0] == -1 || rank[1] == -1)
                    474:                        {
                    475:                                Levelmarked[lev] = 0;
                    476:                                continue;
                    477:                        }
                    478:                        for(; rank[1] != -1; ++rank)
                    479:                        {
                    480:                                register int c0 = 0, c1 = 0;
                    481:                                int v = rank[0], w = rank[1];
                    482: 
                    483:                                if(N_flat_edges > 0 && left2right(v,w) != 0)
                    484:                                        continue;
                    485: 
                    486:                                if(lev > 0)
                    487:                                {
                    488:                                        edge_t *vadj = Inedges[v], *wadj = Inedges[w];
                    489:                                        c0 += vcross(vadj,wadj);
                    490:                                        c1 += vcross(wadj,vadj);
                    491:                                }
                    492:                                if(lev < Maxlevel)
                    493:                                {
                    494:                                        edge_t *vadj = Outedges[v], *wadj = Outedges[w];
                    495:                                        c0 += vcross(vadj,wadj);
                    496:                                        c1 += vcross(wadj,vadj);
                    497:                                }
                    498: 
                    499:                                if (c1 < c0 || (c1 > 0 && c1 == c0 && revert))
                    500:                                {
                    501:                                        Levelmarked[lev] = 2;
                    502:                                        Invert[v]++;
                    503:                                        Invert[w]--;
                    504:                                        rank[0] = w;
                    505:                                        rank[1] = v;
                    506:                                        delta += c0-c1;
                    507:                                }
                    508:                        }
                    509: 
                    510:                        if(Levelmarked[lev] == 2)
                    511:                        {
                    512:                                Levelmarked[lev] = 1;
                    513:                                if(lev > 0)
                    514:                                {
                    515:                                        Levelmarked[lev-1] = 1;
                    516:                                        Cross[lev-1] = -1;
                    517:                                }
                    518:                                if(lev < Maxlevel)
                    519:                                {
                    520:                                        Levelmarked[lev+1] = 1;
                    521:                                        Cross[lev] = -1;
                    522:                                }
                    523:                        }
                    524:                        else    Levelmarked[lev] = 0;
                    525:                }
                    526: 
                    527:                curcross -= delta;
                    528:                float reduce = curcross <= 0 ? 0. : ((float)delta)/curcross;
                    529:                if(curcross == 0 || reduce <= Convergence)
                    530:                        break;
                    531:        }
                    532: 
                    533:        // restore crossing statistics
                    534:        for(l = 0; l < Maxlevel; ++l)
                    535:                if(Cross[l] < 0)
                    536:                        Cross[l] = rcross(ranks[l],ranks[l+1]);
                    537: }
                    538: 
                    539: // sort nodes by their median values.
                    540: // This is basically a bubble sort that respects fixed points
                    541: static int mediansort(int *array, int nelt, int revert, int hasfixed)
                    542: {
                    543:        int changed = 0;
                    544: 
                    545:        register int *ep = array+nelt, *lp, *rp;
                    546:        for(nelt -= 1; nelt > 0; --nelt)
                    547:        {
                    548:                lp = array;
                    549:                while(lp < ep)
                    550:                {
                    551:                        // -1 nodes are FIXED points
                    552:                        if(Median[*lp] < 0)
                    553:                                for(; lp < ep; lp++)
                    554:                                        if(Median[*lp] >= 0)
                    555:                                                break;
                    556:                        if(lp >= ep)
                    557:                                break;
                    558: 
                    559:                        // find the one that can be compared with
                    560:                        int muststay = 0;
                    561:                        for(rp = lp+1; rp < ep; ++rp)
                    562:                        {
                    563:                                if(N_flat_edges > 0 && left2right(*lp,*rp))
                    564:                                {
                    565:                                        muststay = 1;
                    566:                                        break;
                    567:                                }
                    568:                                if(Median[*rp] >= 0)
                    569:                                        break;
                    570:                        }
                    571:                        if(rp >= ep)
                    572:                                break;
                    573: 
                    574:                        // switch if appropriate
                    575:                        if(!muststay &&
                    576:                           (Median[*lp] > Median[*rp] ||
                    577:                            (Median[*lp] == Median[*rp] && revert)))
                    578:                        {
                    579:                                register int t = *lp;
                    580:                                *lp = *rp;
                    581:                                *rp = t;
                    582:                                changed++;
                    583:                        }
                    584:                        lp = rp;
                    585:                }
                    586: 
                    587:                if(!hasfixed && !revert)
                    588:                        --ep;
                    589:        }
                    590:        return changed;
                    591: }
                    592: 
                    593: 
                    594: // reduce crossing using weighted median sorting
                    595: static int intcmp(register int *i1, register int *i2)
                    596: {
                    597:        return *i1 - *i2;
                    598: }
                    599: static void median(int **ranks, int revert, int isup)
                    600: {
                    601: #define SCALE  16
                    602:        for (int lev = 1; lev <= Maxlevel; lev++)
                    603:        {
                    604:                int     thislev = isup ? Maxlevel-lev : lev;
                    605:                int     thatlev = isup ? thislev+1 : thislev-1;
                    606:                edge_t  **edges = isup ? Outedges : Inedges;
                    607:                int     *thislist = ranks[thislev];
                    608:                int     *thatlist = ranks[thatlev];
                    609: 
                    610:                // compute medians of thislist
                    611:                int hasfixed = 0;
                    612:                for(int n_this = 0; thislist[n_this] != -1; n_this++)
                    613:                {
                    614:                        register int node = thislist[n_this];
                    615:                        register int *endadj = Medadj;
                    616:                        for(register edge_t *e = edges[node]; e; e = e->next)
                    617:                                for(int k = e->count; k > 0; --k)
                    618:                                        *endadj++ = Invert[e->node];
                    619:                        register int cnt = endadj-Medadj;
                    620: #ifdef BCENTER
                    621:        // barycenter method
                    622:                        if(cnt > 0)
                    623:                        {
                    624:                                int ave = 0;
                    625:                                for(int m = 0; m < cnt; ++m)
                    626:                                        ave += Medadj[m];
                    627:                                Median[node] = (SCALE*ave)/cnt;
                    628:                        }
                    629:                        else
                    630:                        {
                    631:                                Median[node] = -1;
                    632:                                hasfixed = 1;
                    633:                        }
                    634: #else  /* a right median method */
                    635: #ifdef RMEDIAN
                    636:                        if(cnt > 1)
                    637:                                qsort((char*)Medadj,cnt,sizeof(Medadj[0]),(qsortcmpfun)intcmp);
                    638:                        if(cnt == 0)
                    639:                        {
                    640:                                Median[node] = -1;
                    641:                                hasfixed = 1;
                    642:                        }
                    643:                        else    Median[node] = SCALE*Medadj[cnt/2];
                    644: #else  /* weighted median */
                    645:                        switch(cnt)
                    646:                        {
                    647:                        case 0 :
                    648:                                Median[node] = -1;
                    649:                                hasfixed = 1;
                    650:                                break;
                    651:                        case 1 :
                    652:                                Median[node] = SCALE*Medadj[0];
                    653:                                break;
                    654:                        case 2 :
                    655:                                Median[node] = (Medadj[0]+Medadj[1])*(SCALE/2);
                    656:                                break;
                    657:                        default :
                    658:                                qsort((char*)Medadj,cnt,sizeof(Medadj[0]),(qsortcmpfun)intcmp);
                    659:                                if(cnt%2)
                    660:                                {
                    661:                                        Median[node] = SCALE*Medadj[cnt/2];
                    662:                                        break;
                    663:                                }
                    664: 
                    665:                                register int r = cnt/2;
                    666:                                register int l = r-1;
                    667: 
                    668:                                // compute left/right spans
                    669:                                int lspan = 0, rspan = 0;
                    670:                                int curinv = Medadj[l];
                    671:                                int nextinv;
                    672:                                for(k = l-1; k >= 0; --k)
                    673:                                {
                    674:                                        nextinv = Medadj[k];
                    675:                                        lspan += curinv-nextinv;
                    676:                                        curinv = nextinv;
                    677:                                }
                    678:                                curinv = Medadj[r];
                    679:                                for(k = r+1; k < cnt; ++k)
                    680:                                {
                    681:                                        nextinv = Medadj[k];
                    682:                                        rspan += nextinv-curinv;
                    683:                                        curinv = nextinv;
                    684:                                }
                    685:                                if(lspan == rspan)
                    686:                                        Median[node] = (Medadj[l]+Medadj[r])*(SCALE/2);
                    687:                                else
                    688:                                {
                    689:                                        int w = Medadj[l]*rspan+ Medadj[r]*lspan;
                    690:                                        Median[node] = (w*SCALE)/(lspan+rspan);
                    691:                                }
                    692:                                break;
                    693:                        }
                    694: #endif /* RMEDIAN */
                    695: #endif /* BCENTER */
                    696:                }
                    697: 
                    698:                // sort by medians
                    699:                if(mediansort(thislist,n_this,revert,hasfixed))
                    700:                {
                    701:                        for(int i = 0; *thislist != -1; ++i)
                    702:                                Invert[*thislist++] = i;
                    703:                        if(thislev > 0)
                    704:                                Cross[thislev-1] = -1;
                    705:                        if(thislev < Maxlevel)
                    706:                                Cross[thislev] = -1;
                    707:                }
                    708:        }
                    709:        for(lev = 0; lev < Maxlevel; ++lev)
                    710:                if(Cross[lev] < 0)
                    711:                        Cross[lev] = rcross(ranks[lev],ranks[lev+1]);
                    712: }
                    713: 
                    714: // minimizing crossing using the median and transpose heuristics
                    715: static int mincross(int **ranks, int bestcross)
                    716: {
                    717:        // copy current rank to List to start the process 
                    718:        copyrank(ranks,List);
                    719: 
                    720:        inversion(List);
                    721:        int curcross = cross_stat(List);
                    722:        if(curcross < bestcross)
                    723:                bestcross = curcross;
                    724: 
                    725:        int counter = 1;
                    726:        for (int iter = 0; iter < Maxiter; iter++)
                    727:        {
                    728:                median(List,iter%4 < 2 ? 1 : 0,iter%2 ? 1 : 0);
                    729: #ifndef NOTRANSPOSE
                    730:                transpose(List,iter%4 < 2 ? 0 : 1);
                    731: #endif
                    732:                curcross = 0;
                    733:                for(int i = 0; i < Maxlevel; ++i)
                    734:                        curcross += Cross[i];
                    735: #ifdef BIGGRAPH
                    736:                if(Verbose)
                    737:                        fprintf(stderr,"Iteration %d, curcross=%d bestcross=%d\n",
                    738:                                iter,curcross,bestcross);
                    739: #endif
                    740:                if(curcross < bestcross)
                    741:                {
                    742:                        float reduce = curcross <= 0 ? 0. :
                    743:                                 ((float)(bestcross-curcross))/curcross;
                    744: 
                    745:                        copyrank(List,ranks);
                    746:                        bestcross = curcross;
                    747: 
                    748:                        if(bestcross == 0 || reduce < Convergence)
                    749:                                break;
                    750: 
                    751:                        counter = 1;
                    752:                }
                    753:                else
                    754:                {
                    755:                        if(counter > Minquit)
                    756:                                break;
                    757:                        ++counter;
                    758:                }
                    759:        }
                    760: 
                    761:        return bestcross;
                    762: }
                    763: 
                    764: // compute edge crossings
                    765: static int scross(int iw, int count, edge_t *adj, int dir)
                    766: {
                    767:        int cross = 0;
                    768:        if(dir > 0)
                    769:        {
                    770:                for(register edge_t *e = adj; e; e = e->next)
                    771:                        if(Invert[e->node] < iw)
                    772:                                cross += e->count*count;
                    773:        }
                    774:        else
                    775:        {
                    776:                for(register edge_t *e = adj; e; e = e->next)
                    777:                        if(Invert[e->node] > iw)
                    778:                                cross += e->count*count;
                    779:        }
                    780:        return cross;
                    781: }
                    782: 
                    783: // put stems in place where they'll be close to their adjacent nodes
                    784: static void fixstem(int **ranks, int *stem)
                    785: {
                    786:        for(int dir = 1;  dir >= -1; dir -= 2)
                    787:        for(int l = dir > 0 ? 1 : Maxlevel-1; l >= 0 && l <= Maxlevel; l += dir)
                    788:        {
                    789:                edge_t **these = dir > 0 ? Inedges : Outedges;
                    790:                edge_t **those = dir > 0 ? Outedges : Inedges;
                    791:                int *rank = ranks[l]; 
                    792: 
                    793:                // count the list size
                    794:                int n_rank = 0;
                    795:                int n_stem = 0;
                    796:                for(int k = 0; rank[k] >= 0; ++k, ++n_rank)
                    797:                {
                    798:                        int v = rank[k];
                    799:                        if(these[v] && !these[v]->next && !those[v])
                    800:                                stem[n_stem++] = v;
                    801:                }
                    802:                if(n_stem <= 0)
                    803:                        continue;
                    804: 
                    805:                for(k = 0; k < n_stem; ++k)
                    806:                {
                    807:                        int v = stem[k], iv = Invert[v];
                    808:                        int w = these[v]->node, iw = Invert[w];
                    809:                        int count = these[v]->count;
                    810: 
                    811:                        // find the left and right medians and bounds
                    812:                        int n = 0;
                    813:                        for(edge_t *e = those[w]; e; e = e->next)
                    814:                                if(e->node != v)
                    815:                                        Medadj[n++] = Invert[e->node];
                    816:                        if(n == 0)
                    817:                                continue;
                    818:                        if(n > 2)
                    819:                                qsort((char*)Medadj,n,sizeof(Medadj[0]),(qsortcmpfun)intcmp);
                    820:                        int rmed = Medadj[n/2];
                    821:                        int lmed = n%2 ? rmed : Medadj[n/2-1];
                    822: 
                    823:                        // check each position
                    824:                        int best = iv, cross = 0;
                    825:                        int dist = iabs(2*iv - (rmed+lmed));
                    826:                        for(int d = -1; d <= 1; d += 2)
                    827:                        {
                    828:                                int c = 0, lm = lmed, rm = rmed;
                    829:                                for(int p = iv+d; p >= 0 && p < n_rank; p += d)
                    830:                                {
                    831:                                        int x = rank[p];
                    832:                                        if(p == lm)
                    833:                                                lm -= d;
                    834:                                        if(p == rm)
                    835:                                                rm -= d;
                    836: 
                    837:                                        int c0 = scross(iw,count,these[x],d);
                    838:                                        int c1 = scross(iw,count,these[x],-d);
                    839:                                        c += c1-c0;
                    840:                                        if(c == cross)
                    841:                                        {
                    842:                                                int di = iabs(2*p -(lm+rm));
                    843:                                                if(di < dist)
                    844:                                                {
                    845:                                                        best = p;
                    846:                                                        dist = di;
                    847:                                                }
                    848:                                        }
                    849:                                        else if(c < cross)
                    850:                                        {
                    851:                                                cross = c;
                    852:                                                best = p;
                    853:                                                dist = iabs(2*p - (lm+rm));
                    854:                                        }
                    855:                                }
                    856:                        }
                    857:                        if(best == iv)
                    858:                                continue;
                    859: 
                    860:                        // move v to its best place
                    861:                        d = best < iv ? -1 : 1;
                    862:                        for(register int p = iv; p != best; p += d)
                    863:                        {
                    864:                                rank[p] = rank[p+d];
                    865:                                Invert[rank[p]] = p;
                    866:                        }
                    867:                        rank[p] = v;
                    868:                        Invert[v] = p;
                    869: 
                    870:                }
                    871:        }
                    872: }
                    873: 
                    874: // make node orderings for a connected component
                    875: static int buildrank(int **target, int **tryout, int component)
                    876: {
                    877:        // build order using downward depth-first search
                    878:        int start_target, start_tryout, bestcross, curcross;
                    879:        initrank(target,component,1);
                    880:        inversion(target);
                    881:        start_target = bestcross = cross_stat(target);
                    882:        start_tryout = 0;
                    883: 
                    884:        if(bestcross > 0)
                    885:        {
                    886: #ifndef NOTRANSPOSE
                    887:                transpose(target,0);
                    888:                bestcross = 0;
                    889:                for(int i = 0; i < Maxlevel; ++i)
                    890:                        bestcross += Cross[i];
                    891: #endif
                    892:        }
                    893: 
                    894:        // rebuild order using upward depth-first search
                    895:        if(bestcross > 0)
                    896:        {
                    897:                initrank(tryout,component,0);
                    898:                inversion(tryout);
                    899:                start_tryout = curcross = cross_stat(tryout);
                    900: 
                    901:                if(curcross > 0)
                    902:                {
                    903: #ifndef NOTRANSPOSE
                    904:                        transpose(tryout,0);
                    905:                        curcross = 0;
                    906:                        for(int i = 0; i < Maxlevel; ++i)
                    907:                                curcross += Cross[i];
                    908: #endif
                    909:                }
                    910:                if(curcross == 0)
                    911:                {
                    912:                        copyrank(tryout,target);
                    913:                        bestcross = curcross;
                    914:                }
                    915:        }
                    916: 
                    917:        // iterations to improve crossing
                    918:        if(bestcross > 0)
                    919:                bestcross = mincross(target,Maxint);
                    920:        if(bestcross > 0 && (curcross = mincross(tryout,bestcross)) < bestcross)
                    921:                copyrank(tryout,target);
                    922: 
                    923:        // fix dangling stems
                    924:        if(N_flat_edges <= 0)
                    925:        {
                    926:                inversion(target);
                    927:                fixstem(target,Count);
                    928:        }
                    929: 
                    930:        return max(start_target,start_tryout);
                    931: }

unix.superglobalmegacorp.com

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