3

I know that there are several posts about colouring matrices rows and columns, but I was trying to create a diagram to show matrix multiplication, and ended up with the following code, which is a bit empirical and a bit clumsy. I was wondering if there wasn't a more intelligent way to do the same thing.

\documentclass{article}

\usepackage{tikz} \usetikzlibrary{matrix,positioning,calc}

\begin{document} \begin{tikzpicture}[ every node/.style={minimum height=14pt,minimum width=1em}, every matrix/.style={matrix of math nodes, column sep=1mm, row sep=1mm, left delimiter=(, right delimiter=)}] \fill[red!10] (-1,-6pt) rectangle (1,6pt); \fill[red!10] (4.8,0) ++(-7pt,-1) rectangle +(13pt,2); \fill[red!10] (10.3,0) ++(-7pt,-6pt) rectangle +(13pt,15pt); \matrix (A) at (0,0) { \phantom{\bullet} & & \ \bullet & \cdots & \bullet \ \phantom{\bullet} & & \ }; \matrix (B) at (4.5,0) { \phantom{\bullet} & \phantom{\bullet} & \bullet & \phantom{} \ & & |[rotate=90]| \dots & \ & & \bullet & \ }; \matrix (AB) at (10,0) { \phantom{\bullet} & \phantom{\bullet} & \phantom{\bullet} & \phantom{\bullet} \ \phantom{\bullet} & \phantom{\bullet} & \bullet & \phantom{} \ & & & \ \phantom{\bullet} & & & \ }; \node[left=3mm] at (A.west) {\tikz\draw[semithick,<->] (0,0) -- (0,2) node[midway,anchor=center,fill=white] {$m$};}; \node[above=-1mm] at (A.north) {\tikz\draw[semithick,<->] (0,0) -- (2,0) node[midway,anchor=center,fill=white] {$p$};}; \node[left=3mm] at (B.west) {\tikz\draw[semithick,<->] (0,0) -- (0,2) node[midway,anchor=center,fill=white] {$p$};}; \node[above=-1mm] at (B.north) {\tikz\draw[semithick,<->] (0,0) -- (2.5,0) node[midway,anchor=center,fill=white] {$n$};}; \node[left=3mm] at (AB.west) {\tikz\draw[semithick,<->] (0,0) -- (0,2) node[midway,anchor=center,fill=white] {$m$};}; \node[above=-1mm] at (AB.north) {\tikz\draw[semithick,<->] (0,0) -- (2.5,0) node[midway,anchor=center,fill=white] {$n$};}; \node at ($(A)!0.45!(B)$) {$\times$}; \node at ($(B)!0.45!(AB)$) {$=$}; \node[below] (a) at (A.south) {row $i$}; \node[below] (b) at (B.south) {column $j$}; \node[below] (ab) at (AB.south) {$(i,j)$-cell}; \node at ($(a)!0.45!(b)$) {$\times$}; \node at ($(b)!0.45!(ab)$) {$=$}; \end{tikzpicture}

\end{document}

Thank you for any help to make this a bit better.

Logos
  • 419
  • In case you are interested: https://texample.net/tikz/examples/matrix-multiplication/ – Sigur Apr 13 '21 at 17:51
  • You could avoid some redundancies (\phantom{\bullet}, \tikz\draw[semithick,<->], [midway,anchor=center,fill=white]) to begin with, but this way is fairly acceptable, in my opinion. – SebGlav Apr 13 '21 at 17:53

2 Answers2

4

I think that if you are satisfied with the result, the code is not so important but here you have another version.

It uses some properties of matrix to automatically color desired rows or columns. Also with a nodes in empty cells you don't need \phantom`.

You used nested tikz commands to draw matrix dimensions. I thinks it's wrong.

In this case the lower expression is drawn from right to left in order to easily align all elements.

\documentclass{article}

\usepackage{tikz} \usetikzlibrary{matrix,positioning,calc}

\begin{document} \begin{tikzpicture}[ every matrix/.style={matrix of math nodes, nodes in empty cells, nodes={minimum size=5mm, anchor=center}, left delimiter=(, right delimiter=)}]

\matrix[row 2/.style={nodes={fill=red!10}}] (A) { & & \ \bullet & & \bullet \ & & \ }; \matrix[column 3/.style={nodes={fill=red!10}}, right=2cm of A] (B) { & & \bullet & \ & & & \ & & \bullet & \ }; \matrix[right=2cm of B] (AB) { & & & \ & &|[fill=red!10]| \bullet & \ & & & \ & & & \ };

\node at (A-2-2) {$\dots$}; \node[rotate=90] at (B-2-3) {$\dots$};

\draw[semithick,<->] ([xshift=-1.5em]A.south west) -- ([xshift=-1.5em]A.north west) node[midway,fill=white, inner xsep=1pt] {$m$}; \draw[semithick,<->] ([xshift=-1.5em]B.south west) -- ([xshift=-1.5em]B.north west) node[midway,fill=white, inner xsep=1pt] {$p$}; \draw[semithick,<->] ([xshift=-1.5em]AB.south west) -- ([xshift=-1.5em]AB.north west) node[midway,fill=white, inner xsep=1pt] {$m$};

\draw[semithick,<->] ([yshift=.5em]A.north west) -- ([yshift=.5em]A.north east) node[midway,anchor=center,fill=white] {$p$}; \draw[semithick,<->] ([yshift=.5em]B.north west) -- ([yshift=.5em]B.north east) node[midway,anchor=center,fill=white] {$n$}; \draw[semithick,<->] ([yshift=.5em]AB.north west) -- ([yshift=.5em]AB.north east) node[midway,anchor=center,fill=white] {$n$};

\node[below=0pt of AB.south] (ab) {$(i,j)$-cell}; \node at (B.center|-ab) (j) {column $j$}; \node at (A.center|-ab) (i) {row $i$};

\node at ($(A)!0.45!(B)$) (times) {$\times$}; \node at ($(B)!0.45!(AB)$) (equal) {$=$}; \node at (i-|times) {$\times$}; \node at (i-|equal) {$=$}; \end{tikzpicture}

\end{document}

enter image description here

Ignasi
  • 136,588
  • I am not really happy with my code, because I empirically found the places for the bars and I generally prefer that the program worked out these things instead of going by trial and error. Your solution looks nice: I'm going to try it straight away. Thank you. – Logos Apr 13 '21 at 19:38
  • Sorry for asking again, but your product matrix has more rows than it should be. Is there a way to the number of rows with the first one? – Logos Apr 13 '21 at 19:42
  • Never mind, i figured it out :) – Logos Apr 13 '21 at 19:43
2

2021/06/23: I've edited this answer because, with the latest version of nicematrix (5.16 of 2021/06/20), it's possible to avoid the use of transparency.


Here is a version with {NiceTabular} of nicematrix (and Tikz using PGF/Tikz nodes created by {NiceTabular}.

\documentclass{article}
\usepackage{nicematrix}
\usepackage{tikz}
\usetikzlibrary{fit}
\usepackage{mathtools}
\usepackage{xcolor}

\begin{document}

\setcounter{MaxMatrixCols}{20}

[\def\s{\hspace*{1em}}% only a shortcut to avoid lines of code too long \begin{NiceMatrix}[nullify-dots,columns-width=4mm] \CodeBefore [create-cell-nodes] \begin{tikzpicture} [every node/.style = {rectangle,fill=red!15,inner sep = 3pt}] \node [fit = (3-2)(3-4)] {} ; \node [fit = (2-8)(4-8)] {} ; \node [fit = (3-13)] {} ; \end{tikzpicture} \Body \ & & & & && \s & \bullet & \s & && \s & & \[2mm] & \bullet & \Cdots & \bullet & \times && & \Vdots & & = && & \bullet & \[2mm] & & & & && & \bullet & & && & & \s \ & & \mathclap{\text{row } i} & & \times && & \mathclap{\text{column } j} & & = && & \mathclap{(i,j)\text{-cell}} \ \CodeAfter \SubMatrix({2-2}{4-4}) \SubMatrix({2-7}{4-9}) \SubMatrix({2-12}{4-14}) \begin{tikzpicture} [every node/.style= {fill=white},every path/.style = <->] \draw [<->] (1.5-|2) to node {$p$} (1.5-|5) ; \draw [<->] (1.5-|7) to node {$n$} (1.5-|10) ; \draw [<->] (1.5-|12) to node {$n$} (1.5-|15) ; \draw [<->] (2-|1.5) to node {$m$} (5-|1.5) ; \draw [<->] (2-|6.5) to node {$p$} (5-|6.5) ; \draw [<->] (2-|11.5) to node {$m$} (5-|11.5) ; \end{tikzpicture} \end{NiceMatrix}]

\end{document}

You need several compilations (because the PGF/Tikz nodes are constructed with remember picture).

Output of the above code

In order to show the construction, here is the output when the key hvlines is added to {NiceTabular} (the output is wider because of the width of all the vertical rules).

Output when adding the key hvlines

F. Pantigny
  • 40,250
  • This looks lovely, but when I copied it and tried to compile it gave me the error of \CodeAfter undefined. Am I missing something? – Logos Apr 13 '21 at 19:33
  • Your TeX installation is probably not up-to-date. You should update it. If you use Overleaf, you must upload the latest version of the file nicematrix.sty in the repertory of your Overleaf project. You can find that file on the SVN server of TeXLive: www.tug.org/svn/texlive/trunk/Master/texmf-dist/tex/latex/nicematrix/nicematrix.sty. – F. Pantigny Apr 13 '21 at 19:39
  • I have MacTeX, but once there was an app for updates, but it is a few years it has disappeared and I cannot do any longer the weekly updates. I shall try to see if I can download a new MacTeX version. Thank you – Logos Apr 13 '21 at 19:41