By which pkg to visualize a hypercube graph?
This can also be done with TikZ and a \matrix
(or tikz-cd
) though it gets complicated for more than three dimensions.
Here is a approach that shifts every already placed node for dimension n in the dimension n + 1, n + 2, …, n total and connects it with its parent node (->
).
The \currentTransform
macro is setup in a way that it contains for every node all applied transformation (from 0-0
), this is used to connect the nodes in their own dimension (<->
). (A good reason for a grouped \foreach
loop.)
Code
\documentclass[tikz,convert=false]{standalone}
% a little support for all the keys
\def\hyperset{\pgfqkeys{/tikz/hyper}}
\tikzset{hypher/.code=\hyperset{#1}}
% Dimension setup
\hyperset{
set color/.code 2 args={\colorlet{tikz@hyper@dimen@#1}{#2}},
set color={0}{black},
set color={1}{blue!50!black},
set color={2}{red},
set color={3}{green},
set color={4}{yellow!80!black}}
\hyperset{
set dimens/.style args={#1:(#2)}{
dimen #1/.style={/tikz/shift={(#2)}}},
set dimens=0:(0:0),
set dimens=1:(right:1),
set dimens=2:(up:1),
set dimens=3:(30:.75),
set dimens=4:(180+70:.5),
every hyper node/.style 2 args={%
shape=circle,
inner sep=+0pt,
fill,
draw,
minimum size=+3pt,
color=tikz@hyper@dimen@#1,
label={[hyper/label #1/.try, hyper/dimen #1 style/.try]#1-#2}
},
every hyper edge/.style={draw},
every hyper shift edge/.style={->,tikz@hyper@dimen@#1!80},
every normal hyper edge/.style={<->,tikz@hyper@dimen@#1!40},
}
\newcommand*{\hyper}[1]{% #3 = max level
\def\currentTransform{}
\node[hyper/every hyper node/.try={0}{0}, hyper/dimen 0 node/.try] (0-0) {};
\hyperhyper{0}{0}{#1}}
\newcommand*{\hyperhyper}[3]{% #1 = current level
% #2 = current number
% #3 = maxlevel
\foreach \dimension in {#3,...,\the\numexpr#1+1\relax} {
\edef\newNumber{\the\numexpr#2+\dimension\relax}
\node[hyper/every hyper node/.try={\dimension}{\newNumber}, hyper/dimen \dimension node/.try, hyper/dimen \dimension\space style/.try] at ([hyper/dimen \dimension] #1-#2) (\dimension-\newNumber) {};
\path (#1-#2) edge[hyper/every hyper edge/.try=\dimension, hyper/every hyper shift edge/.try=\dimension, hyper/dimen \dimension\space style/.try] (\dimension-\newNumber);
\ifnum\newNumber>\dimension\relax
\foreach \oldShift in \currentTransform {
\if\relax\detokenize\expandafter{\oldShift}\relax\else
\path (\dimension-\newNumber) edge[hyper/every hyper edge/.try=\dimension, hyper/every normal hyper edge/.try=\dimension, hyper/dimen \dimension\space style/.try] (\dimension-\the\numexpr\newNumber-\oldShift\relax);
\fi
}
\fi
\edef\currentTransform{\dimension,\currentTransform}%
\ifnum\dimension<#3\relax
\edef\temp{{\dimension}{\the\numexpr#2+\dimension\relax}{#3}}
\expandafter\hyperhyper\temp
\fi
}
}
\tikzset{
@only for the animation/.style={
hyper/dimen #1 style/.style={opacity=0}}}
\begin{document}
\foreach \DIM in {0,...,4,4,3,...,0} {
\begin{tikzpicture}[
>=stealth,
scale=3,
every label/.append style={font=\tiny,inner sep=+0pt}, label position=above left,
@only for the animation/.list={\the\numexpr\DIM+1\relax,...,5}
]
\hyper{4}
\end{tikzpicture}}
\end{document}
Output
Algorithm (beamer
, step-for-step)
I'm going to interpret "hypercube" as a way of specifying a graph.
I use LaTeX3 to do some conversions between integers and binary, and to make the various recursions easier. Then TikZ does the actual rendering.
(It could do with a clean-up with regard to temporary variables, and a few styling options would be a reasonable addition.)
\documentclass{article}
%\url{http://tex.stackexchange.com/q/129613/86}
\usepackage[landscape]{geometry}
\usepackage{tikz}
\usepackage{expl3}
\usepackage{xparse}
\ExplSyntaxOn
\int_new:N \l__binp_int
\int_set:Nn \l__binp_int {4}
\tl_new:N \l__bina_tl
\tl_new:N \l__binb_tl
\tl_new:N \l__binhw_tl
\int_new:N \l__bina_int
\int_new:N \l__binb_int
\int_new:N \l__binc_int
\int_new:N \l__bind_int
\fp_new:N \l__bina_fp
\DeclareDocumentCommand \BinaryPrecision {m}
{
\int_set:Nn \l__binp_int {#1}
}
\cs_new_nopar:Npn \int_to_bin:Nn #1#2
{
\tl_clear:N #1
\int_set:Nn \l__bina_int {#2}
\prg_replicate:nn {\l__binp_int}
{
\int_set:Nn \l__binb_int {\int_mod:nn {\l__bina_int} {2}}
\tl_put_left:Nx #1 {\int_use:N \l__binb_int}
\int_set:Nn \l__bina_int {\int_div_truncate:nn {\l__bina_int} {2}}
}
}
\cs_new_nopar:Npn \bin_hamming_weight:NN #1#2
{
\tl_set_eq:NN \l__binhw_tl #2
\tl_replace_all:Nnn \l__binhw_tl {0} {}
\int_set:Nn #1 {\tl_count:N \l__binhw_tl}
}
\cs_new_nopar:Npn \bin_flip_one:NNn #1#2#3
{
\tl_set_eq:NN #2#1
\prg_replicate:nn {#3 - 1}
{
\tl_replace_once:Nnn #2 {1} {a}
}
\tl_replace_once:Nnn #2 {1} {0}
\tl_replace_all:Nnn #2 {a} {1}
}
\DeclareDocumentCommand \HammingWeight {m m}
{
\int_to_bin:Nn \l__binhw_tl {#2}
\bin_hamming_weight:NN #1 \l__binhw_tl
}
\DeclareDocumentCommand \HyperCube {m}
{
\int_set:Nn \l__binp_int {#1}
\int_zero_new:c {l__hyper_0_int}
\int_set:cn {l__hyper_0_int} {-1}
\int_step_inline:nnnn {1} {1} {#1}
{
\int_zero_new:c {l__hyper_##1_int}
\int_set:cn {l__hyper_##1_int} {\int_use:c {l__hyper_\int_eval:n {##1 - 1}_int} * (#1 - ##1 + 1) / ##1}
}
\fp_set:Nn \l__bina_fp {2^{#1}-1}
\int_set:Nn \l__binc_int {\fp_to_int:N \l__bina_fp}
\int_step_inline:nnnn {0} {1} {\l__binc_int}
{
\int_to_bin:Nn \l__bina_tl {##1}
\bin_hamming_weight:NN \l__binb_int \l__bina_tl
\node[every~ hypercube~ label/.try] (hg- \l__bina_tl) at (\int_use:c {l__hyper_\int_use:N \l__binb_int _int},\int_use:N \l__binb_int) {##1};
\int_incr:c {l__hyper_\int_use:N \l__binb_int _int}
\int_incr:c {l__hyper_\int_use:N \l__binb_int _int}
}
\int_step_inline:nnnn {0} {1} {\l__binc_int}
{
\int_to_bin:Nn \l__bina_tl {##1}
\bin_hamming_weight:NN \l__binb_int \l__bina_tl
\int_step_inline:nnnn {1} {1} {\l__binb_int}
{
\bin_flip_one:NNn \l__bina_tl \l__binb_tl {####1}
\draw[every~ hypercube~ edge/.try] (hg- \l__bina_tl) -- (hg- \l__binb_tl);
}
}
}
\ExplSyntaxOff
\begin{document}
\begin{tikzpicture}
\HyperCube{3}
\end{tikzpicture}
\begin{tikzpicture}
\HyperCube{4}
\end{tikzpicture}
\begin{tikzpicture}
\HyperCube{5}
\end{tikzpicture}
\end{document}
Here a possibility to visualize the 3-hypercube which you show with PSTricks:
% arara: latex
% arara: dvips
% arara: ps2pdf
\documentclass[preview,border=3pt]{standalone}
\usepackage{pst-node}
\begin{document}
\begin{psmatrix}[mnode=circle,colsep=0.8,rowsep=0.8]
& [name=8] 8 \\[-0.4\psyunit]
[name=5] 5 & [name=6] 6 & [name=7] 7\\
[name=2] 2 & [name=3] 3 & [name=4] 4\\[-0.4\psyunit]
& [name=1] 1
\ncline{8}{5}\ncline{8}{6}\ncline{8}{7}
\ncline{5}{3}\ncline{5}{2}
\ncline{6}{2}\ncline{6}{4}
\ncline{7}{3}\ncline{7}{4}
\ncline{1}{2}\ncline{1}{3}\ncline{1}{4}
\ncline[offset=5pt, linewidth=0.5\pslinewidth, arrows=->, nodesep=5pt]{1}{2}
\ncarc[offset=3pt, linewidth=0.5\pslinewidth, arrows=->, nodesep=4pt]{2}{5}
\end{psmatrix}
\end{document}
This gives:
But I don't know of any package capable of doing the N-th hypercube automatically.