16

How do you draw natural transformation arrows as mentioned in this question but using TikZ rather than xy? More generally, is it possible to draw edges between edge labels, from an edge label to a node, and from a node to an edge label or is it necessary to explicitly construct a node in order to draw an edge? Does providing an edge label in the path environment implicitly construct a node that can be used as the source and target of another edge? I would like to do this using the matrix and path environments in TikZ if possible.

Example:

\documentclass{article} 
\usepackage{tikz}
\usetikzlibrary{matrix,arrows}

\begin{tikzpicture}[description/.style={fill=white,inner sep=2pt}]
    \matrix (m) [matrix of math nodes, row sep=3em,
    column sep=2.0em, text height=1.5ex, text depth=0.25ex]
    { \mathcal{D} & & \mathcal{J} \\
      \mathcal{C} & & \\ };
    \path[->,font=\scriptsize]
    (m-1-1) edge[loop left] node[auto] {$ F \circ G $} (m-1-1)
    (m-1-1.20) edge node[auto] {$ G $} (m-1-3.160)
    (m-1-3.200) edge node[auto] {$ F $} (m-1-1.340)
    (m-1-1) edge node[left] {$ H $} (m-2-1);    
\end{tikzpicture}

\end{document}

example diagram

How can I connect F◦G and H with a curved natural transformation arrow ⟹? Feel free to rearrange the diagram if you'd like.

David Carlisle
  • 757,742

3 Answers3

23

As percusse mentions in his comment, the tikz-cd package offers you a convenient set of macros to draw commutative diagrams; here's a little example:

\documentclass{article} 
\usepackage{tikz-cd}

\begin{document}

\begin{tikzcd}[column sep=huge]
\textbf{CRing}
  \arrow[bend left=50]{r}[name=U,label=above:$\scriptstyle\mathrm{GL}_n$]{}
  \arrow[bend right=50]{r}[name=D,label=below:$\scriptstyle U$]{} &
\textbf{Grp}
  \arrow[shorten <=10pt,shorten >=10pt,Rightarrow,to path={(U) -- node[label=right:$\det$] {} (D)}]{}
\end{tikzcd}

\end{document}

enter image description here

Since originally the question asked for a TikZ solution using a matrix of nodes, here's a "pure" TikZ possible solution:

\documentclass{article} 
\usepackage{tikz}
\usetikzlibrary{matrix,arrows}

\begin{document}

\begin{tikzpicture}
\matrix[matrix of nodes,column sep=2cm] (cd)
{
   \textbf{CRing} & \textbf{Grp} \\
};
\draw[->] (cd-1-1) to[bend left=50] node[label=above:$\scriptstyle\mathrm{GL}_n$] (U) {} (cd-1-2);
\draw[->] (cd-1-1) to[bend right=50,name=D] node[label=below:$\scriptstyle U$] (V) {} (cd-1-2);
\draw[double,double equal sign distance,-implies,shorten >=10pt,shorten <=10pt] 
  (U) -- node[label=right:$\det$] {} (V);
\end{tikzpicture}

\end{document}

enter image description here

An answer to the edit to the original question, showing two possibilities (a curved double arrow, and a straight one):

\documentclass{article} 
\usepackage{tikz}
\usetikzlibrary{matrix,arrows}

\begin{document}

\begin{tikzpicture}[description/.style={fill=white,inner sep=2pt}]
    \matrix (m) [matrix of math nodes, row sep=3em,
    column sep=2.0em, text height=1.5ex, text depth=0.25ex]
    { \mathcal{D} & & \mathcal{J} \\
      \mathcal{C} & & \\ };
    \path[->,font=\scriptsize]
    (m-1-1) edge[loop left] node[auto] (fg) {$ F \circ G $} (m-1-1)
    (m-1-1.20) edge node[auto] {$ G $} (m-1-3.160)
    (m-1-3.200) edge node[auto] {$ F $} (m-1-1.340)
    (m-1-1) edge node[left] (h) {$ H $} (m-2-1);
    \draw[double,double equal sign distance,-implies] (fg.290) -- (h.150);    
\end{tikzpicture}

\begin{tikzpicture}[description/.style={fill=white,inner sep=2pt}]
    \matrix (m) [matrix of math nodes, row sep=3em,
    column sep=2.0em, text height=1.5ex, text depth=0.25ex]
    { \mathcal{D} & & \mathcal{J} \\
      \mathcal{C} & & \\ };
    \path[->,font=\scriptsize]
    (m-1-1) edge[loop left] node[auto] (fg) {$ F \circ G $} (m-1-1)
    (m-1-1.20) edge node[auto] {$ G $} (m-1-3.160)
    (m-1-3.200) edge node[auto] {$ F $} (m-1-1.340)
    (m-1-1) edge node[left] (h) {$ H $} (m-2-1);
    \draw[double,double equal sign distance,-implies] (fg.290) to[out=-90,in=180] (h.180);    
\end{tikzpicture}

\end{document}

enter image description here

And here's the corresponding code using tikz-cd:

\documentclass{article} 
\usepackage{tikz-cd}

\begin{document}

\begin{tikzcd}[column sep=huge,row sep=huge]
\mathcal{D}
  \arrow[loop left]{}[name=fg]{F \circ G}
  \rar[start anchor=30, end anchor=151]{G}
  \arrow{d}[name=h,swap]{H} & 
\mathcal{J}\lar[start anchor=196, end anchor=-14]{F} \\
\mathcal{C}
\arrow[shorten >=4pt,Rightarrow,to path={(fg.290) -- (h.175)}]{}
\end{tikzcd}

\begin{tikzcd}[column sep=huge,row sep=huge]
\mathcal{D}
  \arrow[loop left]{}[name=fg]{F \circ G}
  \rar[start anchor=30, end anchor=151]{G}
  \arrow{d}[swap,name=h]{H} & 
\mathcal{J}\lar[start anchor=196, end anchor=-14]{F} \\
\mathcal{C}
\arrow[shorten >=3pt,Rightarrow,to path={(fg.290) to[out=-90,in=180] (h)}]{}
\end{tikzcd}

\end{document}

enter image description here

To add a label to the double arrow (as requested in a comment), you can use an additional node; here's an example using both approaches (the first one using tikz-cd and the second one using "pure" TikZ):

\documentclass{article} 
\usepackage{tikz-cd}
\usepackage{tikz}
\usetikzlibrary{matrix,arrows}

\begin{document}

\begin{tikzcd}[column sep=huge,row sep=huge]
\mathcal{D}
  \arrow[loop left]{}[name=fg]{F \circ G}
  \rar[start anchor=30, end anchor=151]{G}
  \arrow{d}[swap,name=h]{H} & 
\mathcal{J}\lar[start anchor=196, end anchor=-14]{F} \\
\mathcal{C}
\arrow[shorten >=1pt,Rightarrow,to path={(fg.290) to[out=-90,in=180] node[xshift=-3.5mm] {$\tau$} (h)}]{}
\end{tikzcd}

\begin{tikzpicture}[description/.style={fill=white,inner sep=2pt}]
    \matrix (m) [matrix of math nodes, row sep=3em,
    column sep=2.0em, text height=1.5ex, text depth=0.25ex]
    { \mathcal{D} & & \mathcal{J} \\
      \mathcal{C} & & \\ };
    \path[->,font=\scriptsize]
    (m-1-1) edge[loop left] node[auto] (fg) {$ F \circ G $} (m-1-1)
    (m-1-1.20) edge node[auto] {$ G $} (m-1-3.160)
    (m-1-3.200) edge node[auto] {$ F $} (m-1-1.340)
    (m-1-1) edge node[left] (h) {$ H $} (m-2-1);
    \draw[double,double equal sign distance,-implies] (fg.290) to[out=-90,in=180] node[xshift=-3.5mm] {$\tau$} (h.180);    
\end{tikzpicture}

\end{document}

enter image description here

Moriambar
  • 11,466
Gonzalo Medina
  • 505,128
8

I don't respect some initial conditions because I don't understand what it's interesting to use a matrix for two vertices. I think matrix is very useful but only for complex structures.

Here we need two lines to place the main nodes. I used outer sep=4pt to put the arrows at right places. Then I place two nodes in the middle of each arrows. I named these nodes to be able to draw the last double arrow. The option fo this arrow are complex, so I think it's preferable to use a style.

\documentclass{article} 
\usepackage{tikz}
\usetikzlibrary{arrows}

\begin{document}

\tikzset{dbl/.style={double,
                     double equal sign distance,
                     -implies,
                     shorten >=10pt,
                     shorten <=10pt}}

\begin{tikzpicture} [every node/.style={outer sep=4pt}]
 \node  (A) at (0,0)  {\textbf{CRing}}; 
 \node  (B) at (4,0)  {\textbf{Grp}};

 \draw[->]  (A.north)  to [bend left = 30]  node[above] (C) {$\scriptstyle\mathrm{GL}_n$} (B.north);
 \draw[->]  (A.south)  to [bend right= 30]  node[below] (D) {$\scriptstyle U$}            (B.south);   
 \draw[dbl]   (C)      to                   node[right]     {$\det$}                      (D);
\end{tikzpicture}     

\end{document}

enter image description here

The aim of this method is to be able to scale the figure like I want, now two examples :

\documentclass{article} 
\usepackage{tikz}
\usetikzlibrary{arrows}

\begin{document}

\tikzset{dbl/.style={double,
                     double equal sign distance,
                     -implies,
                     shorten >=10pt,
                     shorten <=10pt}}

\begin{tikzpicture} [every node/.style={outer sep=4pt},yscale=1.5]
 \node  (A) at (0,0)  {\textbf{CRing}}; 
 \node  (B) at (4,0)  {\textbf{Grp}};

 \draw[->]  (A.north) to [bend left = 30]  node[above] (C) {$\scriptstyle\mathrm{GL}_n$}  (B.north);
 \draw[->]  (A.south) to [bend right= 30]  node[below] (D) {$\scriptstyle U$}             (B.south);   
 \draw[dbl]   (C)     to                   node[right]     {$\det$}                       (D);
\end{tikzpicture}
\begin{tikzpicture} [every node/.style={outer sep=4pt},xscale=1.5,yscale=1.25]
 \node  (A) at (0,0)  {\textbf{CRing}}; 
 \node  (B) at (4,0)  {\textbf{Grp}};

 \draw[->]  (A.north)  to [bend left = 30]  node[above] (C) {$\scriptstyle\mathrm{GL}_n$} (B.north);
 \draw[->]  (A.south)  to [bend right= 30]  node[below] (D) {$\scriptstyle U$}            (B.south);   
 \draw[dbl]   (C)      to                   node[right]     {$\det$}                      (D);
\end{tikzpicture}   
\end{document}

enter image description here

Alain Matthes
  • 95,075
  • Thank you for the examples Altermundus. The reason I asked to use matrix is that I have more complicated diagrams in mind. I just linked to that previous post because it had an example of a natural transformation arrow between two edge labels. That is nice to be able to scale the drawing. I think I will stick with tikz-cd for what seems to be the relative simplicity of the syntax, but that might change with more complicated diagrams. Is it possible to scale a diagram like this with tikz-cd? – Cameron Smith May 11 '12 at 13:25
  • I don't know, I never use tikz-cd. I try with only with your example and it seems not easy to do. Perhaps scale a matrix is a problem. – Alain Matthes May 11 '12 at 13:59
1

I just wanted to add that it can be very useful to write a macro for that. For example as follows:

\documentclass{article}
\usepackage{tikz-cd}

\newcommand{\nat}[6][large]{%
  \begin{tikzcd}[ampersand replacement = \&, column sep=#1]
    #2\ar[bend left=40,""{name=U}]{r}{#4}\ar[bend right=40,',""{name=D}]{r}{#5}\& #3
          \ar[shorten <=10pt,shorten >=10pt,Rightarrow,from=U,to=D]{d}{~#6}
    \end{tikzcd}
}
\newcommand{\te}[1]{\text{#1}}
\newcommand{\tf}[1]{\textbf{#1}}

The command \nat takes 6 arguments but includes one default argument for the column separation, so you just need to specify 5. Then your document looks as follows:

\begin{document}

    \nat{\tf{CRing}}{\tf{Mon}}{M_n}{U}{\te{det}}
    \nat[huge]{\tf{CRing}}{\tf{Mon}}{M_n}{U}{\te{det}}

\end{document}`

enter image description here

exchange
  • 211