Graphviz for very large state machine - graphviz

I have a state machine that, despite having very few node (8), has a lot of connections.
How can I draw it using graphviz in a presentable way.
Currently I have this. The problem is that this is not presentable in any way. The arrows have an awkward shape, the states are all over the place...
digraph finite_state_machine {
rankdir="TB";
size="8,5"
{rank = same; 1 2}
{rank = same; 3 4}
{rank = same; 7 8}
1->7[label="<p,a>"];
1->5[label="<p,a>"];
1->3[label="<p,a>"];
1->1[label="<p,a>"];
2->7[label="<~(p),a>"];
2->5[label="<~(p),a>"];
2->3[label="<~(p),a>"];
2->1[label="<~(p),a>"];
3->7[label="<p,a>"];
3->5[label="<p,a>"];
3->3[label="<p,a>"];
3->1[label="<p,a>"];
4->7[label="<~(p),a>"];
4->5[label="<~(p),a>"];
4->3[label="<~(p),a>"];
4->1[label="<~(p),a>"];
5->8[label="<p,a>"];
5->7[label="<p,a>"];
5->6[label="<p,a>"];
5->5[label="<p,a>"];
5->4[label="<p,a>"];
5->2[label="<p,a>"];
6->8[label="<~(p),a>"];
6->7[label="<~(p),a>"];
6->6[label="<~(p),a>"];
6->5[label="<~(p),a>"];
6->4[label="<~(p),a>"];
6->2[label="<~(p),a>"];
7->8[label="<p,a>"];
7->7[label="<p,a>"];
7->6[label="<p,a>"];
7->5[label="<p,a>"];
7->4[label="<p,a>"];
7->2[label="<p,a>"];
8->8[label="<~(p),a>"];
8->7[label="<~(p),a>"];
8->6[label="<~(p),a>"];
8->5[label="<~(p),a>"];
8->4[label="<~(p),a>"];
8->2[label="<~(p),a>"];
}
Which yields this
Is there any way I can make the automata more presentable?

Some times it help setting e.g. minlen=2 on edges, and decorate=1 make it more obvious where labels belong, try adding the following:
edge[decorate=1 minlen=2]
node[width=2 height=2 fontsize=50]
you can have a bit control of arrow tails and heads using compass so you might like the following better:
1:n->1:n
7:s->7:s
8:s->8:s
instead of:
1->1
7->7
8->8
since you only have 2 kind of edge labels It might also help to have a edge color depending on the label
I sugest you try these kind of things out on http://viz-js.com/

Related

Sepetate 2 glutinous arrow header in graphviz

Hi my arrow like following:
https://i.imgur.com/EJNtfc3.png
Arrow on the red marked is glutinous.
How do I divide it?
add code
https://www.codepile.net/pile/XKvOwL3A
In your situation fastest fix would be to add nodesep = 0.15 graph attribute (right after digraph { statement). This attribute adjusts the minimal distance between the nodes in one rank. This results in:
Also you may play with headport and tailport attributes, as I suggested in the comment. Shortcut for them is to add a colon after node when you are defining edge.
If you replace TR_Client_Data -> idle with TR_Client_Data -> idle:e you will get this result:
Edges are crossed, but they are apart.
Also I've noticed that you define node attributes in a wrong way: keyword node defines global attributes for all nodes in the graph (or subgraph). If you want to specify attributes for a single node, place them after node definition.
e.g.
WRONG:
node [
shape = point,
fontsize = 12
] start_point;
CORRECT:
start_point [
shape = point,
fontsize = 12
];

Graphviz: Putting a Caption on a Node In Addition to a Label

In my Graphviz graph (written in DOT), I want each node to have a label, but in addition to that, I want some nodes to have a small caption denoting some other unique value for that node. For example, if this were for a history diagram, a node's label might be something like "Birth of George Washington" and the caption might read "See also: American Revolution."
This is fairly flexible, so the caption doesn't necessarily need to be inside the node, but I do need some other way of putting text that clearly isn't part of the label (e.g. is a different size, possibly a different color) and is in a different location but is still clearly a part of the node.
Is there any way to do this?
To place captions outside the node, you may use xlabel:
digraph g {
forcelabels=true;
a [label="Birth of George Washington", xlabel="See also: American Revolution"];
b [label="Main label", xlabel="Additional caption"];
a-> b;
}
forcelabels=true makes sure no xlabel is omitted.
A second option is to use HTML-like labels:
digraph g {
a[label=<Birth of George Washington<BR />
<FONT POINT-SIZE="10">See also: American Revolution</FONT>>];
}

how can I adjust direction of edge in dot diagram?

Before asking, I tried to search the answer for my question, buf I couldn't find.
My question is about changing edge direction in dot diagram. Rankdir is 'LR', but in certain part of graph, I want to use 'TB'. Let me give an example.
digraph G {
rankdir=LR;
size="7,5";
browser->ui_thread;
browser->db_thread;
browser->webkit_thread;
browser->cache_thread;
browser->file_thread;
browser->io_thread;
io_thread[style=filled];
cache_thread[style=filled];
ui_thread->thread[label=inherit];
ui_thread->messageloop[style=dotted];
db_thread->messageloop[style=dotted];
webkit_thread->messageloop[style=dotted];
cache_thread->messageloop[style=dotted];
file_thread->messageloop[style=dotted];
io_thread->messageloop[style=dotted];
}
it gives out graph like this
But, this is not what I want.
I want the following image. "thread" is above "ui_thread" vertically.
You may think it can be solved easily using "rankdir=same" with "thread" and "ui_thread".
I sure tried this already. but I failed. "thread" is always below "ui_thread".
thanks,
Unfortunately, graph direction can only be specified once, and the whole graph stays in that direction. In this situation, you can usually get the desired effect with a combination of constraint=false and invisible edges to force some ordering.
This code will produce your second image:
digraph G {
rankdir=LR;
size="7,5";
browser->thread[style=invis];
browser->ui_thread;
browser->db_thread;
browser->webkit_thread;
browser->cache_thread;
browser->file_thread;
browser->io_thread;
io_thread[style=filled];
cache_thread[style=filled];
ui_thread->thread[label=inherit constraint=false];
ui_thread->messageloop[style=dotted];
db_thread->messageloop[style=dotted];
webkit_thread->messageloop[style=dotted];
cache_thread->messageloop[style=dotted];
file_thread->messageloop[style=dotted];
io_thread->messageloop[style=dotted];
}

Graphviz (DOT) Captions

I need to print a large number of graphs using Graphviz DOT. To distinguish which input each graph corresponds to, I want to also have a caption for each graph. Is there anyway to embed this into the DOT representation of the graphs.
You can use label to add a caption to the graph.
Example:
digraph {
A -> B;
label="Graph";
labelloc=top;
labeljust=left;
}
labelloc and labeljust can be used to determine top/bottom and left/right position of the graph label.
All the details and other attributes that can be used to modify the label (font etc) in the graphviz attribute reference.
Tip: Define the graph label end of your dot file, otherwise subgraphs will inherit those properties.
Graph's can have attributes just like nodes and edges do:
digraph {
graph [label="The Tale of Two Cities", labelloc=t, fontsize=30];
node [color=blue];
rankdir = LR;
London -> Paris;
Paris -> London;
}
That dot file produces this graph.
If you are looking for a way to add a caption to a Graph object of graphviz in python. Then the following code can help:
from graphviz import Graph
dot = Graph()
dot.node('1','1')
dot.node('2','2')
dot.edge('1','2', label="link")
dot.attr(label="My caption")
dot.attr(fontsize='25')
dot.render(view=True)
Output:

record nodes and rankdir in graphviz

When I changed the rankdir of my graph from LR to TD, my record nodes also changed their layout direction so they no longer look like a 'record'. I tried applying a separate rankdir to the nodes, but this had no effect.
How does one keep the record nodes with the correct layout?
digraph sample {
graph [rankdir=TD];
node [shape=record];
A [label="ShouldBeTop | ShouldBeBottom"];
B [label="Top | Bottom"];
A -> B;
}
Taking into account that rankdir effectively replaces the notion of "top" and "bottom" for the given graph, that's not surprising.
I am afraid that there is no easy remedy for this, save hacking the source (and that would not be easy at all). You can surround your labels in "{}" with some kind of mass search-replace solution to get the requested effect:
digraph sample { graph [rankdir=TD]; node [shape=record];
A [label="{ShouldBeTop | ShouldBeBottom}"];
B [label="{Top | Bottom}"]; A -> B;
}
You can use html table like labels instead of records. IIRC the table based labels do not rotate with the rank direction. See http://www.graphviz.org/doc/info/shapes.html#html

Resources