使 Tikz 自动节点放置工作

使 Tikz 自动节点放置工作

我发现了一些使用开发版本(2.10 以上)的 tikz 代码,我正尝试让它工作(我感觉我正在做一些相当愚蠢的事情)。

无论如何,我确认了 tikz 的正确版本正在通过第二个答案中建议的方法使用问题。

我正在尝试使用以下代码:

  \documentclass[12pt]{article}
  \usepackage{tikz}
  \usetikzlibrary{positioning,graphs}
  \begin{document}
  \begin{tikzpicture}
      \begin{graph} [circular placement,branch right,nodes={draw,circle},edges=  {>=latex}] {
"0,0,0,0" <->
    { "1,0,0,0"<->
        {"1,1,0,0"<->
         {"1,1,1,0"<->"1,1,1,1","1,1,0,0"}
        ,"1,0,1,0"<->
            {"1,1,1,0","1,0,1,1"<->"1,1,1,1"},
        "1,0,0,1"<->
            {"1,1,0,1","1,0,1,1"}
        },
    "0,1,0,0"<->
        {"1,1,0,0","0,1,1,0","0,1,0,1"<->
            {"1,1,0,1","0,1,1,1"}
        },
    ,"0,0,1,0"<->
        {"1,0,1,0","0,1,1,0","0,0,1,1"}<->
            {"1,0,1,1","0,1,1,1"<->"1,1,1,1"},
    ,"0,0,0,1"<->
        {"1,0,0,1","0,1,0,1","0,0,1,1"}
    }
};
\end{graph}
\end{tikzpicture}
\end{document}

它生成以下图表:

在此处输入图片描述

我正在寻找这个:

在此处输入图片描述

有没有办法使用 tikz 的自动节点定位来生成它?如果没有,如何使用“较旧”的语法来完成?

笔记:如果重要的话,我正在使用 2012-11-04 版本的 tikz。

答案1

也许可以使用新的图库来完成,但我采用了一种老式的方法,首先绘制节点,然后使用基本转换工具确定应该连接哪些节点。数字之间没有逗号,但这留给读者练习 :)。

\documentclass[border=0.125cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric}

\pgfmathsetbasenumberlength{4}

% Take two decimal numbers from 0 - 15, convert them
% to binary and detemine if their nodes should be
% connected.
\def\process#1#2{%
    \pgfmathdectobase{\x}{#1}{2}%
    \pgfmathdectobase{\y}{#2}{2}%
    % Expand the arguments...
    \edef\args{\x\y}%
    % ...so that the next line produces (for example)
    % \Process01000111
    \expandafter\Process\args}

% #1#2#3#4 correspond to the bits of the first number
% #5#6#7#8 correspond to the bits of the second number
\def\Process#1#2#3#4#5#6#7#8{%
    % Nodes are connected if they differ by exactly one bit.
    % So a function is required such that:
    %
    % sum(f(x_i, y_i)) = 1 for i = 1,...,n
    %
    % Where n is the number of bits, and x_i and y_i
    % are the i'th bits of the numbers x and y. 
    % The function f must return 1 if the bits are different,
    % and zero otherwise.
    %
    % Consider the function 
    %
    %   f(x,y) = (x | y) - (x & y)
    %
    % For all combinations of x and y:
    %
    % f(0, 0) = 0
    % f(1, 0) = 1
    % f(1, 1) = 0
    % f(0, 1) = 1
    %
    % So by summing this function over the bits of x and y
    % the nodes will be connected iff the sum is equal to 1
    %
    % Here I've sort of done the same thing 'by hand', and
    % separated the 'or' and 'and' operations as a separate
    % function isn't really necessary.
  \pgfmathparse{int(or(#1,#5)+or(#2,#6)+or(#3,#7)+or(#4,#8)-and(#1,#5)-and(#2,#6)-and(#3,#7)-and(#4,#8))}%
}

\begin{document}

\begin{tikzpicture}[>=stealth, 
    % Installed for every node.
    every byte/.style={
        ellipse, 
        draw,
        font=\sf,
        fill=black!50,
        text=white
},
% Set some node styles if required
0101/.style={fill=blue!20, text=black},
0001/.style={fill=red!20, text=black}]

\foreach \bytes [count=\y from 0] in {
    {0000},
    {1000,0100,0010,0001}, 
    {1100,1010,0110,1001,0101,0011}, 
    {1110,1101,1011,0111}, 
    {1111}}
    \foreach \byte [count=\x from 0] in \bytes
    % Use \byte/.try to install a style if it exists.
        \node [x=3cm, y=2cm, every byte/.try, \byte/.try] 
            % This positioning is a bit of a kludge
            at ({\x+abs(2-\y)+(mod(\y, 4)==0)/2}, -\y) 
            (\byte) {\byte};

% Now go over every combination of numbers to
% to determine if their nodes are connected.
\foreach \x in {0,...,15}{
    \foreach \y in {\x,...,15}{
        \ifnum\x=\y
        \else
            \process{\x}{\y}
            \ifnum\pgfmathresult=1
                \draw [<->] (\x) -- (\y);
            \fi
        \fi     
    }
}

\end{tikzpicture}

\end{document}

在此处输入图片描述

答案2

递归函数用于生成相同的树,但它的效率并不高,因为它需要额外的循环来将一个替换0为一个1。节点的定位与 Op 略有不同。

是的,节点的名称很愚蠢:n-{0,0,0},,n-{1,0,0}...,n-{1,1,1}。前缀n-只是为了避免括号被意外剥离。

使用\pgfutil@ifundefined{},我们可以检查某个节点是否之前已定义,并避免创建重复节点,该节点的内容与之前级别中的另一个节点递归到达的内容相同。这有一个主要缺点:
由于节点是全局定义的,因此我们不能在每个文档中拥有相同的树(具有相同位数)。可以通过\pgfid直接在节点名称中使用 或直接根据节点的 ID 进行检查(\pgfid每个节点都保存 )来解决此问题。

代码

\documentclass[tikz{standalone}
\usetikzlibrary{chains}
\makeatletter
%% Auxiliary things: \pgfMathifthenelse (used twice) and strrepeat function (used once)
\newcommand*{\pgfMathifthenelse}[1]{\pgfmathparse{#1}\ifnum\pgfmathresult=0\relax
  \expandafter\pgfutil@secondoftwo\else\expandafter\pgfutil@firstoftwo\fi}
\newcommand*{\pgfMathsetmacro}[2]{\pgfmathparse{#2}\let#1\pgfmathresult}% 2.10 fix
\pgfmathdeclarefunction{strrepeat}{2}{% from http://tex.stackexchange.com/a/120605/16595
  \begingroup\pgfmathint{#2}\pgfmath@count\pgfmathresult
    \let\pgfmathresult\pgfutil@empty
    \pgfutil@loop\ifnum\pgfmath@count>0\relax
      \expandafter\def\expandafter\pgfmathresult\expandafter{\pgfmathresult#1}%
      \advance\pgfmath@count-1\relax
    \pgfutil@repeat\pgfmath@smuggleone\pgfmathresult\endgroup}
\tikzset{
  % the number of digits is saved in /tikz/digits; a pgfmath function for easier acess
  digits/.initial=2, declare function={digits=\pgfkeysvalueof{/tikz/digits};},
  edge node/.code={% from CVS
    \expandafter\def\expandafter\tikz@tonodes\expandafter{\tikz@tonodes #1}},
  binary tree/.style 2 args={% initializes the tree, digits must be set before
    start chain/.list={ch1 going #1, ch... going #1,%
                                          ch\pgfkeysvalueof{/tikz/digits} going #1},
    /utils/exec={\pgfMathsetmacro\digits@temp{strrepeat("0,",digits-1)}
                 \edef\digits@temp{{\digits@temp0}}
                 \node [name=n-\digits@temp, alias=ch0-begin] {$\digits@temp$};},
    start tree/.expanded={0}{\digits@temp}{#2}},
  start tree/.code n args={3}{% recursive tree-ing
    \pgfmathtruncatemacro\level{#1+1}%
    \foreach \digit in {1,...,\pgfkeysvalueof{/tikz/digits}}{
      \pgfMathifthenelse{#2[\digit-1]==0}{
        \let\digits@temp\pgfutil@gobble
        \foreach \mDigit in {1, ..., \pgfkeysvalueof{/tikz/digits}}{
          \ifnum\mDigit=\digit\relax\def\pgfmathresult{1}
            \else\pgfmathparse{#2[\mDigit-1]}\fi
          \xdef\digits@temp{\digits@temp,\pgfmathresult}}
        \edef\digits@temp{{\digits@temp}}%
        \pgfutil@ifundefined{pgf@sh@ns@n-\digits@temp}{%
          \node[#3=of ch#1-begin, on chain=ch\level, alias=n-\digits@temp]
                                                                    {$\digits@temp$};
           \pgfMathifthenelse{\level+1>digits}{}{% faster stop of recursion
             \def\digits@next{\tikzset{start tree/.expanded={\level}{\digits@temp}{#3}}}}
        }{\let\digits@next\relax}
        \path ({n-#2}) edge [binary edge/.try/.expanded={\level}{\digit}]
                                                                      ({n-\digits@temp});
        \digits@next}{}}}}
\makeatother
\begin{document}
\tikz[binary tree={right}{below}]{}
\tikz[digits=3,
  binary edge/.style 2 args={->, edge node={
    node[near start, sloped, allow upside down, rotate=90, fill=white, inner sep=+2pt]
    {\scriptsize#2}}},
  binary tree={right}{below}]{}
\tikz[digits=4, binary tree={right}{below}]{}
\tikz[digits=5, node distance=0em and 1cm,
      every edge/.append style={to path=(\tikztostart.east) -- (\tikztotarget.west)},
      binary tree={above}{right}]{}
\end{document}

输出

在此处输入图片描述在此处输入图片描述在此处输入图片描述在此处输入图片描述

相关内容