我正在尝试将超立方体可视化为下图。我已寻求帮助这里但是将节点与包放在一起。第 N 个超立方体有 2^n 个节点,每个顶点的度数为 n。我正在尝试找到一种方法来可视化度数更大的超立方体,这对 pkg 来说是一个很大的挑战。我的目标是可视化立方体的遍历。您将如何进行这种可视化?
关于第 3 个超立方体的示例(8 个节点,每个顶点的度为 3)
答案1
我将把“超立方体”解释为指定图形的一种方式。
我使用 LaTeX3 进行整数和二进制之间的转换,并使各种递归更容易。然后 TikZ 进行实际渲染。
(它可以对临时变量进行清理,并且一些样式选项将是一个合理的补充。)
\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}
答案2
\matrix
这也可以使用 TikZ 和 a (或)来实现,tikz-cd
尽管对于三维以上的空间来说会变得复杂。
这是一种将每个已经放置的节点移动到维度的方法n在维度中n+ 1,n+ 2,…,n 总计并将其与其父节点(->
)连接起来。
宏\currentTransform
的设置方式是,它包含每个节点的所有应用转换(来自0-0
),这用于连接节点在其自己的维度中(<->
)。(分组\foreach
循环的一个很好的理由。)
代码
\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}
输出
算法(beamer
,逐步)
答案3
这里可以使用 PSTricks 来可视化 3 超立方体:
% 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}
得出:
但我不知道有哪个包能够自动完成第 N 个超立方体。
答案4
作为替代方案,这里是tikz-cd
原始图像/Op 的真实请求的版本。
代码
\documentclass[tikz,convert=false]{standalone}
\usepackage{tikz-cd}
\tikzset{
shorten/.style={/tikz/shorten >={#1},/tikz/shorten <={#1}}}
\begin{document}
\begin{tikzcd}[
every arrow/.append style={-,thick},
matrix of math nodes maybe/.append style={/tikz/cells={/tikz/nodes={/tikz/draw,/tikz/shape=circle,align=center,text width=\widthof{$x_1x_2x_3$}}}},
row sep=large,
column sep=large,
thick,
]
& x_1x_2x_3 \dar \dlar \drar \\
x_1x_2 & x_1 x_3 \dlar \drar & x_2x_3 \\
x_1 \uar
\uar[bend left=20, shorten=.1cm, -stealth]
& x_2 \ular \urar & x_3 \uar\\
& \emptyset \uar \ular \urar \ular[shift left=.25cm, shorten=.25cm, -stealth]
\end{tikzcd}
\end{document}