48 static int nNodeGroups = 0;
54 static void computeNodeGroups(
graph_t * g)
70 nodeGroups[nNodeGroups].
nodes[0] = n;
71 nodeGroups[nNodeGroups].
nNodes = 1;
75 ND_id(n) = nNodeGroups;
83 nodeGroups[index].
nodes[nodeGroups[index].
nNodes++] = n;
86 (nodeGroups[index].
height <
93 nodeGroups[nNodeGroups].
nodes =
98 nodeGroups[nNodeGroups].
nodes[0] = l;
99 nodeGroups[nNodeGroups].
nNodes = 1;
103 nodeGroups[nNodeGroups].
nodes[0] = l;
104 nodeGroups[nNodeGroups].
nodes[1] = n;
105 nodeGroups[nNodeGroups].
nNodes = 2;
106 nodeGroups[nNodeGroups].
width =
108 nodeGroups[nNodeGroups].
height =
113 ND_id(l) = nNodeGroups;
114 ND_id(n) = nNodeGroups;
171 static int *sortedLayerIndex;
172 static int nLayers = 0;
176 static void computeLayerWidths(
graph_t * g)
186 if (layerWidthInfo) {
187 for (i = 0; i < nNodeGroups; i++) {
188 if (layerWidthInfo[i].nodeGroupsInLayer) {
194 free(layerWidthInfo[i].nodeGroupsInLayer);
196 if (layerWidthInfo[i].removed)
197 free(layerWidthInfo[i].removed);
200 free(layerWidthInfo);
207 for (i = 0; i < nNodeGroups; i++) {
216 layerWidthInfo[i].
width = 0.0;
217 layerWidthInfo[i].
height = 0.0;
248 for (i = 0; i < nNodeGroups; i++) {
249 v = nodeGroups[i].
nodes[0];
255 for (i = 0; i < nNodeGroups; i++) {
256 v = nodeGroups[i].
nodes[0];
263 if (layerWidthInfo[
ND_rank(v)].height < nodeGroups[i].height *
DPI)
266 nodeGroupsInLayer[layerWidthInfo[
ND_rank(v)].
267 nNodeGroupsInLayer] = &nodeGroups[i];
268 layerWidthInfo[
ND_rank(v)].nNodeGroupsInLayer++;
277 static int compFunction(
const void *a,
const void *b)
279 int *ind1 = (
int *) a;
280 int *ind2 = (
int *) b;
282 return (layerWidthInfo[*ind2].width >
283 layerWidthInfo[*ind1].width) - (layerWidthInfo[*ind2].
width <
284 layerWidthInfo[*ind1].
width);
292 static void sortLayers(
graph_t * g)
294 qsort(sortedLayerIndex,
agnnodes(g),
sizeof(
int), compFunction);
303 int i,
max = 0, cnt = 0;
304 for (i = 0; i < ng->
nNodes; i++) {
325 for (i = 0; i < ng->
nNodes; i++) {
343 static int compFunction2(
const void *a,
const void *b)
347 int cnt1 = getOutDegree(*ind1);
348 int cnt2 = getOutDegree(*ind2);
350 return (cnt2 < cnt1) - (cnt2 > cnt1);
358 static int compFunction3(
const void *a,
const void *b)
361 if ((*ind2)->height == (*ind1)->height)
362 return ((*ind2)->width < (*ind1)->width) - ((*ind2)->width >
365 return ((*ind2)->height < (*ind1)->height) - ((*ind2)->height >
416 static int checkNodeGroupConstraints(
nodeGroup_t * ndg)
439 for (i = 0; i < ng->
nNodes; i++) {
441 if (layerWidthInfo[nextLayerIndex].layerNumber ==
479 static void reduceMaxWidth(
graph_t * g)
487 for (i = 0; i < nLayers; i++) {
488 if (layerWidthInfo[sortedLayerIndex[i]].nNodeGroupsInLayer <= 1)
491 maxLayerIndex = sortedLayerIndex[i];
494 i + 1) ? layerWidthInfo[sortedLayerIndex[i +
505 qsort(layerWidthInfo[maxLayerIndex].nodeGroupsInLayer,
506 layerWidthInfo[maxLayerIndex].nNodeGroupsInLayer,
511 if (nextMaxWidth <= layerWidthInfo[maxLayerIndex].width / 2
512 || nextMaxWidth == layerWidthInfo[maxLayerIndex].width)
513 nextMaxWidth = layerWidthInfo[maxLayerIndex].
width / 2;
515 double targetWidth = nextMaxWidth;
522 int nextLayerIndex = -1;
523 for (i = 0; i < nLayers; i++) {
524 if (layerWidthInfo[i].layerNumber ==
525 layerWidthInfo[maxLayerIndex].layerNumber + 1)
529 if (nextLayerIndex > -1) {
536 if (layerWidthInfo[maxLayerIndex].removed[i])
539 if (!checkHorizontalEdge
540 (g, layerWidthInfo[maxLayerIndex].nodeGroupsInLayer[i],
542 && w + layerWidthInfo[nextLayerIndex].width +
543 (layerWidthInfo[maxLayerIndex].nodeGroupsInLayer[i])->
544 width <= targetWidth) {
553 layerWidthInfo[maxLayerIndex].
removed[i] = 1;
555 layerWidthInfo[maxLayerIndex].
width -= ng->
width;
556 for (j = 0; j < ng->
nNodes; j++)
560 layerWidthInfo[nextLayerIndex].
561 nodeGroupsInLayer[layerWidthInfo[nextLayerIndex].
562 nNodeGroupsInLayer] = ng;
563 layerWidthInfo[nextLayerIndex].
564 removed[layerWidthInfo[nextLayerIndex].
565 nNodeGroupsInLayer] = 0;
566 layerWidthInfo[nextLayerIndex].nNodeGroupsInLayer++;
567 layerWidthInfo[nextLayerIndex].
width += ng->
width;
592 for (i = 0; i < nLayers; i++) {
593 if (layerWidthInfo[i].layerNumber >
594 layerWidthInfo[maxLayerIndex].layerNumber)
602 if (layerWidthInfo[maxLayerIndex].removed[i])
607 (layerWidthInfo[maxLayerIndex].nodeGroupsInLayer[i])->width *
610 nodeGroupsInLayer[i]->nodes[0]) !=
SINKRANK
612 nodeGroupsInLayer[i]->nodes[0]) !=
MAXRANK)
615 (layerWidthInfo[maxLayerIndex].nodeGroupsInLayer[i]->
618 nodeGroupsInLayer[i]->nodes[0]) !=
MAXRANK
619 && hasMaxOrSinkNodes(&layerWidthInfo[maxLayerIndex]))
633 layerWidthInfo[maxLayerIndex].
removed[i] = 1;
636 layerWidthInfo[maxLayerIndex].
width -=
638 for (j = 0; j < ng->
nNodes; j++)
642 layerWidthInfo[nLayers].
643 nodeGroupsInLayer[layerWidthInfo[nLayers].
644 nNodeGroupsInLayer] = ng;
645 layerWidthInfo[nLayers].nNodeGroupsInLayer++;
646 layerWidthInfo[nLayers].layerNumber =
ND_rank(ng->
nodes[0]);
648 layerWidthInfo[nLayers].width += (ng->
width *
DPI + (layerWidthInfo[nLayers].nNodeGroupsInLayer > 1) *
GD_nodesep(g));
662 if ((
ND_rank(
aghead(e)) > layerWidthInfo[nLayers].layerNumber
664 layerWidthInfo[nLayers].layerNumber)
674 layerWidthInfo[nLayers].
width +=
686 for (i = 0; i < nLayers; i++) {
687 if (layerWidthInfo[i].layerNumber >
688 layerWidthInfo[maxLayerIndex].layerNumber + 1)
702 static void reduceMaxWidth2(
graph_t * g)
705 int maxLayerIndex = 0;
706 double nextMaxWidth = 0.0;
719 for (i = 0; i < nLayers; i++) {
720 if (layerWidthInfo[sortedLayerIndex[i]].nNodeGroupsInLayer <= 1)
723 maxLayerIndex = sortedLayerIndex[i];
727 i + 1) ? layerWidthInfo[sortedLayerIndex[i +
739 qsort(layerWidthInfo[maxLayerIndex].nodeGroupsInLayer,
740 layerWidthInfo[maxLayerIndex].nNodeGroupsInLayer,
744 printf(
"\nSorted nodes in mx layer:\n---------------------------\n");
747 printf(
"%s. width=%lf, height=%lf\n",
748 agnameof(node), node->width, node->height);
752 if (nextMaxWidth <= layerWidthInfo[maxLayerIndex].width / 4
753 || nextMaxWidth >= layerWidthInfo[maxLayerIndex].width * 3 / 4)
754 nextMaxWidth = layerWidthInfo[maxLayerIndex].
width / 2;
756 targetWidth = nextMaxWidth;
770 for (i = 0; i < limit + rem; i++) {
771 if (layerWidthInfo[maxLayerIndex].removed[i]) {
777 layerWidthInfo[maxLayerIndex].nodeGroupsInLayer[i]->width *
797 for (l = 0; l < ng->
nNodes; l++) {
802 for (p = 0; p < fstNdGrp->
nNodes; p++)
803 for (q = 0; q < ng->
nNodes; q++) {
856 layerWidthInfo[maxLayerIndex].
removed[i] = 1;
861 layerWidthInfo[maxLayerIndex].
width -=
873 static void balanceLayers(
graph_t * g)
875 int maxLayerIndex, nextLayerIndex, i;
880 for (i = 0; i < nLayers; i++) {
881 if (layerWidthInfo[sortedLayerIndex[i]].nNodeGroupsInLayer <= 1
883 layerWidthInfo[sortedLayerIndex[i]].layerNumber + 1 == nLayers)
886 maxLayerIndex = sortedLayerIndex[i];
887 maxWidth = layerWidthInfo[maxLayerIndex].
width;
888 printf(
"Balancing: maxLayerIndex = %d\n", maxLayerIndex);
898 for (i = 0; i < nLayers; i++) {
899 if (layerWidthInfo[i].layerNumber ==
900 layerWidthInfo[maxLayerIndex].layerNumber + 1) {
905 if (nextLayerIndex > -1) {
914 if (layerWidthInfo[maxLayerIndex].removed[i])
917 if (!checkHorizontalEdge
918 (g, layerWidthInfo[maxLayerIndex].nodeGroupsInLayer[i],
920 && layerWidthInfo[nextLayerIndex].width
922 <= layerWidthInfo[maxLayerIndex].width
933 layerWidthInfo[maxLayerIndex].
removed[i] = 1;
935 layerWidthInfo[maxLayerIndex].
width -= (ng->
width);
937 for (j = 0; j < ng->
nNodes; j++)
941 layerWidthInfo[nextLayerIndex].
942 nodeGroupsInLayer[layerWidthInfo[nextLayerIndex].
943 nNodeGroupsInLayer] = ng;
944 layerWidthInfo[nextLayerIndex].
945 removed[layerWidthInfo[nextLayerIndex].
946 nNodeGroupsInLayer] = 0;
947 layerWidthInfo[nextLayerIndex].nNodeGroupsInLayer++;
948 layerWidthInfo[nextLayerIndex].
width +=
966 static void applyPacking(
graph_t * g,
double targetAR)
973 sortedLayerIndex[i] = i;
989 for (i = 0; i < 1; i++) {
995 computeLayerWidths(g);
1005 for (k = 0; k < nLayers - 1; k++) {
1007 if (layerWidthInfo[k].nNodeGroupsInLayer > 7) {
1012 for (i = layerWidthInfo[k].nNodeGroupsInLayer - 1; i >= 0; i--) {
1014 if (layerWidthInfo[k].removed[i])
1021 layerWidthInfo[k].
removed[i] = 1;
1024 layerWidthInfo[k].
width -=
1026 for (j = 0; j < ng->
nNodes; j++)
1033 nNodeGroupsInLayer] =
1051 int nNodeG = 0, l, nDummy = 0;
1054 for (k = 0; k < nLayers; k++) {
1057 if (layerWidthInfo[k].width > maxW)
1059 maxW = layerWidthInfo[k].
width;
1079 static void applyPacking2(
graph_t * g)
1085 for (i = 0; i <
agnnodes(g); i++) {
1086 sortedLayerIndex[i] = i;
1089 computeLayerWidths(g);
1100 void applyPacking4(
graph_t * g)
1106 for (i = 0; i <
agnnodes(g); i++) {
1107 sortedLayerIndex[i] = i;
1111 for (i = 0; i < 1; i++) {
1120 computeLayerWidths(g);
1135 typedef struct myNodeInfo_t {
1142 myNodeInfo_t *myNodeInfo;
1148 int getMaxLevelNumber(
graph_t * g)
1175 for (j = 0; j <
ND_in(v).size; j++) {
1176 e =
ND_in(v).list[j];
1180 dummydiff += countDummyDiff(g, u, max);
1186 myNodeInfo[
ND_id(v)].rank += 1;
1188 dummydiff = dummydiff -
ND_in(v).size +
ND_out(v).size;
1198 static void applyPromotionHeuristic(
graph_t * g)
1204 int max = getMaxLevelNumber(g);
1209 myNodeInfo =
N_NEW(nNodes, myNodeInfo_t);
1210 myNodeInfo_t *myNodeInfoBak =
N_NEW(nNodes, myNodeInfo_t);
1213 myNodeInfo[i].indegree =
ND_in(v).size;
1214 myNodeInfo[i].outdegree =
ND_out(v).size;
1215 myNodeInfo[i].rank =
ND_rank(v);
1216 myNodeInfo[i].node = v;
1219 myNodeInfoBak[i] = myNodeInfo[i];
1226 if (
ND_in(v).size > 0) {
1227 if (countDummyDiff(g, v, max) <= 0) {
1230 for (j = 0; j < nNodes; j++) {
1231 myNodeInfoBak[j] = myNodeInfo[j];
1235 for (j = 0; j < nNodes; j++) {
1236 myNodeInfo[j] = myNodeInfoBak[j];
1242 }
while (count < max);
1256 static int allNeighborsAreBelow(
Agnode_t * n)
1263 for (i = 0; i <
ND_out(n).size; i++) {
1287 static void reverseLevelNumbers(
graph_t * g)
1292 max = getMaxLevelNumber(g);
1306 static void doSameRank(
graph_t * g)
1309 for (i = 0; i < nNodeGroups; i++) {
1312 for (j = 0; j < nodeGroups[i].
nNodes; j++) {
1317 for (k = 0; k < nodeGroups[i].
nNodes; k++) {
1319 nodes[(j + k) % nodeGroups[i].nNodes]) = r;
1335 for (i = 0; i < nNodeGroups; i++) {
1338 for (j = 0; j < nodeGroups[i].
nNodes; j++) {
1342 for (k = 0; k < nodeGroups[i].
nNodes; k++) {
1344 nodes[(j + k) % nodeGroups[i].nNodes]) = 0;
1347 nodes[(j + k) % nodeGroups[i].nNodes]) !=
1351 k) % nodeGroups[i].nNodes]) =
1364 static int getMaxRank(
graph_t * g)
1381 static void doMaxRank(
graph_t * g)
1384 for (i = 0; i < nNodeGroups; i++) {
1386 int maxR = getMaxRank(g);
1388 for (j = 0; j < nodeGroups[i].
nNodes; j++) {
1392 for (k = 0; k < nodeGroups[i].
nNodes; k++) {
1394 nodes[(j + k) % nodeGroups[i].nNodes]) = maxR;
1397 nodes[(j + k) % nodeGroups[i].nNodes]) !=
1401 k) % nodeGroups[i].nNodes]) =
1415 static void doSourceRank(
graph_t * g)
1420 for (i = 0; i < nNodeGroups; i++) {
1423 for (j = 0; j < nodeGroups[i].
nNodes; j++) {
1427 for (k = 0; k < nodeGroups[i].
nNodes; k++) {
1429 nodes[(j + k) % nodeGroups[i].nNodes]) = 0;
1431 nodes[(j + k) % nodeGroups[i].nNodes]) =
1447 for (i = 0; i < nNodeGroups; i++) {
1448 if (nodeGroups[i].nNodes > 0
1450 &&
ND_rank(nodeGroups[i].nodes[0]) == 0) {
1461 for (i = 0; i < nNodeGroups; i++) {
1462 if (nodeGroups[i].nNodes > 0
1466 for (j = 0; j < nodeGroups[i].
nNodes; j++) {
1467 ND_rank(nodeGroups[i].nodes[j])++;
1477 static void doSinkRank(
graph_t * g)
1482 max = getMaxRank(g);
1486 for (i = 0; i < nNodeGroups; i++) {
1487 if (nodeGroups[i].nNodes > 0
1489 &&
ND_rank(nodeGroups[i].nodes[0]) == max) {
1498 for (i = 0; i < nNodeGroups; i++) {
1501 for (j = 0; j < nodeGroups[i].
nNodes; j++) {
1505 for (k = 0; k < nodeGroups[i].
nNodes; k++) {
1507 nodes[(j + k) % nodeGroups[i].nNodes]) =
1510 nodes[(j + k) % nodeGroups[i].nNodes]) =
1526 int currentLayer = 1;
1529 int nPinnedNodes = 0, nSelected = 0;
1532 int i, prevSize = 0;
1541 while (nPinnedNodes != nNodes) {
1544 if (allNeighborsAreBelow(n)) {
1560 for (i = prevSize; i < USize; i++) {
1569 applyPromotionHeuristic(g);
1572 reverseLevelNumbers(g);
1574 computeNodeGroups(g);
1602 for (lc = 0; lc <
ND_in(n).size; lc++) {
1603 e =
ND_in(n).list[lc];
1615 static double computeCombiAR(
graph_t * g)
1617 int i, maxLayerIndex;
1622 computeLayerWidths(g);
1625 for (i = 0; i < nLayers; i++) {
1627 layerWidthInfo[i].width +
1628 layerWidthInfo[i].nDummyNodes *
GD_nodesep(g)) {
1630 layerWidthInfo[i].
width +
1634 maxH += layerWidthInfo[i].
height;
1637 ratio = maxW / maxH;
1647 void applyExpansion(
graph_t * g)
1653 computeLayerWidths(g);
1655 for (i = 0; i < nLayers; i++) {
1656 if (layerWidthInfo[i].layerNumber == nLayers / 2) {
1666 for (p = 0; p < ng->
nNodes; p++) {
1669 while (e =
ND_in(nd).list[0]) {
1670 printf(
"Reversing edge: %s->%s\n", agnemeof(
agtail(e)),
1681 printf(
"Reversing long edge: %s->%s\n",
1715 for (l = 0; l < nLayers && brFlag; l++) {
1722 for (q = 0; q < ng2->
nNodes && brFlag; q++) {
1724 if (
ND_in(nd2).size == 0) {
1735 layerWidthInfo[0].nodeGroupsInLayer[0]->nodes[0],
1749 static void zapLayers(
graph_t * g)
1757 for (i = 0; i < nLayers; i++) {
1758 if (layerWidthInfo[i].nNodeGroupsInLayer == 0) {
1762 }
else if (count && layerWidthInfo[i].layerNumber > start) {
1766 for (q = 0; q < ng->
nNodes; q++) {
1793 computeNodeGroups(g);
1795 for (i = 0; (i < iterations) || (iterations == -1); i++) {
1805 asp->
combiAR = computeCombiAR(g);
1807 fprintf(stderr,
"combiAR = %lf\n", asp->
combiAR);
1812 if (combiAR < 0.8 * targetAR) {
1814 printf(
"Apply expansion? (y/n):");
1816 if (strcmp(str,
"y") == 0)
1822 if ((asp->
combiAR <= asp->
targetAR) || ((iterations == -1) && (lastAR <= asp->combiAR))) {
1836 computeLayerWidths(g);
1838 asp->
combiAR = computeCombiAR(g);
1848 static void NikolovHealy(
graph_t * g)
1850 int currentLayer = 1;
1853 int nPinnedNodes = 0, nSelected = 0;
1856 int i, prevSize = 0;
1868 while (nPinnedNodes != nNodes) {
1871 if (allNeighborsAreBelow(n)) {
1887 for (i = prevSize; i < USize; i++) {
1901 applyPromotionHeuristic(g);
1904 reverseLevelNumbers(g);
1913 void rank4(
graph_t * g,
int iterations)
1915 int currentLayer = 1;
1918 int nPinnedNodes = 0, nSelected = 0;
1921 int i, prevSize = 0;
1924 printf(
"# of interations of packing: ");
1926 printf(
"it=%d\n", it);
1928 computeNodeGroups(g);
1930 for (i = 0; i < it; i++) {
1942 combiAR = computeCombiAR(g);
1943 printf(
"%d. combiAR = %lf\n", i, combiAR);
1984 p =
agget (g,
"aspect");
1986 if (!p || ((r = sscanf (p,
"%lf,%d", &rv, &passes)) <= 0)) {
1991 agerr (
AGWARN,
"the aspect attribute has been disabled due to implementation flaws - attribute ignored.\n");
2004 fprintf(stderr,
"Target AR = %g\n", adata->
targetAR);
struct layerWidthInfo_t layerWidthInfo_t
CGRAPH_API Agedge_t * agfstin(Agraph_t *g, Agnode_t *n)
void initEdgeTypes(graph_t *g)
int agerr(agerrlevel_t level, const char *fmt,...)
void delete_fast_edge(Agedge_t *)
nodeGroup_t ** nodeGroupsInLayer
CGRAPH_API Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Agedge_t * virtual_edge(Agnode_t *, Agnode_t *, Agedge_t *)
char * agget(void *obj, char *name)
node_t * UF_find(node_t *n)
CGRAPH_API Agraph_t * agraphof(void *obj)
CGRAPH_API Agnode_t * agtail(Agedge_t *e)
int rank(graph_t *g, int balance, int maxiter)
CGRAPH_API Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
CGRAPH_API Agnode_t * aghead(Agedge_t *e)
CGRAPH_API char * agnameof(void *)
CGRAPH_API Agnode_t * agfstnode(Agraph_t *g)
EXTERN unsigned char Verbose
CGRAPH_API int agnnodes(Agraph_t *g)
void init_UF_size(graph_t *g)
Agnode_t * node(Agraph_t *g, char *name)
int rank2(graph_t *g, int balance, int maxiter, int search_size)
void reverse_edge(edge_t *e)
CGRAPH_API Agedge_t * agnxtin(Agraph_t *g, Agedge_t *e)
int countDummyNodes(graph_t *g)
CGRAPH_API int agnedges(Agraph_t *g)
CGRAPH_API Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
struct nodeGroup_t nodeGroup_t
void rank3(graph_t *g, aspect_t *asp)
aspect_t * setAspect(Agraph_t *g, aspect_t *adata)