# Formatting arrows between rows of corresponding matrices

Some material I'm creating requires output that looks like this:
(note the position of the arrows).

I'm using the following code (with the AMS macros) to generate this, and I'm looking for comments - it works fine, but I'm curious if there's a better/cleaner way to deal with the arrows:

$\begin{bmatrix}[rrr|r] 1 & 2 & 0 & -1 \\ 2 & 1 & 1 & 1 \\ -1 & 1 & -1 & -1 \end{bmatrix} \begin{matrix}[c] ~ \\ \xrightarrow{R_2-2R_1} \\ \xrightarrow{R_3+R_1} \end{matrix} \begin{bmatrix}[rrr|r] 1 & 2 & 0 & -1 \\ 0 & -3 & 1 & 3 \\ 0 & 3 & -1 & -2 \end{bmatrix} \begin{matrix}[c] ~ \\ ~ \\ \xrightarrow{R_2+R_3} \end{matrix} \begin{bmatrix}[rrr|r] 1 & 2 & 0 & -1 \\ 0 & -3 & 1 & 3 \\ 0 & 0 & 0 & 1 \end{bmatrix}$


I'm using only the standard AMS macros, together with a cute addition to the matrix macros that I found on the Web that allows column specifications within the AMS matrices:

\makeatletter
\renewcommand*\env@matrix[1][*\c@MaxMatrixCols c]{%
\hskip -\arraycolsep
\let\@ifnextchar\new@ifnextchar
\array{#1}}
\makeatother

-
I'm not really sure what would constitute a good answer to this question... –  Seamus Sep 16 '10 at 12:47
How long will it take for the first TikZ solution to appear? ;) (won’t be from me this time — I think your solution together with TH’s macro is fine.) –  Caramdir Sep 16 '10 at 14:30
The problem is that if anything in the matrices vary in height, the arrows will not align vertically with the matrix rows without corresponding fudging. –  Niel de Beaudrap Sep 16 '10 at 15:20
I'm pondering the TikZ solution ... the specifications that I'm thinking of are: the rows of different matrices should align and the separations between the matrices should stretch with the arrows and their accompanying text. That makes it somewhat non-trivial. –  Loop Space Sep 16 '10 at 19:13

## 6 Answers

I can't offer anything other than making your arrows into a simple macro to make it easier to type. Something like

\newcommand\arrows[3]{
\begin{matrix}[c]
\ifx\relax#1\relax\else \xrightarrow{#1}\fi\\
\ifx\relax#2\relax\else \xrightarrow{#2}\fi\\
\ifx\relax#3\relax\else \xrightarrow{#3}\fi
\end{matrix}
}


You'd use it like \arrows{}{R_2-2R_1}{R_3+R_1}

Maybe it'd be better to explicitly pass in the number of rows, like this.

\newcount\arrowcount
\newcommand\arrows[1]{
\global\arrowcount#1
\ifnum\arrowcount>0
\begin{matrix}[c]
\expandafter\nextarrow
\fi
}

\newcommand\nextarrow[1]{
\global\advance\arrowcount-1
\ifx\relax#1\relax\else \xrightarrow{#1}\fi
\ifnum\arrowcount=0
\end{matrix}
\else
\\
\expandafter\nextarrow
\fi
}


You'd use it like \arrows3{}{}{R_2+R_3}. It seems to work for your example.

-

One way to do this is implemented in the (free, in both senses!) online linear algebra textbook Linear Algebra by Jim Hefferon. It's written in LaTeX and is open-source so one can download the book and its attendant style files. One of them, called linalgjh.sty is about typesetting common linear algebra stuff such as augmented matrices and row reductions and the like. The code for the row reductions is:

%--------grstep
% For denoting a Gauss' reduction step.
% Use as: \grstep{\rho_1+\rho_3} or \grstep[2\rho_5 \\ 3\rho_6]{\rho_1+\rho_3}
\newcommand{\grstep}[2][\relax]{%
\ensuremath{\mathrel{
{\mathop{\longrightarrow}\limits^{#2\mathstrut}_{
\begin{subarray}{l} #1 \end{subarray}}}}}}
\newcommand{\swap}{\leftrightarrow}


and is used as:

\documentclass{article}
\usepackage{amsmath}
\usepackage{linalgjh}
\thispagestyle{empty}
\begin{document}

$\begin{bmatrix} -1&2&-1&-2\\ % 2&-3&4&1\\ % 2&3&1&-2 \end{bmatrix} % \grstep[R_3 + 2 R_1]{R_2 + 2 R_1} % \begin{bmatrix} -1&2&-1&-2\\ % 0&1&2&-3\\ % 0&7&-1&-6 \end{bmatrix}$
\end{document}


This produces:

This isn't quite the same as in the question, I freely admit, so may not be a Good Answer as far as the original questioner is concerned. However, someone else looking at this question might not be so bothered about the arrows being aligned on the rows and so this might suffice. Also, the linalgjh package is worth mentioning more than once, as is the text book that it was developed to produce.

That style file has several other useful linear algebra macros that may be useful (I previously mentioned it in answer to this question).

-
I was initially confused when the textbook I was writing for used the aligned-arrows notation. But I came to realize that it's actually pretty clear visually, while the notation above is unclear as to which rows are being modified in what manner. In any case, TH's answer seems just about as easy to use, and more flexible. Thanks. –  rogerl Sep 17 '10 at 17:25
@rogerl: I decided not to comment on the style in my answer, but since you raise it then my instinct is that I don't like aligning the row ops with the rows. Which will you align a row swap with? Also, getting more than two matrices on a line is overcrowding and the alignment doesn't have the same effect when line-breaking occurs. But then I'm not convinced that this sort of notation is at all clear, so don't take any notice of me! –  Loop Space Sep 17 '10 at 18:37
I just use a centered arrow with R_i \leftrightarrow R_j above it for row swaps. Not optimal, I agree. Any such notation is going to be awkward in one way or another, as you say, but in the tradeoff between incredible verbosity (saying all the transitions in words) and some awkwardness but more brevity, I choose brevity. –  rogerl Sep 17 '10 at 20:11

as i see it, the problem is that the rows of the matrices are too close together. if they were farther apart, the arrows should be able to align.

a fix for this is provided by the array package (from the latex tool set). with this, you can specify (for example)

\setlength{\extrarowheight}{3pt}


and that will space out the rows. this should be done outside the affected display, and will continue in effect thereafter, so if you don't want it everywhere, you either need to turn it off after the affected display(s), or limit its scope by appropriate grouping.

-
Thanks. I probably should have known that but didn't. Is that the right way to increase row spacing so that for example you can use display-style fractions in arrays as well? –  rogerl Sep 17 '10 at 17:22
it may be part of the story. –  barbara beeton Sep 17 '10 at 17:51
if you have side-by-side matrices only some of whose cells have displaystyle fractions, you will probably also need to use some \vphantom{\displaystyle\frac12} so that there is at least one "tall" cell in each row of each matrix, so they have parallel structure. then \extrarowheight can be used for fine tuning. it will most likely be a somewhat iterative process. –  barbara beeton Sep 17 '10 at 17:54

I present the following answer in the fervent hope that someone, anyone can provide an equivalent response which does not involve XyPic.

### Answer

You must \usepackage{xypic} or equivalent in the pre-amble.

\newcommand\map[1]{\xrightarrow{#1}} % For brevity
$\xymatrix @R0em @C0.5ex { & & & \ar@{-}[dddd] & & & & & & \ar@{-}[dddd] & & & & & & \ar@{-}[dddd] & \\ 1 & 2 & 0 & & -1 & & 1 & 2 & 0 & & -1 & & 1 & 2 & 0 & & -1 \\ 2 & 1 & 1 & & 1 & \map{R_2-2R_1} & 0 & 3 & -1 & & 3 & & 0 & 3 & -1 & & 3 \\ -1 & 1 & -1 & & -1 & \map{R_3+R_1} & 0 & 3 & -1 & & -2 & \map{R_2+R_3} & 0 & 0 & 0 & & -1 \\ & & & & & & & & & & & & & & & & ~ \POS"2,1"."4,1"."2,5"."4,5"!C*+<0.5pt>\frm{)} \POS"2,1"."4,1"."2,5"."4,5"!C*+<0.5pt>\frm{(} \POS"2,7"."4,7"."2,11"."4,11"!C*+<0.5pt>\frm{)} \POS"2,7"."4,7"."2,11"."4,11"!C*+<0.5pt>\frm{(} \POS"2,13"."4,13"."2,17"."4,17"!C*+<0.5pt>\frm{)} \POS"2,13"."4,13"."2,17"."4,17"!C*+<0.5pt>\frm{(} }$


### Reasons why I hate this answer

The following complaints are intended with no disrespect to the authors of XyPic, who went to a lot of work to make a package which is quite versatile — but whose time has passed in my opinion.

1. Xypic is slow. In my experience, if you put more than a handful of smallish \xymatrix-ces in your document, it will bog down compilation time.

2. It requires extra rows and columns to implement the "sub-matrix" bars: the \ar@{-}[dddd] commands implement vertical lines four rows high in the specified columns, which are necessary to span the three rows of the "actual" matrices. It must do so in its own column, and in so doing it unbalances the horizontal spacing between the final two columns of each matrix.

3. It is extremely cryptic. For instance, unless you are an expert in XyPic, it will be difficult to decipher the final four \POS lines, which implement the round parentheses about the matrices. (And these commands break if you don't insert some dummy material such as the ~ character in the last row!)

4. Why have I put round parentheses instead of square ones, in the arguments to \frm (which produce round parentheses for the matrices)? It's not because I prefer round parentheses; it's because there doesn't seem to be a way to put square ones. The possible decorations, which are described on page 25 of the XyPic guide, does not include them.

In short: it is inefficient, it is clumsy, it is not flexible enough, and the code is uglier than I would like. The only reason why I have any clue how even to write this is because, for a time, the best available tool to automatically draw quantum circuit diagrams was qcircuit.tex, which is based on XyPic. I needed to learn it to try and hack my own figures.

### If I hate this answer, why am I posting it?

Because:

• I foresee having to write exactly these sorts of matrix transformations in my future,
• Some answer which ensures proper vertical alignment is better than no answer,
• I hope that if I'm snarky enough, someone will improve this solution using their superior TiKZ-fu or something, and everyone will live happily ever after.
-

Here is a different clumsy solution to your problem --- but which is better than the earlier solution I presented using XyPics.

The basic principle is the same: you put all of your matrices into a single super-matrix. Then, you use horizontal spacing to introduce your matrix delimiters into the middle of your super-matrix, where the 'logical' matrices begin and end, thusly:

\newcommand\map[1]{\xrightarrow{#1}} % For brevity
$\left.\left.\left.\left.\left[ \begin{array}{rrr|rcrrr|rcrrr|r} 1 & 2 & 0 & -1 & & 1 & 2 & 0 & -1 & & 1 & 2 & 0 & -1 \\ 2 & 1 & 1 & 1 & \map{R_2-2R_1} & 0 & 3 & -1 & 3 & & 0 & 3 & -1 & 3 \\ -1 & 1 & -1 & -1 & \map{R_3+R_1} & 0 & 3 & -1 & -2 & \map{R_2+R_3} & 0 & 0 & 0 & -1 \end{array}\right] \mspace{-448mu}\right] \mspace{70mu}\right[ \mspace{125mu}\right] \mspace{60mu}\right[$


The first \right] is the final square-bracket for your matrices; we do this first in order to ensure that at least this delimiter is in Knuth-standard position. All the other delimiters are positioned by manually choosing how much forward or backward it should be from the last one produced.

(This obviously only works if the matrix transformations are the only, or the last, object in your math environment; otherwise, you should produce the matrix delimiters in sequence, ending with the last one, in order for the subsequent mathematics to follow in the correct location in your equation.)

I dislike this solution because of the necessity of manually choosing the spacing — among other things, you will have to modify the spacing each time you modify the matrices. But at least if you change your matrices incrementally, the spacing also needs only incremental changes; and this solution is otherwise robust and flexible.

Ideally, one could use some mechanism to determine precisely how to position the delimiters correctly; but I don't have enough TeXpertise to know how. Can anyone help?

-

Here is a solution that shows up like in the O.P. question (operation on a row described on the same line as the row. I define a rowops macro with only one argument, the row operations being comma-separated. It requires xparse and xifthen.

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{fourier}
\usepackage{heuristica}

\usepackage{mathtools}
\usepackage{xifthen, xparse}

\thispagestyle{empty}

\newcommand\rowop[1]{\scriptstyle\smash{\xrightarrow[\vphantom{#1}]{\mkern-4mu#1\mkern-4mu}}}

\DeclareDocumentCommand\converttorows%
{>{\SplitList{,}}m}%
{\ProcessList{#1}{\converttorow}}
\NewDocumentCommand{\converttorow}{m}
{\ifthenelse{\isempty{#1}}{}{\rowop{#1}}\\}

\DeclareDocumentCommand \rowops{m}
{\;
\begin{matrix}
\converttorows {#1}
\end{matrix}
\; }

\begin{document}

$\begin{bmatrix} -1&2&-1&-2\\ % 2&-3&4&1\\ % 2&3&1&-2 \end{bmatrix} % \rowops{,R_2 + 2R_1,R_3 + 2R_1} % \begin{bmatrix} -1&2&-1&-2\\ % 0&1&2&-3\\ % 0&7&-1&-6 \end{bmatrix}$

\end{document}


-