Matrix
It seems that a TikZ \matrix
is the easiest approach here.
Combined with the execute at empty cell
which fills the matrix automatically and the continous edges to
style, you can create this diagram very fast.
Though, the arrows follow a pattern which can be automated, too:
This is done with the keys matrix connector urr
(up-right, right) and matrix connector ldd
(left-down, down) which initial a search algorithm that relies on named nodes in the matrix.
Code
\documentclass[tikz,convert=false]{standalone}
\usetikzlibrary{matrix}
\makeatletter
\tikzset{
@continous edges to/.style={insert path={edge (#1) (#1)}},
continous edges to/.style={@continous edges to/.list={#1}},
matrix connector urr/.code args={#1-#2-#3}{%
\pgfutil@ifundefined{pgf@sh@ns@#1-\the\numexpr#2-1\relax-\the\numexpr#3+1\relax}{%
\pgfutil@ifundefined{pgf@sh@ns@#1-#2-\the\numexpr#3+1\relax}{}{
\tikzset{insert path={(#1-#2-#3) edge (#1-#2-\the\numexpr#3+1\relax)},
matrix connector ldd/.expanded={#1-#2-\the\numexpr#3+1\relax}}%
}%
}{%
\tikzset{insert path={(#1-#2-#3) edge (#1-\the\numexpr#2-1\relax-\the\numexpr#3+1\relax)},
matrix connector urr/.expanded={#1-\the\numexpr#2-1\relax-\the\numexpr#3+1\relax}}%
}
},
matrix connector ldd/.code args={#1-#2-#3}{%
\pgfutil@ifundefined{pgf@sh@ns@#1-\the\numexpr#2+1\relax-\the\numexpr#3-1\relax}{%
\pgfutil@ifundefined{pgf@sh@ns@#1-\the\numexpr#2+1\relax-#3}{}{%
\tikzset{insert path={(#1-#2-#3) edge (#1-\the\numexpr#2+1\relax-#3)},
matrix connector urr/.expanded={#1-\the\numexpr#2+1\relax-#3}}%
}%
}{%
\tikzset{insert path={(#1-#2-#3) edge (#1-\the\numexpr#2+1\relax-\the\numexpr#3-1\relax)},
matrix connector ldd/.expanded={#1-\the\numexpr#2+1\relax-\the\numexpr#3-1\relax}}%
}
},
}
\makeatother
\begin{document}
\begin{tikzpicture}
\matrix (m) [
matrix of nodes,
nodes={
shape=circle,
inner sep=+.1667em,% half the default value
},
execute at empty cell={\node {$S_{\the\pgfmatrixcurrentrow\the\pgfmatrixcurrentcolumn}$};},
row sep=2em,
column sep=2em
] {
& & & \\
& & & \\
& & & \\
& & & \\
};
\path[->, ultra thick, matrix connector urr={m-1-1}];
\path[->,white, shorten >=2\pgflinewidth] (m-1-1) [continous edges to={m-1-2, m-2-1, m-3-1, m-2-2, m-1-3, m-1-4, m-2-3, m-3-2, m-4-1}];
\end{tikzpicture}
\end{document}
Output
Chains
An alternative approach, similar to Jubobs' answer, can be implemented with the chains
library where one can use the placement options of the positioning
library (i.e. on grid
, node distance
) for greater control. It is only used to place the nodes that are connected.
Code
\documentclass[tikz,convert=false]{standalone}
\usetikzlibrary{chains}
\newcommand*{\subscript}[3][]{%
\ifodd#2
\the\numexpr#2+1-#3\relax#1#3%
\else
#3#1\the\numexpr#2+1-#3\relax
\fi}
\tikzset{
zigzag/.code 2 args={%
\ifnum#1>1
\ifodd#1
\ifnum#2=1
\def\position{below}%
\else
\def\position{above right}%
\fi
\else
\ifnum#2=1
\def\position{right}%
\else
\def\position{below left}%
\fi
\fi
\tikzset{\position=of \tikzchainprevious}
\fi
},
zigzag*/.code={%
\edef\llevel{\number\tikzchaincount}%
\pgfmathloop
\edef\testllevel{\the\numexpr\llevel-\pgfmathcounter\relax}%
\ifnum1>\testllevel\relax
\let\level\pgfmathcounter
\else
\let\llevel\testllevel
\repeatpgfmathloop
\tikzset{zigzag=\level\llevel}%
}
}
%
\tikzset{
every label/.append style={inner sep=+0pt, outer sep=+0pt, font=\tiny},
label position=above left,
every join/.append style={-latex},
}
\begin{document}
\begin{tikzpicture}[
start chain=ch going {zigzag=\level\llevel},
node distance=.75cm and 1cm,
every on chain/.append style={
join, label={(\number\tikzchaincount)}}]
\foreach \level in {1,...,4}
\foreach \llevel in {1,...,\level}
\node[on chain=ch] {$S_{\subscript[,]\level\llevel}$};
\end{tikzpicture}
\begin{tikzpicture}[
on grid, node distance=1cm and 1.5cm, start chain=ch placed zigzag*,
every on chain/.append style={
circle, inner sep=+.1667em, text depth=+0pt, text height=+1.5ex,
join, label/.expanded={(\noexpand\subscript[/]{\level}{\llevel})}}]
\foreach \cnt in {a,...,f} \node[on chain=ch] {\cnt};
\foreach \cnt in {G,...,M} \node[on chain=ch] {\cnt};
\end{tikzpicture}
\end{document}
Output
circle,fill=blue!20,draw
.\matrix
or eventikz-cd
come to mind. You could also simplify the connecting of the nodes or creating the matrix.