Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I am currently typesetting a document which requires many commutative diagrams of the same shape and construction, but with different labels at the vertices and edges. For example, I want a commutative diagram which describes the associative structure of an algebra. This I can do with:

\begin{equation}
\begin{tikzpicture}[baseline=(current bounding box.center)]
\matrix(m)[matrix of math nodes,
row sep=2.6em, column sep=2.8em,
text height=2ex, text depth=0.5ex]
{(A\otimes A)\otimes A& & A\otimes (A\otimes A)\\
A\otimes A& &A\otimes A\\
 &A& \\};
\path[->,font=\normalsize,>=angle 90]
(m-1-1) edge node[auto] {$\mu\otimes Id$} (m-2-1)
(m-2-1) edge node[auto] {$\mu$} (m-3-2)
(m-1-3) edge node[auto] {$ Id\otimes\mu$} (m-2-3)
(m-2-3) edge node[auto] {$ \mu$} (m-3-2);
\path[<->, font=\normalsize,>=angle 90]
(m-1-1) edge node[auto] {$\alpha$} (m-1-3);
\end{tikzpicture}
\end{equation}

In the same section, I also want to use a commutative diagram to express the monoidal structure of a group. In my document as it stands, this is exactly the same code, but with different labels. As I go forward, I know that this is a diagram which I will likely use very often, and would like to not have to copy and paste this exact code into each new document.

I naively tried using \newcommand{\monoid}[8]{...} to wrap the whole thing, however this did not work. Is there a way to define a macro around this environment so that I can specify only the arguments I need and not be cluttered by having to copy and paste the whole block every time?

share|improve this question
    
Please explain what "didn't work". \newcommand is pretty much what you should use, so please give us your faulty code. –  Jean-Christophe Dubacq Apr 30 '12 at 6:17

3 Answers 3

up vote 11 down vote accepted

You'll need to replace the ampersands in the TikZ matrix using the key ampersand replacement=<macro>, where <macro> can be \&, for example.

Here's your code as a command. I used the approach described in PGF/TikZ: How to store strings in array? for using a list instead of separate arguments for the labels. Your diagram

can then be created using

\monoid{
    (A\otimes A)\otimes A,
    A\otimes (A\otimes A),
    A\otimes A,
    A\otimes A,
    A,
    $\mu\otimes Id$,
    $\mu$,
    $ Id\otimes\mu$,
    $ \mu$,
    $\alpha$
}

Here's the full code:

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

\usepackage{xparse}
\usepackage{etoolbox}
\newcounter{listtotal}\newcounter{listcntr}%
\NewDocumentCommand{\argument}{o}{%
  \setcounter{listtotal}{0}\setcounter{listcntr}{-1}%
  \renewcommand*{\do}[1]{\stepcounter{listtotal}}%
  \expandafter\docsvlist\expandafter{\argumentarray}%
  \IfNoValueTF{#1}
    {\namesarray}% \names
    {% \names[<index>]
     \renewcommand*{\do}[1]{\stepcounter{listcntr}\ifnum\value{listcntr}=#1\relax##1\fi}%
     \expandafter\docsvlist\expandafter{\argumentarray}}%
}

\newcommand{\monoid}[1]{
\def\argumentarray{#1}
\begin{tikzpicture}[baseline=(current bounding box.center)]
    \matrix(m)[
        matrix of math nodes,
        ampersand replacement=\&,
        row sep=2.6em,
        column sep=2.8em,
        text height=2ex,
        text depth=0.5ex
    ]
    {
    \argument[0]    \&              \& \argument[1]\\
    \argument[2]    \&              \& \argument[3]\\
                    \& \argument[4] \& \\
    };
\path[->,font=\normalsize,>=angle 90]
(m-1-1) edge node[auto] {\argument[5]} (m-2-1)
(m-2-1) edge node[auto] {\argument[6]} (m-3-2)
(m-1-3) edge node[auto] {\argument[8]} (m-2-3)
(m-2-3) edge node[auto] {\argument[9]} (m-3-2);
\path[<->, font=\normalsize,>=angle 90]
(m-1-1) edge node[auto] {\argument[10]} (m-1-3);
\end{tikzpicture}
}
\begin{document}
\monoid{
    (A\otimes A)\otimes A,
    A\otimes (A\otimes A),
    A\otimes A,
    A\otimes A,
    A,
    $\mu\otimes Id$,
    $\mu$,
    $ Id\otimes\mu$,
    $ \mu$,
    $\alpha$
}

\end{document}
share|improve this answer

Another approach:

  • Use tikz-cd for simple contruction of commutative diagrams
  • Use the arrayjobx package for the elements

Benefits:

  • Shorter diagram code, arrows directly within the elements
  • Instead of writing 9 parameters each time you call \monoid, you could modify just specific array arguments if diagrams are similar, such as by \monoidelements(1)={A'\otimes A'} and calling \monoid again

\documentclass{article}
\usepackage{arrayjobx}
\newarray{monoidelements}

\usepackage{tikz-cd}
\newcommand{\monoid}[1]{
  \begin{tikzcd}[->,font=\normalsize,>=angle 90,ampersand replacement=\&]
  #1(1) \arrow{d}{#1(6)} \arrow[<->]{rr}{\alpha}\& \& #1(2) \arrow{d}{#1(7)}\\
  #1(3) \arrow{dr}{#1(8)} \& \& #1(4)\arrow{dl}{#1(9)}\\
   \& #1(5) \&
  \end{tikzcd}}

\begin{document}
\readarray{monoidelements}{(A\otimes A)\otimes A\otimes A&A\otimes (A\otimes A)
  &A\otimes A&A\otimes A&A&\mu\otimes Id&Id\otimes\mu&\mu&\mu\otimes Id}
\monoid{\monoidelements}
\end{document}

Monoid

share|improve this answer

An answer which is too long for being a comment, as it's only a rewriting of Jake's answer using a shorter syntax based on expl3:

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

\usepackage{xparse}
\ExplSyntaxOn
\seq_new:N \l_jake_monoid_seq
\NewDocumentCommand{\monoid}{m}
 {
  \seq_set_split:Nnn \l_jake_monoid_seq { , } { #1 }
  \domonoid
 }
\NewDocumentCommand{\argument}{o}
 {
  \IfNoValueTF{#1}
   { \seq_use:N \l_jake_monoid_seq }
   { \seq_item:Nn \l_jake_monoid_seq { #1 } }
 }
\ExplSyntaxOff
\NewDocumentCommand{\domonoid}{}
 {
  \begin{tikzpicture}[baseline=(current bounding box.center)]
    \matrix(m)[
        matrix of math nodes,
        ampersand replacement=\&,
        row sep=2.6em,
        column sep=2.8em,
        text height=2ex,
        text depth=0.5ex
    ]
    {
    \argument[0]    \&              \& \argument[1]\\
    \argument[2]    \&              \& \argument[3]\\
                    \& \argument[4] \& \\
    };
  \path[->,font=\normalsize,>=angle 90]
  (m-1-1) edge node[auto] {\argument[5]} (m-2-1)
  (m-2-1) edge node[auto] {\argument[6]} (m-3-2)
  (m-1-3) edge node[auto] {\argument[8]} (m-2-3)
  (m-2-3) edge node[auto] {\argument[9]} (m-3-2);
  \path[<->, font=\normalsize,>=angle 90]
  (m-1-1) edge node[auto] {\argument[10]} (m-1-3);
  \end{tikzpicture}
 }
\begin{document}
\monoid{
    (A\otimes A)\otimes A,
    A\otimes (A\otimes A),
    A\otimes A,
    A\otimes A,
    A,
    $\mu\otimes \mathit{Id}$,
    $\mu$,
    $ \mathit{Id}\otimes\mu$,
    $ \mu$,
    $\alpha$
}

\end{document}

The \monoid macro does two things: it sets a sequence from its argument and calls \domonoid which is identical to Jake's \monoid. Notice that \domonoid must be defined with \ExplSyntaxOff, because spaces in TikZ keys are significant.

The definition of \argument is much easier than with etoolbox.

Note: in order to get a better form of Id, it's better to use \mathit{Id}.


We can use similar ideas also for Stefan Kottwitz's answer

\documentclass{article}
\usepackage{xparse}
\usepackage{tikz-cd}
\NewDocumentCommand{\monoid}{m}
 {
  \makeargument{#1}    
  \begin{tikzcd}[->,font=\normalsize,>=angle 90,ampersand replacement=\&]
  \argument{0} \arrow{d}{\argument{5}} \arrow[<->]{rr}{\alpha}\& \& \argument{1} \arrow{d}{\argument{6}}\\
  \argument{2} \arrow{dr}{\argument{7}} \& \& \argument{3}\arrow{dl}{\argument{8}}\\
   \& \argument{4} \&
  \end{tikzcd}
 }
\ExplSyntaxOn
\seq_new:N \l_sk_monoid_seq
\cs_new:Npn \makeargument #1
 { \seq_set_split:Nnn \l_sk_monoid_seq { & } { #1 } }
\cs_new:Npn \argument #1
 { \seq_item:Nn \l_sk_monoid_seq {#1} }
\ExplSyntaxOff

\begin{document}
\monoid{
  (A\otimes A)\otimes A\otimes A &
  A\otimes (A\otimes A) &
  A\otimes A &
  A\otimes A &
  A &
  \mu\otimes\mathit{Id} &
  \mathit{Id}\otimes\mu &
  \mu &
  \mu\otimes\mathit{Id}
}
\end{document}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.