From c15f3d7edbb5ebf59e512d991ddfae2c534c3371 Mon Sep 17 00:00:00 2001 From: Github Actions Date: Mon, 8 Apr 2024 20:02:26 +0000 Subject: [PATCH] Update docs from rizinorg/cutter Original Commit: bce9fe7732890934f750d9d91f4093983dbb5830 Update GraphGridLayout Documentation (#3325) --- docs/api/widgets/classGraphGridLayout.html | 77 ++++++++++++---------- docs/searchindex.js | 2 +- 2 files changed, 43 insertions(+), 36 deletions(-) diff --git a/docs/api/widgets/classGraphGridLayout.html b/docs/api/widgets/classGraphGridLayout.html index fee02b81..fa6fbdf7 100644 --- a/docs/api/widgets/classGraphGridLayout.html +++ b/docs/api/widgets/classGraphGridLayout.html @@ -60,43 +60,43 @@

GraphGridLayout -
  • Vertex, node, block - read description of graph for definition. Within this text vertex and node are used interchangeably with block due to code being written for visualizing basic block control flow graph.

  • -
  • edge - read description of graph for definition for precise definition.

  • -
  • DAG - directed acyclic graph, graph using directed edges which doesn’t have cycles. DAG may contain loops if following them would require going in both directions of edges. Example 1->2 1->3 3->2 is a DAG, 2->1 1->3 3->2 isn’t a DAG.

  • +
  • Vertex, node, block - see the definition of graph. Within this text vertex/node/block are used interchangeably due to the code being purposed for visualizing basic block control flow graph.

  • +
  • edge - see the definition of graph.

  • +
  • DAG - directed acyclic graph, a graph using directed edges which doesn’t have cycles. A DAG may contain loops if following them would require going in both directions of edges. Example 1->2 1->3 3->2 is a DAG, 2->1 1->3 3->2 isn’t a DAG.

  • DFS - depth first search, a graph traversal algorithm

  • -
  • toposort - topological sorting, process of ordering a DAG vertices that all edges go from vertices earlier in the toposort order to vertices later in toposort order. There are multiple algorithms for implementing toposort operation. Single DAG can have multiple valid topological orderings, a toposort algorithm can be designed to prioritize a specific one from all valid toposort orders. Example: for graph 1->4, 2->1, 2->3, 3->4 valid topological orders are [2,1,3,4] and [2,3,1,4].

  • +
  • toposort - topological sorting, the process of ordering a DAG vertices that results in all edges going from vertices earlier in the toposort order to vertices later in toposort order. There are multiple algorithms implementing toposort. A single DAG can have multiple valid topological orderings, a toposort algorithm can be designed to prioritize a specific one from all valid toposort orders. Example: for graph 1->4, 2->1, 2->3, 3->4 valid topological orders are [2,1,3,4] and [2,3,1,4].

  • -

    High level structure of the algorithm

    +

    High level algorithm structure

      -
    1. select subset of edges that form a DAG (remove cycles)

    2. -
    3. toposort the DAG

    4. -
    5. choose a subset of edges that form a tree and assign layers

    6. -
    7. assign node positions within grid using tree structure, child subtrees are placed side by side with parent on top

    8. -
    9. perform edge routing

    10. -
    11. calculate column and row pixel positions based on node sizes and amount edges between the rows

    12. -
    13. [optional] layout compacting

    14. +
    15. Select a subset of edges that form a DAG (remove cycles)

    16. +
    17. Toposort the DAG

    18. +
    19. Choose a subset of edges that form a tree and assign layers

    20. +
    21. Assign node positions within grid using tree structure, child subtrees are placed side by side with parent on top

    22. +
    23. Perform edge routing

    24. +
    25. Calculate column and row pixel positions based on node sizes and amount edges between the rows

    26. +
    27. [optional] Layout compacting

    -

    Contrary to many other layered graph drawing algorithm this implementation doesn’t perform node reordering to minimize edge crossing. This simplifies implementation, and preserves original control flow structure for conditional jumps ( true jump on one side, false jump on other). Due to most of control flow being result of structured programming constructs like if/then/else and loops, resulting layout is usually readable without node reordering within layers.

    -

    Description of grid.

    -

    To simplify the layout algorithm initial steps assume that all nodes have the same size and edges are zero width. After placing the nodes and routing the edges it is known which nodes are in in which row and column, how many edges are between each pair of rows. Using this information positions are converted from the grid cells to pixel coordinates. Routing 0 width edges between rows can also be interpreted as every second row and column being reserved for edges. The row numbers in code are using first interpretation. To allow better centering of nodes one above other each node is 2 columns wide and 1 row high.

    +

    Contrary to many other layered graph-drawing algorithms this implementation doesn’t perform node reordering to minimize edge crossing. This simplifies the implementation, and preserves the original control-flow structure for conditional jumps ( true jump on one side, false jump on other). Due to most of the control flow resulting from structured programming constructs like if/then/else and loops, the resulting layout is usually readable without node reordering within layers.

    +

    Grid

    +

    To simplify the layout algorithm, its initial steps assume that all nodes have the same size and that edges are zero-width. After nodes placement and edges rounting, the row/column of nodes is known as well as the amount of edges between each pair of rows. Using this information, positions are converted from grid cells to pixel coordinates. Routing zero-width edges between rows can also be interpreted as every second row and column being reserved for edges. The row numbers in code are using the first interpretation. To allow better centering of nodes one above other, each node is 2 columns wide and 1 row high.

    ../../_images/graph_grid.svg

    1-2 Cycle removal and toposort

    -

    Cycle removal and toposort are done at the same time during single DFS traversal. In case entrypoint is part of a loop DFS started from entrypoint. This ensures that entrypoint is at the top of resulting layout if possible. Resulting toposort order is used in many of the following layout steps that require calculating some property of a vertex based on child property or the other way around. Using toposort order such operations can be implemented iteration through array in either forward or reverse direction. To prevent running out of stack memory when processing large graphs DFS is implemented non-recursively.

    +

    Cycle removal and toposort are done in a single DFS traversal. In case the entrypoint is part of a loop, the DFS starts from the entrypoint. This ensures that the entrypoint is at the top of resulting layout, if possible. The resulting toposort order is used in many of the following layout steps that require calculating some property of a vertex based on a child property or the other way around. Using toposort order, such operations can be implemented by array iteration in either forward/backward direction. To prevent running out of stack memory when processing large graphs, DFS is implemented non-recursively.

    Row assignment

    -

    Rows are assigned in toposort order from top to bottom, with nodes row being max(predecessor.row)+1. This ensures that loop edges are only ones going from deeper levels to previous layers.

    -

    To further simply node placement a subset of edges is selected which forms a tree. This turns DAG drawing problem into a tree drawing problem. For each node in level n following nodes which have level exactly n+1 are greedily assigned as child nodes in tree. If a node already has parent assigned then corresponding edge is not part of tree.

    -

    Node position assignment

    -

    Since the graph has been reduced to a tree, node placement is more or less putting subtrees side by side with parent on top. There is some room for interpretation what exactly side by side means and where exactly on top is. Drawing the graph either too dense or too big may make it less readable so there are configuration options which allow choosing these things resulting in more or less dense layout.

    -

    Once the subtrees are placed side by side. Parent node can be placed either in the middle of horizontal bounds or in the middle of direct children. First option results in narrower layout and more vertical columns. Second option results in nodes being more spread out which may help seeing where each edge goes.

    -

    In more compact mode two subtrees are placed side by side taking into account their shape. In wider mode bounding box of shorter subtree is used instead of exact shape. This gives slightly sparse layout without it being too wide.

    +

    Rows are assigned in toposort order from top to bottom, with nodes row being max(predecessor.row)+1. This ensures that loop back-edges are the only edges going from lower to higher layers.

    +

    To further simply node placement, a subset of edges is selected which forms a tree. This turns a DAG drawing problem into a tree drawing problem. For each node in level n the following nodes with level exactly n+1 are greedily assigned as child nodes in the tree. If a node already has a parent assigned then the corresponding edge is not part of the tree.

    +

    Node placement

    +

    Since the graph has been reduced to a tree, node placement is more or less putting subtrees side by side with parent on top. There is some room for interpretation as to what exactly ‘side by side’ means and where exactly ‘on top’ is: drawing the graph either too dense or too sparse may make it less readable, so there are configuration options which allow choosing these things resulting in more or less dense layout.

    +

    Once the subtrees are placed side by side, the parent node can be placed either in the middle of the horizontal bounds or in the middle of its direct children. The first option results in narrower layout and more vertical columns, while the second option results in more spread out layout which may help seeing where each edge goes.

    +

    In compact mode two subtrees are placed side by side accounting for their shape. In wider mode the bounding box of the shorter subtree is used instead of its exact shape. This gives slightly sparser layout without being too wide.

    ../../_images/graph_parent_placement.svg

    Edge routing

    -

    Edge routing can be split into: main column selection, rough routing, segment offset calculation.

    -

    Transition from source to target row is done using single vertical segment. This is called main column.

    -

    A sweep line is used for computing main columns: Blocks and edges are processed as events top to bottom based off their row (max(start row, end row) for edges). Blocked columns are tracked in a tree structure which allows searching nearest column with at least last N rows empty. The column of the starting block is favored for the main column, otherwise the target block’s column is chosen if it is not blocked. If both the source and target columns are blocked, nearest unblocked column is chosen. An empty column can always be found, in the worst case there are empty columns at the sides of drawing. If two columns are equally close, the tie is broken based on whether the edge is a true or false branch. In case of upward edges it is allowed to choose a column on the outside which is slightly further than nearest empty to reduce the chance of producing tilted figure 8 shaped crossing between two blocks.

    -

    Rough routing creates the path of edge using up to 5 segments using grid coordinates. Due to nodes being placed in a grid. Horizontal segments of edges can’t intersect with any nodes. The path for edges is chosen so that it consists of at most 5 segments, typically resulting in sideways U shape or square Z shape.