Graphviz

Graphviz is a very hand graph vizualization tool. And since every problem is a graph problem in disguise, it's a handy tool to have in your arsenal. I will discuss the Dot Graphviz renderer (there are many)

Basic Syntax

The basic syntax is fairly simple, but can be highly configurable. Graphs are defined by listing their edges.

graph example01 {
    NODE_1 -- NODE_2;
    NODE_1 -- NODE_3;
    NODE_2 -- NODE_3;
}
Define a graph by listing its edges

Despite the simplicity, and the generally good defaults, here are some common tweaks that you might need.

Top-to-bottom and left-to-right layouts

By default, graphs are layed out top-to-bottom in the order nodes are specified. But you can add rankdir=LR grapha ttribute to force a left-to-right layout. This can make the graph more legible if you add edge labels.

graph example02 {
        rankdir=LR;

        NODE_1 -- NODE_2;
        NODE_1 -- NODE_3;
    }

You do not have control of node placement. The goal here isn't to produce a perfect diagram a la TikZ, it's to produce a decent diagram that gets the point across with minimal effort.

Notice that the nodes were split into two ranks (columns).

Directed graphs

digraph example03 {
    NODE_1 -> NODE_2;
    NODE_1 -> NODE_3;
    NODE_3 -> NODE_2;
}

Notice here that there are three ranks.

Increasing distance between nodes

You can use the nodesep and ranksep graph parameters to set the distance between nodes and ranks respectively. Units are in inches.

digraph example04 {
    ranksep=0.5;

    NODE_1 -> NODE_3;
    NODE_2 -> NODE_3;
}

Note that the ranksep is the vertical distance between the horizontal ranks.

digraph example05 {
    ranksep=0.75;

    NODE_1 -> NODE_3;
    NODE_2 -> NODE_3;
}
digraph example06 {
    nodesep=1;

    NODE_1 -> NODE_3;
    NODE_2 -> NODE_3;
}

Notice that nodesep also applies to the distance between ranks, but that this distance is measured from node to node.

Node shape

Perhaps ovals aren't your thing. See https://graphviz.org/doc/info/shapes.html for the different node shapes you can use. Note that record shapes are special, and are how you can build things like tables or arrays.

digraph example07 {
    node [shape=box] NODE_2;
    // The node keyword is optional.
    NODE_1 [shape=circle];
    // Sets default node shape.
    node [shape=square];

    NODE_1 -> NODE_2 -> NODE_3;
    NODE_1 -> NODE_4;
}

Node and edge labels

A very common thing you'll want to do is to add labels to your nodes and edges

digraph example08 {
    rankdir=LR;
    ranksep=0.75;
    nodesep=0.5;

    node [shape=point] START;
    node [shape=doublecircle] INITIAL;
    node [shape=circle];

    START -> INITIAL [label="startup"];
    INITIAL -> STATE_1 [label="event a\naction 1"];
    INITIAL -> STATE_2 [label="event b\naction 2"];
    STATE_1 -> STATE_1 [label="event c"];
}

Edge and multi-edge colors

digraph example09 {
    rankdir=LR;

    node [shape=point] START;
    node [shape=doublecircle] INITIAL;
    node [shape=circle];

    START -> INITIAL;

    INITIAL -> STATE_1;
    STATE_1 -> STATE_2 [color=blue];
    STATE_1 -> STATE_3 [style=dashed];
    // quotes necessary when specifying multiple colors.
    STATE_2 -> STATE_3 [color="black:red:black"];
    STATE_3 -> STATE_3;
}

Subgraphs

digraph example10 {
    rankdir=LR;

    subgraph cluster_1 {
        node [style=box];
        color=red;
        label="process 1";
        a1 -> a2 -> a3;
    }
    subgraph cluster_2 {
        node [style=dashed];
        label="process 2";
        b1 -> b2;
    }
    // Shorthand for start -> a1; start -> b1;
    start -> {a1, b1};
    {a3, b2} -> end;
}

Live X11 Preview

This is very handy for prototyping Graphviz diagrams. Use dot -Tx11 <filename> to run the live preview in an X11 window. The preview is regenerated every time the given file is written to. Note that the zooming is a bit touchy; use <ctrl-scroll> to zoom to/from the cursor.

Generating PNG/SVG Output

Use dot -Tsvg -o <output> <input> . Or you can use -Tpng if you really want to.

Embedding Graphviz in Doxygen Documentation

This is one of the things that makes Graphviz really quite powerful as a design tool. You can embed your design directly in the source code where the desgin is implemented. This makes it easier to update the diagrams when you refactor (something that should be caught in code review).

Include the Graphviz code wrapped between @dot and @enddot Doxygen tags. You can also use @dotfile to read the diagram from a *.dot file saved in the DOTFILES_DIRS configuration variable.