39

I just read a book "Linear Algebra and Its Applications 4E" by David C. Lay. The book is (should be) LaTeX typeset. The matrix and equations are so nice, please see the following 3 examples:

enter image description here

enter image description here

enter image description here

It's so beautiful, so I want get the same effect inside my paper. Here is my code:

\usepackage{amsmath}
\usepackage{colortbl}
\newcommand\y{\cellcolor{clight2}}
\definecolor{clight2}{RGB}{212, 237, 244}%

%%%
\[A=\left[
\begin{array}{ccccc}
\y 0 & -3 & -6 & 4 & 9 \\   
-1 & \y -2 & -1 & 3 & 1 \\
-2 & -3 & 0 & \y 3 & -1 \\
1 & 4 & 5 & -9 & -7     
\end{array}
\right]\]

\[A=\left[\begin{array}{cccccc}
\rowcolor{clight2}
3 & -9 & 12 & -9 & 6 & 15\\
0 & 2 & -4 & 4 & 2 & -6 \\
0 & 3 & -6 & 6 & 4 & -5
\end{array}
\right]\]

And the result:

enter image description here

But how to add these arrows??

gernot
  • 49,614
ZYX
  • 727
  • 2
    Probably you can do that with tikzmark, see http://tex.stackexchange.com/questions/57101/highlight-a-column-in-equation-or-math-environment ; notice that there is a new version of the package, see http://tex.stackexchange.com/questions/295903/refer-to-a-node-in-tikz-that-will-be-defined-in-the-future-two-passes – Rmano Mar 31 '17 at 08:05
  • @Rmano It could very easily be done using tikzmark (you'd use \tikzmarknode) but I think that the answer using the nicematrix package is the right one for this – Andrew Stacey Aug 18 '22 at 09:14

3 Answers3

57

Use the command

\tikznode[..options..]{..label..}{..contents..}

to mark the contents that the arrows should point to. To add arrows and text, use

\begin{tikzpicture}[remember picture,overlay]
  ... tikz code using the labels defined by \tikznode ...
\end{tikzpicture}

Define the command \tikznode in the preamble as

\usepackage{tikz}
\newcommand\tikznode[3][]%
   {\tikz[remember picture,baseline=(#2.base)]
      \node[minimum size=0pt,inner sep=0pt,#1](#2){#3};%
   }

You have to run LaTeX at least twice until the information about the positions has propagated everywhere.

enter image description here

\documentclass{article}
\usepackage{tikz}
\usepackage{amsmath}
\usepackage{colortbl}
\newcommand\y{\cellcolor{clight2}}
\definecolor{clight2}{RGB}{212, 237, 244}%
\newcommand\tikznode[3][]%
   {\tikz[remember picture,baseline=(#2.base)]
      \node[minimum size=0pt,inner sep=0pt,#1](#2){#3};%
   }
\tikzset{>=stealth}
\renewcommand\vec[1]{\mathbf{#1}}
\begin{document}
%%%
\[A=\left[
\begin{array}{rrrrr}
\y \tikznode{pp1}{$0$} & -3 & -6 & 4 & 9 \\   
-1 & \y -\tikznode{pp2}{$2$} & -1 & 3 & 1 \\
-2 & -3 & 0 & \y \tikznode{pp3}{$3$} & -1 \\
\tikznode{pc1}{$1$} & \tikznode{pc2}{$4$} & 5 & -\tikznode{pc3}{$9$} & -7     
\end{array}
\right]\]
\vspace{3ex}

\[A=\left[\begin{array}{rrrrrr}
\rowcolor{clight2}
3 & -9 & 12 & -9 & 6 & 15\\
0 & \tikznode{piv}{$2$} & -4 & 4 & 2 & -6 \\
0 & \tikznode{npc}{$3$} & -6 & 6 & 4 & -5
\end{array}
\right]\]
\vspace{3ex}

\[\tikznode{u1v1}{$(u_1+v_1)$}\tikznode{a1}{$\vec a_1$}
  + \tikznode{u2v2}{$(u_2+v_2)$}\tikznode{a2}{$\vec a_2$}
\]

\begin{tikzpicture}[remember picture,overlay,cyan,rounded corners]
  % explicit coordinates are relative to the end of arrow,
  % they do not accumulate (note the single + preceding the coords)
  % "Pivot positions"
  \draw[<-,shorten <=1pt] (pp1)
    -- +(0.4,0)% short line to the right
    |- +(4,0.4)% short up and long right
    coordinate (pp)% remember position for other arrows
    node[right] {Pivot positions};
  \draw[<-,shorten <=1pt] (pp2)
    -- +(0.4,0)% short line to the right
    |- (pp);% up and right to pp
  \draw[<-,shorten <=1pt] (pp3)
    -- +(0.4,0)% short line to the right
    |- (pp);% up and right to pp
  % "Pivot columns"
  \draw[<-,shorten <=2pt] (pc1)
    -- +(0,-0.5)% short line down
    coordinate (pc1')% remember position for computing next coord
    -- (pc1'-|pp)% horizontal line to position right of pc1' and below of pp
    coordinate (pcs)% remember position for other arrows
    node[right] {Pivot columns};
  \draw[<-,shorten <=2pt] (pc2)
    |- (pcs);% down and right to pcs
  \draw[<-,shorten <=2pt] (pc3)
    |- (pcs);% down and right to pcs
  % "Pivot"
  \draw[<-,shorten <=1pt] (piv)
    -- +(0.4,0)% short line to the right
    |- +(1,0.8)% up and right
    node[right] {Pivot};
  % "New Pivot column"
  \draw[<-,shorten <=2pt] (npc)
    |- +(1,-0.5)% down and right
    node[right] {New Pivot column}; 
  % "Entries in u+v"
  \draw[<-] (u1v1)
    |- +(4,0.5)% short up and long right
    coordinate (uv)% remember position for other arrow and other label
    node[right]{Entries in $\vec u+\vec v$};
  \draw[<-] (u2v2)
    |- (uv);% up and right to uv
  % "Columns of A"
  \draw[<-] (a1)
    -- +(0,-0.5)% short line down
    coordinate (a1')% name position for computing next coord
    -- (a1'-|uv)% horizontal line to position right of a1' and below of uv
    coordinate (a)% remember position for other arrow
    node[right]{Columns of $A$};
  \draw[<-] (a2)
   |- (a);% down and right to a
\end{tikzpicture}
\end{document}

If you prefer pointed corners like in the original, remove the option rounded corners.

enter image description here

gernot
  • 49,614
  • 9
    +1. Your \tikznode should become a feature of \tikzmark package! – CarLaTeX Mar 31 '17 at 16:34
  • @gernot What should I change if I want multiple matrices in the same line, uncentered and not different lines, each centered? – reyna Apr 16 '20 at 07:36
  • 1
    @zaira I don't completely understand what you want to achieve. My impression is that it is unrelated to adding arrows. Once you have figured out how to arrange the matrices, you can add arrows as described above. I suggest that you post a separate question with a sketch showing the desired arrangement of matrices. You may also take a look at the answers to maybe related problems, like https://tex.stackexchange.com/q/9901/110998, https://tex.stackexchange.com/q/145952/110998, https://tex.stackexchange.com/q/74443/110998, – gernot Apr 16 '20 at 09:00
  • @gernot I had trouble with alignment, actually. Instead of centre, I wanted them to be left aligned but I have figured out a way. Thanks! – reyna Apr 16 '20 at 10:05
  • @CarLaTeX It is. It's called \tikzmarknode. The history of it is a little complicated since this is what the original tikzmark did, then that evolved and \tikzmarknode stepped into the vacant evolutionary niche. – Andrew Stacey Feb 04 '21 at 18:54
  • @AndrewStacey Thanks for the info, I think \tikzmarknode did not exist when I wrote the comment – CarLaTeX Feb 04 '21 at 19:02
  • @CarLaTeX Quite possibly. There was a time when I stripped it back to its core positioning functionality, but then I realised the original version was still useful so put it back in. – Andrew Stacey Feb 04 '21 at 19:38
  • @AndrewStacey Good to know. I'm still a bit reluctant to advocate the use of another package if all it takes is a basic command that users should be aware of anyway (when doing anything tikz-related). – gernot Feb 04 '21 at 19:48
  • @gernot Given the size of TikZ then loading tikmark is not much! Nevertheless, I take your point. However, there are a few other useful bits and bobs in the tikzmark package so if someone is loading it anyway then they may as well use it instead of defining it again. It's come a long way since its first use here in https://tex.stackexchange.com/a/316/86 – Andrew Stacey Feb 04 '21 at 20:07
  • @AndrewStacey It's not really about the size of packages, but about the attitude of users (and their feeling of impotence), if the answer to every question is "Load this package and use that new macro". Ideally, there should be a limited set of commands (and packages) that would allow an ordinary user (or at least one affine to computers) to solve most problems. But I will take a look at tikzmark & friends ... – gernot Feb 04 '21 at 20:20
  • @gernot Absolutely! Tikzmark only became a package when it started doing non-trivial things. For example, tikzmarknode detects the math mode and sets it correctly inside. That's a bit complicated with regard to the labellings and means that it is no longer a simple macro. – Andrew Stacey Feb 04 '21 at 20:40
  • Superb...Nice one... – MadyYuvi Nov 05 '21 at 14:15
  • 1
    Very nice indeed. Out of my mind.... – Mikasa Jan 31 '23 at 16:18
6

For the pictures with the matrices, you can draw the arrows with Tikz by using the Tikz nodes created by {bNiceMatrix} of nicematrix.

\documentclass{article}
\usepackage{nicematrix,tikz}

\begin{document}

$A = \begin{bNiceMatrix}[margin,r] \CodeBefore \cellcolor{cyan!15}{1-1,2-2,3-4} \Body 0 & -3 & -6 & 4 & 9 \ -1 & -2 & -1 & 3 & 1 \ -2 & -3 & 0 & 3 & -1 \ 1 & 4 & 5 & -9 & -7 \ \CodeAfter \begin{tikzpicture} [cyan,<-] \draw (1-1.east) -| ([xshift=1mm,yshift=2mm]1-|2) -- ([yshift=2mm]1-|last) -- ++(5mm,0) node [right] {Pivot positions} ; \draw (2-2.east) -| ([xshift=1mm,yshift=2mm]1-|3) ; \draw (3-4.east) -| ([xshift=1mm,yshift=2mm]1-|5) ; \draw (4-1.south) ++(0,-2pt) |- ([yshift=-2mm]5-|last) -- ++(5mm,0) node [right] {Pivot columns} ; \draw (4-2.south) ++(0,-2pt) |- ([yshift=-2mm]5-|4-2) ; \draw (4-4.south) ++(0,-2pt) |- ([yshift=-2mm]5-|4-4) ; \end{tikzpicture} \end{bNiceMatrix}$

\end{document}

You need several compilations (because nicematrix uses PGF/Tikz nodes under the hood).

Output of the above code

F. Pantigny
  • 40,250
2

The existing answers focus primarily on the matrix part of the question. In this answer, I'm going to focus on the equation. Although this is in gernot's answer, it is missing a crucial feature: spacing relative to the rest of the mathematics.

For this, I use the tikzmark TikZ library. Tikzmark has evolved considerably since its first appearance in http://tex.stackexchange.com/a/316/86 (in 2010) where in its initial form it was very similar to the command \tikznode that gernot uses in their answer. In the intervening decade, it split into two parts: \tikzmark, which focusses on just remembering a position, and \tikzmarknode, which is based on the original command but with added extras such as detecting the current math mode.

To get the spacing right, we need both. We use \tikzmarknode to mark the relevant parts of the equation. Then in a later tikzpicture we place the annotation nodes at their correct places relative to the equation. We also use \tikzmark (which can work both inside and outside a tikzpicture environment) to remember certain locations inside this tikzpicture. These locations are then used earlier to set the spacing of the annotated line.

There is a subtlety here. This all relies on locations of pieces of the page being written out to the aux file and then read back in on the next run. So each time, the locations are actually one compilation out of date. This can lead to bits of text jumping around and never settling down. In particular, if the location of A depends on the previous position of B, and that of B on the previous position of A then it can end up in a loop. The solution is to build in a level of relative positioning. So that instead of B depending on the previous position of A, it depends on the previous position of A relative to some other point that is chosen to avoid the loop.

Here's the code:

\documentclass{article}
%\url{https://tex.stackexchange.com/q/361375/86}
\usepackage{amsmath}
\usepackage{tikz}
\usetikzlibrary{tikzmark,calc,arrows.meta}

\let\vec=\mathbf

\begin{document}

\begin{align} A(\vec{u} + \vec{v}) &= \begin{bmatrix} \vec{a}_1 & \vec{a}_2 & \vec{a}_3 \end{bmatrix} \begin{bmatrix} u_1 + v_1 \ u_2 + v_2 \ u_3 + v_3 \end{bmatrix} \ % % The various \tikzmarknodes here allow us to refer back to these % terms &= \tikzmarknode{uv1}{(u_1 + v_1)} \tikzmarknode{a1}{\vec{a}_1} + \tikzmarknode{uv2}{(u_2 + v_2)} \tikzmarknode{a2}{\vec{a}_2} + \tikzmarknode{uv3}{(u_3 + v_2)} \tikzmarknode{a3}{\vec{a}_3} % This is a bit like a vertical strut; it ensures that there is enough % vertical space for the annotations \tikz[remember picture,baseline={(0,0)}] {\path let \p1=(pic cs:upper), \p2=(pic cs:lower), \p3=(pic cs:middle) in (0,\y1-\y3) (0,\y2-\y3);} \ % &= (u_1 \vec{a}_1 + u_2 \vec{a}_2 + u_3 \vec{a}_3) + (v_1 \vec{a}_1 + v_2 \vec{a}_2 + v_3 \vec{a}_3) \ % &= A \vec{u} + A \vec{v} \end{align}

\begin{tikzpicture}[remember picture, overlay,>=Latex, cyan] % locate the annotations \node[above right] (entries) at ($(a3.north east)+(1,.5)$) {Entries in (\vec{u} + \vec{v})}; \node[below right] (columns) at ($(a3.south east)+(1,-.5)$) {Columns of (A)}; % Draw the lines \draw[<-,rounded corners] (uv1.north) |- (entries); \draw[<-,rounded corners] (uv2.north) |- (entries); \draw[<-,rounded corners] (uv3.north) |- (entries); \draw[<-,rounded corners] (a1.south) |- (columns); \draw[<-,rounded corners] (a2.south) |- (columns); \draw[<-,rounded corners] (a3.south) |- (columns); % These three are used mark the extent of the annotations % Although a3.base is in the same place as the tikzmark a3, these % three tikzmarks need to be all defined in the same tikzpicture % so that their relative positions are always the same \tikzmark{upper}{(entries.north)} \tikzmark{lower}{(columns.south)} \tikzmark{middle}{(a3.base)} \end{tikzpicture}

\end{document}

Here's the result:

Using tikzmark to space out lines in an annotated equation

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751