Thursday, November 17, 2011

Playing around with graphviz

In my data structures class we've been talking about binary trees. One of the example programs used a stack and space counting to display the tree to the console in a very fortran way. I mentioned to my instructor that using dot would be much simpler, just generate the dot file, hand it off to graphviz, and read the svg/png when you've finished.

Initial experiments were unsatisfying, since a node with only one child tends to have a vertical bar straight down, giving no indication which link (left or right) it is attached to. So I threw some color in, with blue indicating a left/less than link, and red indicating a right/greater than link. This was simple and easy to see. I couldn't shake the suspicion that there was a way to push the links to the right sides, and started thinking about making tables within the records with named ports, but this seemed to be more trouble than it's worth, and I didn't understand why the example code worked, but my hand edited version went unrecognized. Then I remembered reading that invisible edges to invisible nodes will make graphviz count more nodes at a level than there are. Observe the 'balanced' image:



and the unbalanced original:


Honestly, I prefer the density of the original to the strange, warped feeling of the corrected version. In many cases, the links still point downward (especially on outer branches pointing in), but some sense of angular proportion can be felt. With the original, most of the nodes at any given depth are bunched together, giving a sense of feel for the completeness of that level, while the corrected/balanced image has (artificially inserted) gaps to create angular distinctions between left and right, which makes seeing across more difficult.

A rather weird twist, I tried only inserting dummy nodes on the left and leaving the right alone to see what might happen. This is from a different data set, so the overall shape is different, but see how wrong this became:

2 comments:

Dan said...

So I actually modified this an added it as a routine in AVL and Red Black trees to show the progressive insertion/rotation behavior. Since I was asked to manually draw the insertion diagrams in office software, I found that having a few dozen png/svg files and feeding them to latex was easy to do automatically, and involved very little mouse-herding. For red black trees, I had to add some color info to the nodes, while for a general BST or AVL tree, I only needed edges (with optional invisible nodes to fill out the rows for spacing).

Dan said...

I forgot to say that a fair amount of inspiration for this came from the use of neato for graphs in Conrad Barski's Land of Lisp. He certainly made generation of simple graphs a solvable problem, and the domain shifted easily to a few helper functions in C++ from an admittedly lisp oriented approach. +1 for reading multiple languages, there really is great inspiration out there in the strangest places.