Show sparse matrices like chessboards

With a fairly natural syntax:

\documentclass{article}
\usepackage{amsmath}

\newlength{\sparsesize}
\setlength{\sparsesize}{12pt}

\newcommand{\sparsezero}{%
  \begingroup
  \setlength{\fboxsep}{-0.2pt}%
  \setlength{\fboxrule}{0.2pt}%
  \fbox{\hspace{\sparsesize}\rule{0pt}{\sparsesize}}%
  \endgroup
}
\newcommand{\sparseone}{\rule{\sparsesize}{\sparsesize}}
\newcommand{\activate}[2]{%
  \begingroup\lccode`~=`#1\lowercase{\endgroup\let~}#2%
  \mathcode`#1="8000
}

\newenvironment{sparsematrix}
 {%
  \renewcommand{\arraystretch}{0}%
  \setlength{\arraycolsep}{0pt}%
  \activate{0}{\sparsezero}\activate{1}{\sparseone}%
  \begin{matrix}%
 }
 {\end{matrix}}

\begin{document}

\[
\begin{pmatrix}
0 & 1 & 0 \\
1 & 0 & 1 \\
0 & 1 & 0
\end{pmatrix}
=
\begin{sparsematrix}
0 & 1 & 0 \\
1 & 0 & 1 \\
0 & 1 & 0
\end{sparsematrix}
\]

\end{document}

enter image description here

For general matrices with integer coefficients it's a bit more difficult.

\documentclass{article}
\usepackage{amsmath,xparse}

\newlength{\sparsesize}
\setlength{\sparsesize}{12pt}
\newcommand{\sparsezero}{%
  \begingroup
  \setlength{\fboxsep}{-0.2pt}%
  \setlength{\fboxrule}{0.2pt}%
  \fbox{\hspace{\sparsesize}\rule{0pt}{\sparsesize}}%
  \endgroup
}
\newcommand{\sparseone}{\rule{\sparsesize}{\sparsesize}}

\ExplSyntaxOn
\NewDocumentEnvironment{sparsematrix}{b}
 {
  \renewcommand{\arraystretch}{0}%
  \setlength{\arraycolsep}{0pt}%
  {% make a subformula
   \begin{matrix}
   \eagleone_sparsematrix:n { #1 }
   \end{matrix}
  }
 }{}

\seq_new:N \l__eagleone_sparsematrix_rows_seq
\seq_new:N \l__eagleone_sparsematrix_row_in_seq
\seq_new:N \l__eagleone_sparsematrix_row_out_seq

\cs_new_protected:Nn \eagleone_sparsematrix:n
 {
  \seq_set_split:Nnn \l__eagleone_sparsematrix_rows_seq { \\ } { #1 }
  \seq_map_function:NN \l__eagleone_sparsematrix_rows_seq \__eagleone_sparsematrix_row:n
 }
\cs_new_protected:Nn \__eagleone_sparsematrix_row:n
 {
  \seq_set_split:Nnn \l__eagleone_sparsematrix_row_in_seq { & } { #1 }
  \seq_map_inline:Nn \l__eagleone_sparsematrix_row_in_seq
   {
    \int_compare:nTF { ##1 = 0 }
     {
      \seq_put_right:Nn \l__eagleone_sparsematrix_row_out_seq { \sparsezero }
     }
     {
      \seq_put_right:Nn \l__eagleone_sparsematrix_row_out_seq { \sparseone }
     }
   }
  \seq_use:Nn \l__eagleone_sparsematrix_row_out_seq { & } \\
 }

\ExplSyntaxOff

\begin{document}

\[
\begin{pmatrix}
0 & 1 & 0 \\
1 & 0 & 1 \\
0 & 1 & 0
\end{pmatrix}
=
\begin{sparsematrix}
0 & 1 & 0 \\
1 & 0 & 1 \\
0 & 1 & 0
\end{sparsematrix}
\]

\[
\begin{sparsematrix}
0 & 1 & 0 \\
1 & 0 & 1 \\
0 & 1 & 0
\end{sparsematrix}^2
=
\begin{sparsematrix}
1 & 0 & 1 \\
0 & 2 & 0 \\
1 & 0 & 1
\end{sparsematrix}
\]

\end{document}

enter image description here


With TikZ this is rather straightforward.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix}
\begin{document}
\begin{tikzpicture}[0/.style={draw,ultra thin},1/.style={0,fill=black}]
 \matrix[matrix of nodes,cells={minimum size=1.5em,anchor=center}]
 {|[0]| & |[1]| & |[0]| \\
 |[1]| & |[0]| & |[1]|\\
 |[0]| & |[1]| & |[0]|\\
 };
\end{tikzpicture}
\end{document}

enter image description here

If you have a simple pattern as this one, you could also do

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix}
\begin{document}
\begin{tikzpicture}[my cell/.style={/utils/exec={%
 \pgfmathtruncatemacro{\itest}{mod(\the\pgfmatrixcurrentrow+\the\pgfmatrixcurrentcolumn,2)}
 \ifnum\itest=1
 \pgfkeysalso{/tikz/fill=black}
 \fi}}]
 \matrix[matrix of nodes,nodes in empty cells,
 nodes={minimum size=1.5em,anchor=center,draw,ultra thin,my cell}]
 { &  &  \\
  &  & \\
  &  & \\
 };
\end{tikzpicture}
\end{document}

An addendum, just for fun. It is rather similar to @egreg's nice answer, in fact \sparsezero, \sparseone and the name of the environment are just stolen from there. The difference is that instead of making 0 and 1 active characters collcell is employed, which is also hacky but arguably less violent. It defines a new column type that just employs a macro. However, extending the entries to larger values will be as easy to add a few \ors to the \ifcase, so I feel that this may be easier to customize than egreg's nice solution this is conceptually building on.

\documentclass[12pt]{article}
\usepackage{amsmath}
\usepackage{array}
\usepackage{collcell}
\newlength{\sparsesize}
\setlength{\sparsesize}{12pt}
\newcommand{\sparsezero}{%
  \begingroup
  \setlength{\fboxsep}{-0.2pt}%
  \setlength{\fboxrule}{0.2pt}%
  \fbox{\hspace{\sparsesize}\rule{0pt}{\sparsesize}}%
  \endgroup
}
\newcommand{\sparseone}{\rule{\sparsesize}{\sparsesize}}
\newcommand{\sparseentry}[1]{\ifcase#1
\sparsezero
\or
\sparseone
\fi}
\newcolumntype{F}{>{\collectcell\sparseentry}c<{\endcollectcell}}
\newenvironment{sparsematrix}
 {%
  \renewcommand{\arraycolsep}{0pt}%
 \renewcommand{\arraystretch}{0}%
  \begin{array}{*{20}{F}}%
 }
 {\end{array}}
\begin{document}
\[
\begin{sparsematrix}
0 & 1 & 0 \\
1 & 0 & 1 \\
0 & 1 & 0 \\
\end{sparsematrix}=\begin{pmatrix}
0 & 1 & 0 \\
1 & 0 & 1 \\
0 & 1 & 0 \\
\end{pmatrix}
\]
\end{document}

Tags:

Matrices