Erratum: Fast and Simple Horizontal Coordinate Assignment
EErratum:Fast and Simple Horizontal Coordinate Assignment
Ulrik Brandes , [0000 − − − , Julian Walter , and JohannesZink , [0000 − − − X ] ETH Z¨urich, Z¨urich, Switzerland. [email protected] Universit¨at W¨urzburg, W¨urzburg, Germany. [email protected]
Abstract.
We point out two flaws in the algorithm of Brandes andK¨opf (Proc. GD 2001), which is often used for the horizontal coordinateassignment in Sugiyama’s framework for layered layouts. One of them hasbeen noted and fixed multiple times, the other has not been documentedbefore and requires a non-trivial adaptation. On the bright side, neitherrunning time nor extensions of the algorithm are affected adversely.
Keywords:
Sugiyama layout · Layered graph drawing · Horizontal com-paction.
Horizontal coordinate assignment is the final phase of Sugiyama’s frameworkfor drawing directed graphs [6,3]. By that point, the original graph has beentransformed into a directed acyclic graph with its vertices assigned to a sequenceof layers, and ordered within these layers. Moreover, the layer assignment isproper, i.e., edges spanning layers are subdivided by dummy vertices so that twovertices are adjacent only if they are assigned to neighboring layers.Brandes and K¨opf [2] proposed a simple algorithm to determine x -coordinatesfor the vertices such that their order is preserved and the distance between eachtwo vertices is at least some δ >
0. The algorithm runs in time linear in the sizeof the input and is implemented and taught widely.The original publication, however, contains two mistakes. The first is wellknown and easy to fix. The other, however, is not commonly known, less straight-forward, and, to the best of our knowledge, no solution has been proposed.The purpose of this short paper is to identify clearly where these two mistakesoccur, and to provide suitable corrections. Our proposed corrections do not alterthe behavior of the algorithm and do not clash with extensions that have beenproposed to accommodate, for instance, vertices of varying size, ports, and otherconstraints [1,5].
In this section we sketch the algorithm of Brandes and K¨opf. Two mistakes,both occurring in the same subroutine, are identified and corrected in the nextsection. a r X i v : . [ c s . D S ] A ug U. Brandes, J. Walter and J. Zink
In the horizontal coordinate assignment problem, we are given a layereddirected acyclic graph G = ( V (cid:93) B, E ; L ), i.e., a directed acyclic graph G =( V ∪ B, E ) with two types of vertices (original vertices and potential bend pointsof edges) and a sequence of layers L = ( L , . . . , L h ) that forms an orderedpartition of V ∪ B . The layering is required to be proper, i.e., adjacent verticesare in neighboring layers. Moreover, the vertices are ordered within each layer L i = { v ( i )1 , . . . , v ( i ) | L i | } , where v ( i ) k denotes the k th vertex in the i th layer. Thus,the topology of the drawing has already been fixed, and the horizontal coordinateassignment algorithm is now to determine the shape and the final metrics. L L L L L L L v (2)1 v (1)1 v (4)1 x = 0 Fig. 1.
Example illustrating the various definitions. The vertices in V ∪ B togetherwith the alignment (black) and predecessor (orange) relations form a directed graph,the strongly connected components of which are the blocks (light blue rectangles).Blocks therefore form a DAG and are assigned to a class (green polygon) defined bythe highest sink (labeled vertex) they can reach. The algorithm of Brandes and K¨opf consists of the following three steps, thefirst two of which are repeated four times, once for each combination of verticaland horizontal orientations. We describe the top-to-bottom, left-to-right case inwhich vertices are left-aligned conditional on upper neighbors; the other threecases are symmetric. Figure 1 illustrates the subsequent definitions.1.
Vertical alignment:
Every vertex v ∈ V ∪ B is assigned a vertex, align[ v ],that can be v itself or otherwise it is either a neighbor on the next lower levelor the uppermost vertex when tracing back these alignment pointers. Thispartitions the vertex set into singly-linked (possibly singleton) cycles called blocks , where the topmost vertex in a block is called the root . All vertices ina block ultimately receive the same x -coordinate in order to straighten long rratum: Fast and Simple Horizontal Coordinate Assignment 3 edges (by aligning subdivision vertices in B ) and to reduce edge lengths (byaligning vertices in V with a median neighbor in the layer above).2. Horizontal compaction:
Next, vertices are aligned to the left. By adding anedge between every vertex and its predecessor (left neighbor), if present, weobtain a directed acyclic graph of blocks. The sinks of this DAG are blockswhose roots are leftmost in their layer and are hence ordered vertically.Let the sink of a vertex be the highest sink reachable from any vertex inits block by the predecessor and alignment edges. All vertices and blockswith the same highest sink form a class . In Figure 1, there are three sinksdefining a class, namely v (1)1 , v (2)1 , and v (4)1 . The vertices in a class have aunique minimum x -coordinate relative to their common sink, and it can beobtained from longest-path layering. We say two classes are neighboring eachother if they contain vertices on the same layer. If a class is not neighboringanother class with a higher sink, its own sink is placed at x -coordinate zero.In Figure 1, this is the case for the class with sink v (1)1 . Otherwise it is placedas close to higher classes as possible. In Figure 1, this is the case for the twoother classes.3. Balancing:
The four x -coordinates per vertex obtained from repeating theprevious steps with different orientations are combined into one by align-ing the four resulting drawings and taking the average of the two mediancoordinates per vertex.Both problems occur in the horizontal compaction step. We therefore reproducethe pseudo-code of Alg. 3 from the original publication. It does not require anyspecial data structures other than the vertex arrays listed in Tab. 1. Table 1.
All auxiliary data is stored in vertex arrays. v ( i ) k k th vertex in i th layer array content pos[ v ] rank in layer, i.e., pos[ v ( i ) k ] = k pred[ v ] preceding vertex in same layer, i.e., pred[ v ( i ) k ] = v ( i ) k − align[ v ] vertex below in same block (or root for lowest)root[ v ] highest vertex in same blocksink[ v ] if v is a root: highest leftmost root, defining the classshift[ v ] if v is a sink: offset by which class is to be shifted x [ v ] horizontal coordinate (relative to sink, later absolute) The problematic lines of pseudo-code concern the computation of absolute co-ordinates and the accumulation of shift values for classes. They are marked (S)and (A) in Alg. 3.
U. Brandes, J. Walter and J. Zink
Alg. 3:
Horizontal compaction function place block( v ) beginif x [ v ] undefined then x [ v ] ← w ← v repeatif pos [ w ] > then u ← root[pred[ w ]]place block( u ) if sink [ v ] = v then sink[ v ] ← sink[ u ] if sink [ v ] (cid:54) = sink [ u ] then (A) shift[sink[ u ]] ← min { shift[sink[ u ]] , x [ v ] − x [ u ] − δ } else x [ v ] ← max { x [ v ] , x [ u ] + δ } w ← align[ w ] until w = v initialize sink[ v ] ← v , v ∈ V ∪ B initialize shift[ v ] ← ∞ , v ∈ V ∪ B initialize x [ v ] to be undefined, v ∈ V ∪ B // root coordinates relative to sink foreach v ∈ V ∪ B doif root [ v ] = v then place block( v ) // absolute coordinates foreach v ∈ V ∪ B do x [ v ] ← x [root[ v ]] (S) if shift [ sink [ root [ v ]]] < ∞ then x [ v ] ← x [ v ] + shift[sink[root[ v ]]] Double shifting.
The easier problem manifests itself in line (S) of Alg. 3. Todetermine absolute coordinates, we want to combine, for every vertex, the rel-ative coordinate of its block with respect to the sink of its class (stored at theroot), with the offset of the entire class (stored at the sink). The way Alg. 3 isformulated, offsets are actually added twice for vertices whose root has alreadybeen shifted to its final x -coordinate.Multiple implementors have noted and fixed the problem in different ways.The correction we provide in Alg. 3a involves aligning blocks in the recursivesubroutine place block as soon as the relative coordinate of the root with respectto the sink has been determined. In this way, block alignment and shifting areseparated and only offsets have to be added to every vertex in the last line ofAlg. 3b. Given the name of the subroutine, this should have been the procedureall along. And to simplify later steps, we also assign the sink to vertices, not justroots. rratum: Fast and Simple Horizontal Coordinate Assignment 5 Alg. 3a:
Placing a block (not just the root) function place block( v ) if x [ v ] undefined then x [ v ] ← w ← v repeatif pos [ w ] > then u ← root[pred[ w ]]place block( u ) if sink [ v ] = v then sink[ v ] ← sink[ u ] if sink [ v ] = sink [ u ] then x [ v ] ← max { x [ v ] , x [ u ] + δ } // class offsets (shift of sinks) are calculated later w ← align[ w ] until w = v // align the whole block while align [ w ] (cid:54) = v do w ← align[ w ] x [ w ] ← x [ v ]sink[ w ] ← sink[ v ] Shift accumulation.
Problem (A) is a serious flaw that has not been documentedbefore. It is not clear how often it has actually resulted in visually notableproblems, but it is easy to craft instances in which it becomes severe.During compaction, shift values are determined for preceding classes relativeto the current class. The implicit assumption in line (A) is, however, that thecurrent class is not shifted itself. As a consequence, shift values are not accumu-lated along critical paths in the DAG of classes. It is not sufficient to considerthe shift value of sink[ v ] in line (A) because it may not be in its final state, yet.The correction we propose in Alg. 3b therefore separates the determination ofshift values from the placement of blocks relative to the sink of their class.A high-level solution is to construct the DAG of classes and perform an-other longest-path layering, this time with respect to the sources in the DAG,by placing each class as close as possible to its right neighbors. The followinglemma implies that classes are stacked diagonally, top-to-bottom, right-to-left.It is therefore possible to accumulate shift values in this order without recursionor explicit representation of all preceding classes. Lemma 1.
Let v ( i ) k , v ( i ) k be two vertices in the same layer L i , ≤ i ≤ h withsink [ v ( i ) k ] = v ( h )1 and sink [ v ( i ) k ] = v ( h )1 after all blocks have been placed. If k U. Brandes, J. Walter and J. Zink Alg. 3b: Horizontal compaction initialize sink[ v ] ← v , v ∈ V ∪ B initialize shift[ v ] ← ∞ , v ∈ V ∪ B initialize x [ v ] to be undefined, v ∈ V ∪ B // coordinates relative to sink foreach v ∈ V ∪ B doif root [ v ] = v then place block( v ) // class offsets for i = 1 , . . . , h doif sink [ v ( i )1 ] = v ( i )1 thenif shift [ sink [ v ( i )1 ]] = ∞ then shift[sink[ v ( i )1 ]] ← j ← i ; k ← repeat v ← v ( j ) k while align [ v ] (cid:54) = root [ v ] do v ← align[ v ] ; j ← j + 1 if pos [ v ] > then u ← pred[ v ]shift[sink[ u ]] ← min { shift[sink[ u ]] , shift[sink[ v ]]+ x [ v ] − ( x [ u ] + δ ) } k ← pos[ v ] + 1 until k > | L j | or sink [ v ] (cid:54) = sink [ v ( j ) k ] // absolute coordinates foreach v ∈ V ∪ B do x [ v ] ← x [ v ] + shift[sink[ v ]] The monotonic ordering of classes can be utilized as follows. Instead of ensur-ing that all critical paths determining the total shifts of the classes have alreadybeen traversed by recursion (as in the placement of blocks) we can now start fromthe class with the highest sink because we know it is rightmost in each layer.For each sink, from top to bottom, we trace the lower contour of each class, andmake sure that the preceding classes are shifted such that a minimum separationguarantees they do not overlap. This is similar to the shifting of subtrees in thetree-drawing algorithm of Reingold and Tilford [4].The implementation shown in Alg. 3b traverses the layers from top to bottom.If the leftmost vertex is a sink that still has an infinite shift value, the class is notto the left of any previously processed class with a higher sink. It can thereforebe aligned without any offset, i.e., a shift value of zero. The lower contour of aclass is traced by either moving down in a block (using align[ v ]) or, if we havereached the lower end of a block pointing back at the root, moving one positionto the right. The tracing ends when there is no right neighbor or if the rightneighbor is part of a class with a higher sink.While traversing the lower contour, a predecessor u of the current vertex v , ifany, belongs to a class with a lower sink. We therefore update the shift value ofsink[ u ] to ensure minimum separation between the classes of u and v . Since we rratum: Fast and Simple Horizontal Coordinate Assignment 7 are starting with an upper bound and proceed from right to left, shift values canonly decrease, pushing classes further to the left after their initial placement. We identified and corrected two flaws in the compaction step of the well-knownhorizontal coordinate assignment algorithm of Brandes and K¨opf [2]. The cor-rections are internal to the algorithm, they do not alter running time in anysubstantial way, and are unlikely to interfere with any of the algorithm’s exten-sions.The first mistake was the result of a discrepancy between the implementationand an attempt to make the pseudo-code more readable. Others have identifiedand corrected the issue before, notably Florian Fischer (Diplom 2004, Passau)and John Julian Carstens (M.Sc. 2012, Kiel) in their theses. A frequently pro-posed correction only checks whether the vertex to be shifted is a root, andtherefore relies implicitly on the top-to-bottom processing order to ensure thatroots are shifted before the other members of a block inherit their coordinate.We believe that the correction proposed here is more appropriate.Walter and Zink recently noted and clearly identified problem (A). We devel-oped multiple corrections, but present only one that aligns most closely with theoriginal algorithm. We shortly describe one alternative version of Alg. 3b in theappendix, also because it operates more explicitly on the DAG of classes. Thesecorrections were developed without realizing that the problem had already beenidentified by Damon Lundin while working for IBM Blueworks Live (personalcommunication, 2013). He even proposed a fix that bears similarity with ourindependently developed solutions but does not work in general. Unfortunately,the conversation was only recovered while preparing this contribution. References 1. Bachmaier, C.: A radial adaptation of the sugiyama framework for visualizing hier-archical information. IEEE Transactions on Visualization and Computer Graphics (3), 583–594 (2007). https://doi.org/10.1109/TVCG.2007.10002. Brandes, U., K¨opf, B.: Fast and simple horizontal coordinate assignment. In: Mutzel,P., J¨unger, M., Leipert, S. (eds.) Proceedings of the 9th International Symposium onGraph Drawing. Lecture Notes in Computer Science, vol. 2265, pp. 31–44. Springer(2002)3. Healy, P., Nikolov, N.S.: Hierarchical drawing algorithms. In: Tamassia, R. (ed.)Handbook of Graph Drawing and Visualization, pp. 409–453. CRC Press (2013)4. Reingold, E.M., Tilford, J.S.: Tidier drawing of trees. IEEE Transactions on Soft-ware Engineering (2), 223–228 (1981)5. R¨uegg, U., Schulze, C.D., Carstens, J.J., von Hanxleden, R.: Size- and port-awarehorizontal node coordinate assignment. In: Proceedings of the 23rd InternationalSymposium on Graph Drawing and Network Visualization. Lecture Notes in Com-puter Science, vol. 9411, pp. 139–150 (2015). https://doi.org/10.1007/978-3-319-27261-0 12 U. Brandes, J. Walter and J. Zink6. Sugiyama, K., Tagawa, S., Toda, M.: Methods for visual understanding of hierarchi-cal system structures. IEEE Transactions on Systems, Man and Cybernetics (2),109–125 (1981) Appendix Since sinks (and thus class membership) have already been determined, we donot actually have to traverse contours to identify vertices whose predecessors(left neighbors) are in another class. Instead, we can iterate over all verticesand compare their sink with that of the predecessor. By storing the pairs ofneighboring vertices in different classes, we are essentially constructing the DAGof classes (including its parallel edges).An alternative approach for Alg. 3b is therefore the following. First, classadjacencies are recorded in a list neighborings[ i ] for each sink v ( i )1 . Shift valuesare then propagated down from the higher to lower classes. Note that this maynot be done during the first enumeration because all neighborings of a higherclass need to be processed before propagating values from its neighboring classes. Alg. 3b (alternative): Horizontal compaction initialize sink[ v ] ← v , v ∈ V ∪ B initialize shift[ v ] ← ∞ , v ∈ V ∪ B initialize layer[ v ( i ) ] ← i , v ( i ) ∈ V ∪ B initialize x [ v ] to be undefined, v ∈ V ∪ B // coordinates relative to sink foreach v ∈ V ∪ B doif root [ v ] = v then place block( v ) // class offsets initialize neighborings[ i ] ← ∅ , i ∈ { , . . . , h } // find all neighborings for i ← , . . . , h dofor j ← | L i | , . . . , doif sink [ v ( i ) j − ] (cid:54) = sink [ v ( i ) j ] then neighborings[layer[sink[ iv ( i ) j ]]] ← neighborings[layer[sink[ v ( i ) j ]]] ∪ { ( v ( i ) j − , v ( i ) j ) } // apply shift for all neighborings for i ← , . . . , h doif shift [ sink [ v ( i )1 ]] = ∞ then shift[sink[ v ( i )1 ]] ← for ( u, v ) ∈ neighborings [ i ] do shift[sink[ u ]] ← min { shift[sink[ u ]] , shift[sink[ v ]]+ x [ v ] − ( x [ u ] + δ ) } // absolute coordinates foreach v ∈ V ∪ B do x [ v ] ← x [ v ] + shift[sink[ vv