Add a second label to a path in an automaton

Friends, consider the following code:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{automata}
\usetikzlibrary{positioning}

\begin{document}

\begin{tikzpicture}[shorten >=1pt,,node distance=4cm,on grid,auto, /tikz/initial text={start}]
\node[state, initial, accepting] (q0) {0};
\node[state] (q1) [right=of q0] {1};
\path[->] (q0) edge [bend left] node {on} (q1)
(q1) edge [bend left] node {off} (q0)
;
\end{tikzpicture}

\end{document}


This code produces the following output:

Pretty straightforward, I guess. :) I was wondering if it would be possible to add a second label to each one of those paths in a way I don't need to calculate their coordinates and hardcode them into the picture. My idea for a second label would is to put the text in the opposite direction of the primary label. :)

As a bonus, I was wondering how challenging would be to make the second label a little different than the first one, say, like this gimp'ed image:

Any hints on how to achieve this? :) I am already happy if a second label is possible, even without these bells and whistles.

• I'm not sure if this suffices your demands, but you could just specify a second node with [above] or below the path. This wouldn't be totally automatic but far away from hardcoded. Yor path would look like this: \path[->] (q0) edge [bend left] node[above] {on} node[below] {a} (q1) (q1) edge [bend left] node[below] {off} node[above] {a} (q0); This produces the two a nodes on the inner sides of the edges. – Dave Jun 12 '14 at 22:24
• @Dave: silly me, I had no idea of using a node (living and learning)! Perhaps you could convert your comment to an answer? I think it's a valid approach towards solving my question (of course, it's up to you). Thank you! Edit: actually, one the answers use this very approach, oopsie. But I really appreciate your comment! :) – Paulo Cereda Jun 13 '14 at 9:34
• I simply forgot to check this here since I had to do some work yesterday. I'm glad you got your answer anyway :) – Dave Jun 14 '14 at 12:17
• @Dave: thank you for the initial insight! :) – Paulo Cereda Jun 14 '14 at 13:20

Here is another idea, using pic (requires PGF 3.0.0)

The code which draws the "status" (on/off), and the additional char (a), and the little arrow, is all encapsulated in a pic style, which gets as two arguments the text to show in the "status" and in the "char". We need in fact two different pics, depending on the relative position of "status" and "char".

Defining pics with two arguments is a little more complex than single-argument pics, because the shortcut foo/.pic allows only for a single argument. So we have to go the "low level" pics/foo/.style, but still it is very straightforward:

\tikzset{
pics/second label below/.style 2 args = {
code = {
\node[above] (-status) {#1};
\node[below=3mm, inner sep=1pt] (-char) {\small #2};
\draw[->] (0,0) -- (-char);
}
},
pics/second label above/.style 2 args = {
code = {
\node[below] (-status) {#1};
\node[above=3mm, inner sep=1pt] (-char) {\small #2};
\draw[->] (0,0) -- (-char);
}
}
}


This pic can be used like this:

\begin{tikzpicture}[shorten >=1pt,,node distance=4cm,on grid,auto, /tikz/initial text={start}]
\node[state, initial, accepting] (q0) {0};
\node[state] (q1) [right=of q0] {1};
\path[->] (q0) edge [bend left] pic {second label below={on}{a}} (q1)
(q1) edge [bend left] pic {second label above={off}{a}} (q0)
;
\end{tikzpicture}


And produces:

As a bonus, it can be used at other positions of the curve, and it works too:

\begin{tikzpicture}[shorten >=1pt,,node distance=4cm,on grid,auto, /tikz/initial text={start}]
\node[state, initial, accepting] (q0) {0};
\node[state] (q1) [right=of q0] {1};
\path[->] (q0) edge [bend left] pic[pos=0.8] {second label below={on}{a}} (q1)
(q1) edge [bend left] pic[pos=0.8] {second label above={off}{a}} (q0)
;
\end{tikzpicture}


• Oh my, this is truly awesome! :) – Paulo Cereda Jun 13 '14 at 9:40

You can use swap or the shorthand ' to put the second label in the opposite direction of the first one:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{automata}
\usetikzlibrary{positioning}

\begin{document}

\begin{tikzpicture}[shorten >=1pt,,node distance=4cm,on grid,auto, /tikz/initial text={start}]
\node[state, initial, accepting] (q0) {0};
\node[state] (q1) [right=of q0] {1};
\path[->] (q0) edge [bend left] node {on} node [swap] {a} (q1)
(q1) edge [bend left] node {off} node [swap] {a} (q0)
;
\end{tikzpicture}

\end{document}


Maybe you can enlarge the outer sep to shift the second node:

\begin{tikzpicture}[shorten >=1pt,,node distance=4cm,on grid,auto, /tikz/initial text={start},
secn/.style={swap,outer sep=5pt}
]
\node[state, initial, accepting] (q0) {0};
\node[state] (q1) [right=of q0] {1};
\path[->] (q0) edge [bend left] node {on}node[secn]{a} (q1)
(q1) edge [bend left] node {off}node[secn]{a} (q0)
;
\end{tikzpicture}


• How nice, I had no idea there was a swap option! – Paulo Cereda Jun 13 '14 at 9:36

Another alternative is use of label distance=xxcm and below/above:text, as displayed below. In the direction from q0 to q1 the label a is allocated below of the path, hence the key below is used, actually, left, right, above right and more can be an option too. Utilizing the same idea, the path from q1 to q0 the label a is above the path, hence the key above is used.

node[label={[label distance=0.5cm] below:a}]


Code

\documentclass[border=10pt]{standalone}%{article}

\usepackage{tikz}
\usetikzlibrary{automata}
\usetikzlibrary{positioning}

\begin{document}

\begin{tikzpicture}[shorten >=1pt,,node distance=4cm,on grid,auto, /tikz/initial text={start}]
\node[state, initial, accepting] (q0) {0};
\node[state] (q1) [right=of q0] {1};
\path[->] (q0) edge [bend left]
node[label={[label distance=0.5cm] below:a}] {on} (q1)
(q1) edge [bend left]
node[label={[label distance=0.5cm] above:a}] {off} (q0)
;
\end{tikzpicture}

\end{document}

• Oh my, it looks very interesting! Thank you! :) – Paulo Cereda Jun 13 '14 at 9:36

As none of the existing answers show how to draw the little arrowed paths tangent to the curved ones, let me stole some code from Jake, namely: How to draw tangent line of an arbitrary point on a path in TikZ.

\documentclass[border=10pt,tikz]{standalone}

\usepackage{tikz}
\usetikzlibrary{automata}
\usetikzlibrary{decorations.markings}% we need this library
\usetikzlibrary{positioning}

\tikzset{tangent/.style={
decoration={
markings,% switch on markings
mark=
at position #1
with
{
\coordinate (tangent point-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) at (0pt,0pt);
\coordinate (tangent unit vector-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) at (1,0pt);
\coordinate (tangent orthogonal unit vector-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) at (0pt,1);
}
},
postaction=decorate
},
use tangent/.style={
shift=(tangent point-#1),
x=(tangent unit vector-#1),
y=(tangent orthogonal unit vector-#1)
},
use tangent/.default=1
}

\begin{document}

\begin{tikzpicture}[shorten >=1pt,node distance=4cm,on grid,auto, /tikz/initial text={start}]
\node[state, initial, accepting] (q0) {0};
\node[state] (q1) [right=of q0] {1};

\path[->] (q0) edge [bend left,tangent=0.5] node {on} (q1);
\draw[->, thick, use tangent] (0,0) --++ (0,-0.25) node[below]{a};

\path[->] (q1) edge [bend left,tangent=0.5] node {off} (q0);
\draw[->, thick, use tangent] (0,0) --++ (0,-0.25) node[above]{a};

\end{tikzpicture}

\end{document}


The result:

• ooh TikZ magic going on! Grazie, Claudio! :) – Paulo Cereda Jun 13 '14 at 9:37
• @PauloCereda: you're always welcome! I've seen Brazil managed to win the first match in World Cup.. though the penalty was too generous ;) – Claudio Fiandrino Jun 13 '14 at 9:43
• egreg and I were talking in the chatroom that, given the past penalty shootouts, we were likely to miss that one (Neymar almost missed it). :) It wasn't a penalty at all, thankfully Oscar scored the 3rd goal. :) I am waiting for the big game on Saturday. Avanti, Azzurra! :) – Paulo Cereda Jun 13 '14 at 9:55

With minimal modification, using the pin option

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{automata}
\usetikzlibrary{positioning}

\begin{document}

\begin{tikzpicture}[shorten >=1pt,,node distance=4cm,on grid,auto, /tikz/initial text={start},
pin edge={bend left=0,black, thick},
pin distance=3mm,
every pin/.style={font=\small, inner sep=1pt},
point/.style={inner sep=0, outer sep=0, minimum size=0}
]
\node[state, initial, accepting] (q0) {0};
\node[state] (q1) [right=of q0] {1};
\path[->] (q0) edge [bend left] node[pos=.3] {on} node[point,pin=below:a,pos=.2] {} (q1)
(q1) edge [bend left] node {off} node[point,pin=above:b] {} (q0)
;
\end{tikzpicture}

\end{document}


If you vary the value of pos you can shift the pin along the path and the arrow will follow it.

• Does anybody know why using coordinate instead of node[point] results in a double arrow for the pin? – Bordaigorl Jun 13 '14 at 10:36
• Oh my, another neat trick! Thank you! :) – Paulo Cereda Jun 13 '14 at 12:09
{"extraction_info": {"found_math": true, "script_math_tex": 0, "script_math_asciimath": 0, "math_annotations": 0, "math_alttext": 0, "mathml": 0, "mathjax_tag": 0, "mathjax_inline_tex": 0, "mathjax_display_tex": 0, "mathjax_asciimath": 1, "img_math": 0, "codecogs_latex": 0, "wp_latex": 0, "mimetex.cgi": 0, "/images/math/codecogs": 0, "mathtex.cgi": 0, "katex": 0, "math-container": 0, "wp-katex-eq": 0, "align": 0, "equation": 0, "x-ck12": 0, "texerror": 0, "math_score": 0.7551528215408325, "perplexity": 6911.118984011497}, "config": {"markdown_headings": false, "markdown_code": true, "boilerplate_config": {"ratio_threshold": 0.18, "absolute_threshold": 20, "end_threshold": 15, "enable": true}, "remove_buttons": true, "remove_image_figures": true, "remove_link_clusters": true, "table_config": {"min_rows": 2, "min_cols": 3, "format": "plain"}, "remove_chinese": true, "remove_edit_buttons": true, "extract_latex": true}, "warc_path": "s3://commoncrawl/crawl-data/CC-MAIN-2019-51/segments/1575540544696.93/warc/CC-MAIN-20191212153724-20191212181724-00034.warc.gz"}