Tuesday, May 15, 2018

Grouping Rows of a Matrix

I spent a large chunk of yesterday afternoon doing something I thought would be simple (relatively speaking) in LaTeX. I wanted to group rows of a matrix (actually, in my case, a vector) with right braces, and label the groups. An example of what I wanted is in the image below.


This seems to me to be a fairly common thing to do, and LaTeX has been around over 35 years (TeX even longer), so by now it must be pretty easy. Right? Um, not so much. I wore out Google looking for packages that would do this. Curiously, it's easy to put braces over and under things:
  • $\overbrace{[x_1,\dots,x_n]}$ [\overbrace{[x_1,\dots,x_n]}];
  • $\underbrace{[x_1,\dots,x_n]}$ [\underbrace{[x_1,\dots,x_n]}].
There are packages to let you surround matrices, arrays etc. with a variety of delimiters (not just parentheses or square brackets). Nowhere, though, could I find a command or package to do the above.

Fortunately, something pointed me in the direction of the PGF/TiKZ package, which I've used in the past for doing drawings. It's an incredible tool in terms of both what it can do and the outstanding quality of its manual. Because it does so many things, I've never really gotten to know all its capabilities, and in particular its ability to do matrices in a picture environment.

Here is the code to do my illustration. You need to load the TiKZ package and two of its libraries in your document preamble, as follows:

\usepackage{tikz}
\usetikzlibrary{matrix, decorations.pathreplacing}

The code for the drawing is:

\begin{tikzpicture}
 \matrix (vec) [matrix of math nodes, left delimiter = {[}, right delimiter = {]}] {
f_1 \\
\vdots \\
f_{a} \\
f_{a + 1} \\
\vdots \\
f_{b} \\
f_{b + 1} \\
\vdots \\
f_{c} \\
};
\node (a) at (vec-1-1.north) [right=20pt]{};
\node (b) at (vec-3-1.south) [right=20pt]{};
\node (c) at (vec-4-1.north) [right=20pt]{};
\node (d) at (vec-6-1.south) [right=20pt]{};
\node (e) at (vec-7-1.north) [right=20pt]{};
\node (f) at (vec-9-1.south) [right=20pt]{};
\draw [decorate, decoration={brace, amplitude=10pt}] (a) -- (b) node[midway, right=10pt] {\footnotesize something};
\draw [decorate, decoration={brace, amplitude=10pt}] (c) -- (d) node[midway, right=10pt] {\footnotesize something else};
\draw [decorate, decoration={brace, amplitude=10pt}] (e) -- (f) node[midway, right=10pt] {\footnotesize something silly};
\end{tikzpicture}

The name of the matrix ("vec") is arbitrary. The amplitude for the brace (10pt) and the offsets (10pt and 20pt) are matters of taste.

If you happen to know a faster way of doing this, please do share in a comment.

2 comments:

  1. I've been looking for this, but had a similar experience to yours. So I just transposed the matrix and used underbraces.

    ReplyDelete
    Replies
    1. You know, it never occurred to me to do that. That's definitely much simpler, although fitting it without line wrapping might get tricky in some cases.

      It's also reassuring to know that I'm not the only one who couldn't find the equivalent of underbraces for the side margins. :-)

      Delete

Due to intermittent spamming, comments are being moderated. If this is your first time commenting on the blog, please read the Ground Rules for Comments. In particular, if you want to ask an operations research-related question not relevant to this post, consider asking it on Operations Research Stack Exchange.