Hi all. Did you ever wonder what is the best and easiest way to create a beautiful Finite State machine for your documentation? Can this task be done with Latex? In this post I will show you my way of creating a Finite Stare Machine with Latex.
A finite-state machine (FSM) or finite-state automaton (FSA, plural: automata), finite automaton, or simply a state machine, is a mathematical model of computation. It is an abstract machine that can be in exactly one of a finite number of states at any given time. The FSM can change from one state to another in response to some inputs; the change from one state to another is called a transition.[1] An FSM is defined by a list of its states, its initial state, and the inputs that trigger each transition.
from Wikipedia
I found image of the state machine on the internet and tried to replicate that state machine with Latex. So, lets begin.
Include package
First, we need to include Latex library tikz (good references for tikz library are https://www.overleaf.com/learn/latex/TikZ_package and https://texample.net/tikz/examples/). We can do include that library with the next commands in our latex document.
\usepackage{tikz}
\usetikzlibrary{automata, positioning, arrows}
Config tikzpicure with tikzset
Now, we can set tikzset to our liking and I settled on next setting.
\tikzset{->, % makes the edges directed
>=stealth', % makes the arrow heads bold stealth
node distance=3cm, % specifies the minimum distance between two nodes. Change if necessary.
every state/.style={thick, fill=bln_blue!10}, % sets the properties for each ’state’ node
initial text=$\ Init\ $, % sets the text that appears on the start arrow
}
After begin document command we can initialize our Finite State Machine with begin and end tikzpicture.
\begin{tikzpicture}
...
\end{tikzpicture}
Create States with nodes
Then we can create our state states with
\begin{tikzpicture}
\node[state, initial, initial where=left] (1) {$Initial$};
\node[state, right of=1] (2) {$Pending$};
\node[state, right of=2] (3) {$Closed$};
\node[state, right of=3] (4) {$Suceess$};
\node[state, below right of=3] (5) {$Open$};
\node[state, below left of=3] (6) {$Half-Open$};
\node[state, right of=5] (7) {$Failure$};
\end{tikzpicture}
Now we have image bellow:
We can modified nodes or states a bit in order to have state name above state circle.
\begin{tikzpicture}
\node[state, initial, initial where=left] (1) {$ $};
\node[state, right of=1] (2) {$ $};
\node[state, right of=2] (3) {$ $};
\node[state, right of=3] (4) {$ $};
\node[state, below right of=3] (5) {$ $};
\node[state, below left of=3] (6) {$ $};
\node[state, right of=5] (7) {$ $};
\draw
(1) node[above= 0.5,text width=1cm] {$Initial$}
(2) node[above= 0.5,text width=1cm] {$Pending$}
(3) node[above= 0.5,text width=1cm] {$Closed$}
(4) node[above= 0.5,text width=1cm] {$Suceess$}
(5) node[above= 0.5,text width=1cm] {$Open$}
(6) node[above= 0.5,text width=1cm ] {$Half\-Open$}
(7) node[above= 0.5,text width=1cm] {$Failure$};
\end{tikzpicture}
Create relations
Next we can add relations between states:
\begin{tikzpicture}
\node[state, initial, initial where=left] (1) {$ $};
\node[state, right of=1] (2) {$ $};
\node[state, right of=2] (3) {$ $};
\node[state, right of=3] (4) {$ $};
\node[state, below right of=3] (5) {$ $};
\node[state, below left of=3] (6) {$ $};
\node[state, right of=5] (7) {$ $};
\draw
% State names
(1) node[above= 0.5,text width=1cm] {$Initial$}
(2) node[above= 0.5,text width=1cm] {$Pending$}
(3) node[above= 0.5,text width=1cm] {$Closed$}
(4) node[above= 0.5,text width=1cm] {$Suceess$}
(5) node[above= 0.5,text width=1cm] {$Open$}
(6) node[above= 0.5,text width=1cm ] {$Half\-Open$}
(7) node[above= 0.5,text width=1cm] {$Failure$}
% State relations
(1) edge[below] node[scale=0.8,text width=1.2cm]{create request} (2)
(2) edge[below] node[scale=0.8,text width=1.2cm]{execute request} (3)
(3) edge[above] node[scale=0.7]{request succeeded} (4)
(3) edge[above right = 0.1] node[scale=0.7,text width=1cm]{request failed} (5)
(5) edge[above, bend right] node[scale=0.8]{timeout reached} (6)
(6) edge[below, bend right] node[scale=0.8]{canary failed} (5)
(5) edge[below] node[scale=0.8]{timeout not reached} (7)
(6) edge[above left= 1] node[scale=0.7,text width=1.7cm]{canary succeeded} (3)
;
\end{tikzpicture}
After that we have or state machine. And it look we very nice, but how can we add some final touch.
And now we have final Latex document
\documentclass[a4paper,landscape]{report}
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}
\usepackage{tikz}
\usetikzlibrary{automata, positioning, arrows}
\definecolor{bln_blue}{HTML}{00A8FF}
\definecolor{bln_red}{HTML}{c23616}
\definecolor{bln_green}{HTML}{16A085}
\definecolor{bln_magenta}{HTML}{9B59B6}
%#8c7ae6
\tikzset{->, % makes the edges directed
>=stealth', % makes the arrow heads bold stealth
node distance=4cm, % specifies the minimum distance between two nodes. Change if necessary.
every state/.style={thick, fill=bln_blue}, % sets the properties for each ’state’ node
initial text=$\ \ $, % sets the text that appears on the start arrow
}
\pagestyle{empty}
\begin{document}
\begin{tikzpicture}
\node[state, fill=bln_magenta, initial, initial where=left] (1) {$ $};
\node[state, right of=1] (2) {$ $};
\node[state, right of=2] (3) {$ $};
\node[state, fill=bln_green, accepting, right of=3] (4) {$ $};
\node[state, below right of=3] (5) {$ $};
\node[state, below left of=3] (6) {$ $};
\node[state, fill=bln_red, accepting, right of=5] (7) {$ $};
\draw
% State names
(1) node[above= 0.5, scale=0.9] {$Initial$}
(2) node[above= 0.5, scale=0.9] {$Pending$}
(3) node[above= 0.5, scale=0.9] {$Closed$}
(4) node[above= 0.5, scale=0.9] {$Suceess$}
(5) node[below= 0.5, scale=0.9] {$Open$}
(6) node[below= 0.5,text width=1cm, scale=0.9] {$Half\-Open$}
(7) node[below= 0.5, scale=0.9] {$Failure$}
% State relations
(1) edge[above] node[scale=0.8,text width=1.2cm]{\texttt{create request}} (2)
(2) edge[above] node[scale=0.8,text width=1.2cm]{\texttt{execute request}} (3)
(3) edge[above] node[scale=0.8,text width=1.6cm]{\texttt{request succeeded}} (4)
(3) edge[above right = 0.1] node[scale=0.8,text width=1cm]{\texttt{request failed}} (5)
(5) edge[above, bend right=20] node[scale=0.8]{\texttt{timeout reached}} (6)
(6) edge[below, bend right=20] node[scale=0.8]{\texttt{canary failed}} (5)
(5) edge[below] node[scale=0.8]{\texttt{timeout not reached}} (7)
(6) edge[above left= 1] node[scale=0.8,text width=1.7cm]{\texttt{canary succeeded}} (3)
;
\end{tikzpicture}
\end{document}
Finite State machine looks something like this:
Final words
What do you think? Is this the best way to create a nice looking State machine for your documentation? I think that you can make an argument that this will be a bit faster way of creating a state machine if you already using Latex. There is maybe a more convenient way of creating state machine diagrams with some web tool like draw.io or maybe with vector graphics tool Inkscape, but for me, Latex is a great tool for creating complete documentation with state machine graph.
How do you create State Machine diagram for your documentation? Comment down below and check my other Latex related post on https://bln364.com/latex-in-linux/