ginger/gim/NOTES

72 lines
3.9 KiB
Plaintext
Raw Normal View History

Notes from reading https://www.graphviz.org/Documentation/TSE93.pdf, which
describes an algorithm for drawing an acyclic graph in basically the way which I
want.
This document assumes the primary flow of drawing is downward, and secondary is
right.
For all of this it might be easier to not even consider edge values yet, as
those could be done by converting them into vertices themselves after the
cyclic-edge-reversal and then converting them back later.
Drawing the graph is a four step process:
1) Rank nodes in the Y axis
- Graph must be acyclic.
- This can be accomplished by strategically reversing edges which cause
a cycle, and then reversing them back as a post-processing step.
- Edges can be found by:
- walking out from a particular node depth-first from some arbitrary
node.
- As you do so you assign a rank based on depth to each node you
encounter.
- If any edge is destined for a node which has already been seen you
look at the ranks of the source and destination, and if the source
is _greater_ than the destination you reverse the edge's
direction.
- I think that algorithm only works if there's a source/sink? might have
to be modified, or the walk must traverse both to & from.
- Assign all edges a weight, default 1, but possibly externally assigned to
be greater.
- Take a "feasible" minimum spanning tree (MST) of the graph
- Feasibility is defined as each edge being "tight", meaning, once you
rank each node by their distance from the root and define the length
of an edge as the difference of rank of its head and tail, that each
tree edge will have a length of 1.
- Perform the following on the MST:
- For each edge of the graph assign the cut value
- If you were to remove any edge of an MST it would create two
separate MSTs. The side the edge was pointing from is the tail,
the side it was pointing to is the head.
- Looking at edges _in the original graph_, sum the weights of all
edges directed from the tail to the head (including the one
removed) and subtract from that the sum of the weights of the
edges directed from the head to the tail. This is the cut value.
- "...note that the cut values can be computed using information
local to an edge if the search is ordered from the leaves of the
feasible tree inward. It is trivial to compute the cut value of a
tree edge with one of its endpoints a leaf in the tree, since
either the head or the tail component consists of a single node.
Now, assuming the cut values are known for all the edges incident
on a given node except one, the cut value of the remaining edge is
the sum of the known cut values plus a term dependent only on the
edges incident to the given node."
- Take an edge with a negative cut value and remove it. Find the graph
edge between the remaining head and tail MSTs with the smallest
"slack" (distance in rank between its ends) and add that edge to the
MST to make it connected again.
- Repeat until there are no negative cut values.
- Apparently searching "cyclically" through the negative edges, rather
than iterating from the start each time, is worthwhile.
- Normalize the MST by assigning the root node the rank of 0 (and so on), if
it changed.
- All edges in the MST are of length 1, and the rest can be inferred from
that.
- To reduce crowding, nodes with equal in/out edge weights and which could
be placed on multiple rankings are moved to the ranking with the fewest
nodes.
2) Order nodes in the X axis to reduce edge crossings
3) Compute node coordinates
4) Determine edge splines