Diagrammes commutatifs avec XY-Pic

Il y a, à ma connaissance, deux extensions (« packages », en anglais) qui permettent de tracer des diagrammes commutatifs sous LaTeX, sans trop de restriction : XY-Pic, dont nous allons parler, et PSTricks. Tous les autres que j'ai essayés (un peu moins d'une dizaine, je crois), sont trop limités : si au début, on peut s'en satisfaire, on voudra tôt ou tard faire un diagramme commutatif trop compliqué pour les macros que l'on a choisies (flèches en diagonales, flèches courbes, diagramme dans une 2-catégorie, diagramme en forme de pentagone régulier, etc.).

Problèmes éventuels
La structure d'un document LaTeX utilisant XY-Pic sera la suivante.
  \documentclass[a4paper,12pt]{article}
  \usepackage[latin1]{inputenc}
  \usepackage[T1]{fontenc}
  \usepackage{amsmath,amssymb}
  %\usepackage{french}
  \usepackage[all]{xy}
  \begin{document}
    ...
  \end{document}
Le lecteur n'ayant jamais utilisé XY-Pic est prié de passer à la section suivante : avant de donner des exemples qui marchent, nous allons signaler ce qui peut poser problème. Tout d'abord, XY-Pic exige que les catcodes ne changent plus une fois qu'il a été chargé, alors que french les change sans cesse. Il est donc bon de mettre des \english devant les diagrammes commutatifs les plus compliqués. La commande \CompileMatrices est aussi suceptible de poser des problèmes avec french (ou avec d'autres extensions) : évitez-la.
  \documentclass[a4paper,12pt]{article}
  \usepackage[latin1]{inputenc}
  \usepackage[T1]{fontenc}
  \usepackage{amsmath,amssymb}
  \usepackage{french}
  \usepackage[all]{xy}
  \begin{document}
  $$ \english \xymatrix{ ... } $$
  \end{document}
Avec Babel, c'est un peu plus compliqué :
  \documentclass[a4paper,12pt]{article}
  \usepackage[latin1]{inputenc}
  \usepackage[T1]{fontenc}
  \usepackage{amsmath,amssymb}
  \usepackage{dsfont}\let\mathbb\mathds
  \usepackage[english,frenchb]{babel}
  \usepackage[all,dvips]{xy}
  \begin{document}
  $$ 
  \shorthandoff{;:!?}
  \xymatrix ...
  $$
  \end{document}
Ensuite, il faut savoir que le premier caractère d'une entrée dans un diagramme commutatif ne doit pas être un antislash (ni certains caractères qui ont un sens particulier pour XY-Pic, par exemple une étoile). Si on en a besoin, on le fera précéder de \relax (en fait, on constate des problèmes uniquement pour la première case, pas pour les autres).
  \documentclass[a4paper,12pt]{article}
  \usepackage[latin1]{inputenc}
  \usepackage[T1]{fontenc}
  \usepackage{amsmath,amssymb}
  \usepackage{french}
  \usepackage[all]{xy}
  \begin{document}
  $$ \english\xymatrix{\relax
     ... 
    } $$
  \end{document}
Les problèmes qui suivent ne sont pas visibles sur les images GIF de ce document : il faudrait prendre le fichier PostScript et le regarder à la loupe.
Vous vous appercevrez peut-être que l'empenage des flèches n'est pas exactement aligné avec le corps des flèches ou que les flèches en diagonales sont saccadées : le problème est dû à un mauvais positionnement des fontes utilisées pour les tracer ; il disparait si on demande à XY-Pic de faire les flèches en PostScript.
  \documentclass[a4paper,12pt]{article}
  \usepackage[latin1]{inputenc}
  \usepackage[T1]{fontenc}
  \usepackage{amsmath,amssymb}
  \usepackage{french}
  \usepackage[all,dvips]{xy}
  \begin{document}
  $$ \english\xymatrix{\relax
     ... 
    } $$
  \end{document}
Toujours en examinant votre fichier à la loupe, vous verrez peut-être que les entrées sont toutes centrées : en particulier, si une entrée très haute est juste à côté d'une entrée très profonde, leurs lignes de base ne seront pas alignées.
*
On peut corriger ce problème en rajoutant la ligne suivante dans le préambule du document.
  \entrymodifiers={!!<0pt,0.7ex>+}
*
Toujours avec une très bonne loupe, vous constatez que quand vous essayez de mettre de petits diagrammes dans le texte, au milieu d'un paragraphe (et non plus en mode mathématique centré), la ligne de base des entrées n'est pas alignée avec la ligne de base du texte. Dans l'exemple suivant, les deux G n'étaient pas alignés. La commande \raisebox a permi de corriger le problème.
  \def\dar[#1]{\ar@<2pt>[#1]\ar@<-2pt>[#1]}
  \entrymodifiers={!!<0pt,0.7ex>+}
  Soit $G = \raisebox{.7ex}{\xymatrix{ G_1 \dar[r] & G_0 }}$ 
  un groupoïde...
*

Exemples simples
Commençons par traiter le cas des diagrammes commutatifs qui rentrent dans un tableau. On met tout d'abord les différents éléments dans les cases du tableau : le &amp; sépare les colonnes, le \\ sépare les lignes et le tout est donné en argument de la commande \xymatrix.
    \xymatrix{
      A & B \\
      C & D
    }
*
On rajoute ensuite les flèches, sous la forme \ar[?], où on remplace le point d'interrogation par la direction de la flèche :
  r pour une case vers la droite, 
  l pour une case vers la gauche, 
  d pour une case vers le bas, 
  u pour une case vers le haut.
Il est possible de les combiner, par exemple rd pour aller une case vers le bas et une case vers la droite ou rr pour aller deux cases vers la droite. On met la flèche dans sa case de départ.
  \xymatrix{
    A \ar[r] \ar[d] \ar[rd] & B \ar[d] \\
    C \ar[r] & D
  }
*
On peut maintenant donner des noms aux flèches : il suffit de les mettre en exposant ou en indice, selon la position désirée. Pour savoir s'il s'agit d'un exposant ou d'un indice, on commence par faire tourner la flèche pour qu'elle aille de la gauche vers la droite : l'exposant est au dessus et l'indice en dessous.
  \xymatrix{
    A \ar[r]^f \ar[d]_\phi \ar[rd] & B \ar[d]^\psi \\
    C \ar[r]_g & D
  }
*
Il est possible de changer la forme des flèches en rajoutant des choses du genre
  @{.>} (flèche en pointillés),
  @{-->} (autre type de pointillés, moins beau),
  @{=>} (flèche double),
  @{=} (grand signe égal),
  @{^{(}->} (inclusion),
  @{->>} (épimorphisme),
  @{|->} (image par une application),
  @{~>} (flèche qui ondule),
  etc.
entre le début \ar de la flèche et sa direction.
  \xymatrix{
    A \ar@{^{(}->}[r]^f \ar@{.>}[d]_\phi \ar@{=>}[rd] & B \ar@{=}[d]^\psi \\
    C \ar@{->>}[r]_g & D
  }
*
On peut définir soi-même de nouveaux types de flèches (n'essayez surtout pas vous-même), par exemple, ici, une autre manière de dessiner les monomorphismes.
  \newdir{ >}{{}*!/-5pt/\dir{>}}
  \xymatrix{
    A \ar@{|->}[r] \ar@{~>}[d] & B \ar@{-->}[d] \\
    C \ar@{ >->}[r] & D
    }
*
On peut aussi avoir des flèches courbes, en rajoutant @/^/ ou @/_/ entre le début de la flèche et sa direction. La sens de la courbure est donné par la même convention que ci-dessus.
  \xymatrix{ A \ar[r] & B \ar@/_/@{.>}[l] }
*
  \xymatrix{
    T \ar@/^/[rrd] \ar@/_/[rdd] \ar@{.>}[rd] \\
    & A \ar[r] \ar[d] & B \ar[d] \\
    & C \ar[r] & D 
  }
*
Si la courbure n'est pas suffisante, on peut la modifier en rajoutant une distance.
  \xymatrix{ A \ar@/^1pc/[r] \ar@/^2pc/[r] \ar@/^3pc/[r] & B }
*

(trouver un titre)
Lorsque l'on met une flèche entre deux entrées de tailles très différentes, XY-Pic met le label de la flèche exactement entre les deux centres des entrées, ce qui peut être très éloigné du milieu de la flèche. On peut lui demander de prendre le milieu de la flèche en rajoutant un tiret juste avant ce label.
*
  \xymatrix{\relax
    \txt{Bla bla bla} \ar[r]^-{f} & X }
*
Si on ne précise rien, XY-Pic calcule tout seul la taille des cases. Cela a une conséquence desagréable : la grille obtenue n'est pas homogène, il y aura des cases plus larges ou plus hautes que les autres. On peut demander à LaTeX d'utiliser une grille régulière, en rajoutant @!juste après \xymatrix.
  \xymatrix{
    A & B & C & D \\
    E & \sin x \cos y & G & H }
*
  \xymatrix@!{
    A & B & C & D \\
    E & \sin x \cos y & G & H }
*
Dans les exemples précédents, la grille était constituée de carrés : on peut préférer des rectangles.
  \xymatrix@!C{
    A & B & C & D \\
    E & \sin x \cos y & G & H }
*
Jusqu'à présent, on laissait LaTeX calculer la taille de ces rectangles, en prenant les dimensions de la case la plus grande. On peut imposer ces valeurs.
  \xymatrix @!0 @R=5mm @C=1cm {
    A & B & C & D \\
    E & \sin x \cos y & G & H }
*
On peut utilise les constructions précédentes pour améliorer les diagrammes triangulaires.
  \xymatrix{ A \ar[rr] \ar[rd] && B \ar[ld] \\ & C }
*
  \xymatrix{ A \ar[rr] \ar[rd] && B \ar[ld] \\ & A+B+C+D+E+F+G }
*
  \xymatrix @!0 @C=4pc @R=3pc { 
    A \ar[rr] \ar[rd] && B \ar[ld] \\ & A+B+C+D+E+F+G }
*
C'est beaucoup plus utile sur l'exemple suivant.
  \xymatrix{ & B \\ A \ar[ru] \ar[rd] \\ & C }
*
  \xymatrix  @!0 @R=1em @C=4pc { & B \\ A \ar[ru] \ar[rd] \\ & C }
*
On peut faire passer une flèche en dessous d'une autre, en rajoutant |!{[ur];[dr]}\hole juste après la flèche du dessous, où [ur] et [dr] sont les cases de départ de de fin de la flèche du dessus (il faut qu'elle soit droite).
  \xymatrix @!0 @R=2pc @C=3pc {
    A \ar[rr] \ar[rd] \ar[dd] && B \ar[dd] \\
    & C \ar[ru] \ar[dd] \\
    A' \ar[rr] |!{[ur];[dr]}\hole \ar[rd] && B' \\
    & C' \ar[ru] }
*
  \xymatrix {
    A \ar[rr] \ar[dd] \ar[dr] && B \ar[dr] \ar[dd] |!{[dl];[dr]}\hole \\
    & A \ar[rr] \ar[dd] && B' \ar[dd] \\
    C \ar[rr] |!{[ur];[dr]}\hole \ar[dr] && D \ar[rd] \\
    & C' \ar[rr] && D' \\
  }
*
Nous sommes déjà capables de faire des diagrammes simples avec des 2-catégories.
  \xymatrix{ 
    A \ar[r] \ar[d] \ar@{=>}[rd]^\alpha & B \ar[d] \\
    C \ar[r] & D }
*
(expliquer)
  \xymatrix{ 
    A \ar[r] & B \\ C \ar[u] 
    \ar[ru]|*{}="A" 
    \ar@{=>}[u];"A"^\alpha }
*
  \def\enlargexyentry#1{%
    \POS "#1",*{
      \vrule height 1pt depth 1pt width 0pt
      \vrule height 0pt depth 0pt width 2pt
      }="#1",}
  \xymatrix{ 
    A \ar[r] & B \\ C \ar[u] 
    \ar[ru]|*{}="A" 
    \enlargexyentry A
    \ar@{=>}[u];"A"^-\alpha }
*
On a souvent besoin de 2-cellules : on peut facilement écrire une macro qui les trace.
  \let\cat\mathfrak % Fonte pour les catégories
  \let\f\mathcal    % fonte pour les foncteurs
  \newcommand{\UN}[4][r]{%
    \ar@/^1pc/[#1]^{#2}_*=<0.3pt>{}="HAUT"
    \ar@/_1pc/[#1]_{#3}^*=<0.3pt>{}="BAS"
    \ar @{=>} "HAUT";"BAS" ^{#4}
  }
  \xymatrix{\relax
    \cat A \UN[r]{\f F}{\f G}{\alpha} & \cat B }
*
On a aussi souvent besoin de deux 2-cellules empilées.
  \let\cat\mathfrak % Fonte pour les catégories
  \let\f\mathcal    % fonte pour les foncteurs
  \newcommand{\DEUX}[6][r]{
    \ar@/^2pc/[#1]^{#2}_*=<0.3pt>{}="HAUT"
    \ar@{}    [#1]     ^*=<0.3pt>{}="MILIEUHAUT"
                       _*=<0.3pt>{}="MILIEUBAS"
    \ar[#1]_(0.3){#3}                  
    \ar@/_2pc/[#1]_{#4}^*=<0.3pt>{}="BAS"
    \ar @{=>} "HAUT";"MILIEUHAUT" ^{#5}
    \ar @{=>} "MILIEUBAS";"BAS" ^{#6}
  }  
  \xymatrix{\relax
    \cat A \DEUX[r]{\f F}{\f G}{\f H}{\alpha}{\beta} & 
    \cat B \DEUX[r]{\f F'}{\f G'}{\f H'}{\gamma}{\delta} & 
    \cat C }
*
Voici une macro permettant de tracer des diagrammes cartésiens.
  \def\cartesien{%
    \ar@{-}[]+R+<6pt,-1pt>;[]+RD+<6pt,-6pt>%
    \ar@{-}[]+D+<1pt,-6pt>;[]+RD+<6pt,-6pt>%
  }
  \xymatrix{ 
    A \ar[r] \ar[d] \cartesien & B \ar[d] \\
    C \ar[r] & D }
*
Idem pour les diagrammes cocartésiens.
  \def\cocartesien{%
    \ar@{-}[]+L+<-6pt,+1pt>;[]+LU+<-6pt,+6pt>%
    \ar@{-}[]+U+<-1pt,+6pt>;[]+LU+<-6pt,+6pt>%
  }
  \xymatrix{ 
    A \ar[r] \ar[d] & B \ar[d] \\
    C \ar[r] & D \cocartesien }
*
On peut insister sur le fait qu'un diagramme est commutatif.
  \def\commutatif{\ar@{}[rd]|{\circlearrowleft}}
  \xymatrix{ 
    A \ar[r] \ar[d] \commutatif & B \ar[d] \\
    C \ar[r] & D }
*
On a parfois besoin de décaler légèrement les flèches. On peut le faire en rajoutant @&lt;2pt> (vous pouvez changer la distance et même en mettre une négative pour déplacer la flèche dans l'autre sens).
  \xymatrix{ A \ar@<2pt>[r] & B \ar@<2pt>[l] }
*
  \def\dar[#1]{\ar@<2pt>[#1]\ar@<-2pt>[#1]}
  \xymatrix{ A \dar[r] & B }
*
On a parfois besoin d'un « grand » symbole d'isomorphisme. Celui que j'utilise n'est peut-être pas très beau.
  \newcommand{\eq}[1][r]
   {\ar@<-3pt>@{-}[#1]
    \ar@<-1pt>@{}[#1]|<{}="gauche"
    \ar@<+0pt>@{}[#1]|-{}="milieu"
    \ar@<+1pt>@{}[#1]|>{}="droite"
    \ar@/^2pt/@{-}"gauche";"milieu"
    \ar@/_2pt/@{-}"milieu";"droite"}
  \xymatrix{ A \eq[r] \eq[rd] & B \eq[d] \\ & C }
*
On peut aussi vouloir faire la même chose avec des inclusions (mais le résultat n'est pas très satisfaisant).
  \newcommand{\incl}[1][r]
  {\ar@<-0.2pc>@{^(-}[#1] \ar@<+0.2pc>@{-}[#1]}
  \xymatrix{ A \incl[r] \incl[d] \incl[rd] & B \incl[d] \\ 
             C \incl[r]                    & D}
*
On peut noter les immersions ouvertes de la manière suivante.
  \newcommand{\immouv}[1][r]
   {\ar@{}[#1] |*[o][F]{\hbox{%
         \vrule width 1.5mm height 0pt depth 0pt%
         \vrule width 0pt height .75mm depth .75mm%
         }}
     \ar@{^{(}->}[#1]}
  \xymatrix{ A \immouv[r] \immouv[d] \immouv[rd] & B \immouv[d] \\ 
             C \immouv[r]                    & D}
*
On peut utiliser XY-Pic pour dessiner des matrices.
  $$
  \left(
     \raisebox{0.5\depth}{%
       \xymatrixcolsep{1ex}%
       \xymatrixrowsep{1ex}%
       \xymatrix{
         1 \ar @{-}[ddddrrrr] & 
         \lambda \ar @{-}[dddrrr]
         & 0 \ar @{.}[rr] \ar@{.}[ddrr]& & 0 \ar@{.}[dd]\\
         0 \ar@{.}[ddd] \ar@{.}[dddrrr]\\
         &&&& 0\\
         &&&& \lambda \\
         0 \ar@{.}[rrr] & & & 0 & 1
       }%
     }
   \right)
  $$
*
On a parfois besoin d'un diagramme commutatif en forme de pentagone régulier (si, si, ça arrive vraiment). On constate que c'est plus beau si le pentagone est applati.
  \def\MyNode{\ifcase\xypolynode\or
      ((A   B)   C)   D
    \or
      (A   B)   (C   D)
    \or
      A   (B   (C   D))
    \or
      A   ((B   C)   D)
    \or
      (A   (B   C))   D
    \fi
  }%
  \xy/r7pc/: (0,.3)::
    \xypolygon5{~>{}\txt{\ \ \strut\ensuremath{\MyNode}}} % ???
    \ar "2";"1" ^a
    \ar "3";"2" ^a
    \ar "3";"4" _<{1\otimes a}
    \ar "4";"5" _a
    \ar "5";"1" _>{a\otimes 1}
  \endxy
*
*

Exemples beaucoup plus compliqués, que l'utilisateur normal n'a pas à connaître
Il est possible de faire tourner du texte
  \xymatrix{
    & B \ar[d] \\
    A \ar[ru]^*[@]{\txt{bla bla}} \ar[r] & C}
*
  \xymatrix{
    & B \ar[d] \\
    A \ar[ru]^*[@]{\hbox to 0pt{\hss\txt{bla bla}\hss}} \ar[r] & C}
*
  \xymatrix{
    & B \ar[d] \\
    A \ar[ru]^*[@]{\hbox to 0pt{\hss\txt{bla bla\\bla bla}\hss}} \ar[r] & C}
*
Il est possible d'encadrer du texte
  \xymatrix{
    *+[F]+\txt{Bla bla bla} \ar@/^1cm/[r] & 
    *+[F]+\txt{Bla bla bla} \ar@/^1cm/[l] }
*
Il est possible de « recentrer » les entrées.
  \xymatrix{
    \txt{Bla bla bla} \ar@/^/[r] \ar[d] & 
    \txt{Bla bla bla} \ar@/^/[l] \ar[d] \\
    **[l]\txt{Bla bla bla} \ar@/^/[r] & 
    **[r]\txt{Bla bla bla} \ar@/^/[l] }
*
Il est bien évidemment possible de combiner cela avec l'encadrement.
  \xymatrix{
    **{[l][F]+}\txt{Bla bla bla} \ar@/^1cm/[r] & 
    **{[r][F]+}\txt{Bla bla bla} \ar@/^1cm/[l] }
*
Par contre, on remarquera que la syntaxe **[l] est compatible avec \entrymodifiers={!!&lt;0pt,0.7ex>+} (en fait, ça n'est pas incompatible, mais les deux sont interprétées dans le mauvais ordre, la première effaçant les instructions de la seconde). On peut s'en tirer comme suit. (On n'utilise plus la commande \txt, car elle centre verticalement son argument, ce que l'on tient à éviter.)
  \entrymodifiers={!!<0pt,0.7ex>+}
  \xymatrix{
    \txt{Bla bla blap} \ar@/^/[r] \ar[d] & 
    \txt{Bla bla bla} \ar@/^/[l] \ar[d] \\
    \hbox{Bla bla blap} \ar@/^/[r] \ar[d] & 
    \hbox{Bla bla bla} \ar@/^/[l] \ar[d] \\
    *!!<0pt,0.7ex>+!R!<-1.2ex,0pt>\hbox{Bla bla blap} \ar@/^/[r] & 
    *!!<0pt,0.7ex>+!L!<+1.2ex,0pt>\hbox{Bla bla bla} \ar@/^/[l] \\
  }
*
Il est possible d'avoir des flèches qui partent d'une case et qui y reviennent (attention à l'ordre : si on veut changer la forme de la flèche, il faut le faire avant, par exemple \ar@{.>}@(ul,ur)[]).
  \xymatrix{
    A \ar@(ul,dl)[] \ar@/^/[r] & 
    B \ar@(ur,dr)[] \ar@/^/[l] }
*
Quand les flèches sont très courbes et leur empennage très étroit, le résultat est horrible. On peut reprendre l'exemple précédent en changeant cet empennage (et en le prenant dans les fontes Euler, 12 points).
  \SelectTips{eu}{12}%
  \xymatrix{
    A \ar@(ul,dl)[] \ar@/^/[r] & 
    B \ar@(ur,dr)[] \ar@/^/[l] }
*
On peut jouer avec l'épaisseur des flèches.
  \xymatrix{A \ar@*{[|<2pt>]}[r] & B }
*
On peut aussi jouer avec leur couleur.
  \xymatrix{ A \ar@*{[|<2pt>]}@*{[red]}[r] & B }
*
Parfois, les flèches sont trop courtes.
  \def\pr{\operatorname{pr}}
  \makeatletter
    \let\OLD@times\times
    \def\Times{\@ifnextchar_\timesWSB\OLD@times}
    \def\timesWSB_#1{\mathbin{\mathop{\OLD@times}\limits_{#1}}}
  \makeatother
  $$ \xymatrix @!0 @R=2pc @C=4pc {
    G_1 \Times_{G_0} G_1 
    \ar[rd] _{\pr_2} 
    \ar[rrrr]^m &&&& G_1 \ar[lldd]^s\\
    & G_1 \ar[rd]_s \\
    && G_0} $$
*
  \def\pr{\operatorname{pr}}
  \makeatletter
    \let\OLD@times\times
    \def\Times{\@ifnextchar_\timesWSB\OLD@times}
    \def\timesWSB_#1{\mathbin{\mathop{\OLD@times}\limits_{#1}}}
  \makeatother
  $$ \xymatrix @!0 @R=2pc @C=4pc {
    G_1 \Times_{G_0} G_1 
    \ar[rrrr]^m 
    \ar@{}[rd] |(.2)*{}="A"
    \ar "A";[rd] _{\pr_2}
    &&&& G_1 \ar[lldd]^s\\
    & G_1 \ar[rd]_s \\
    && G_0} $$
*

Vincent Zoonekynd
<zoonek@math.jussieu.fr>
latest modification on mar ao