Annotation of researchv10dc/cmd/dag/dag_ranks.c, revision 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.