使用 TikZ 进行伯努利实验的概率树?

使用 TikZ 进行伯努利实验的概率树?

考虑下面的树。有没有一种简单的方法来标记每个左边缘 q、每个右边缘 p、每个左节点 f 和每个右节点 r,而无需手动对每个级别进行标记?

第二个问题:有没有一个好的方法可以将这个伯努利过程树示例推广到 n 级?

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{trees}
\begin{document}
\pagestyle{empty}



\tikzstyle{level 1}=[level distance=3.5cm, sibling distance=6cm]
\tikzstyle{level 2}=[level distance=3.5cm, sibling distance=3cm]
\tikzstyle{level 3}=[level distance=3.5cm, sibling distance=2cm]


\tikzstyle{bag} = [text centered,circle,draw,inner sep=0.3em]
\tikzstyle{head} = [inner sep=0pt]

\begin{tikzpicture} %
   \node[head] {} %
   child { %
     node[bag] {} %
     child{ %
       node[bag]{}
       child { %
         node[bag, label=below: %
         {$a$}] {} %
       } %
       child { %
         node[bag, label=below: %
         {$b$}] {} %
       } %
     }%
 child{ %
       node[bag]{}
       child { %
         node[bag, label=below: %
         {$c$}] {} %
       } %
       child { %
         node[bag, label=below: %
         {$d$}] {} %
       } %
     }%
   }
   child { %
     node[bag] {} %
     child{ %
       node[bag]{}
       child { %
         node[bag, label=below: %
         {$e$}] {} %
       } %
       child { %
         node[bag, label=below: %
         {$f$}] {} %
       } %
     }%
 child{ %
       node[bag]{}
       child { %
         node[bag, label=below: %
         {$g$}] {} %
       } %
       child { %
         node[bag, label=below: %
         {$h$}] {} %
       } %
     }%
   }; %             %
         \end{tikzpicture}

      \end{document}

答案1

我正在研究类似的东西,但我需要研究这个代码(实际上没有时间)您可以查看\pgfqkeys{/berntree}以查看所有选项。限制是 5,但使用循环方法来构建这棵树会很好!我做了一些修改,现在您可以修改样式:node success style一个node miss style。要在每个分支的末尾添加一些标签,您可以使用最后的节点(这不是很容易),对于边缘上的标签,您可以使用edge style。代码不是很好,因为箭头在某些节点内,最好为每个节点提供相同的大小。版本 4:edge style/.style = {->,>=latex',shorten <= 6pt}针对边缘的问题,查看标签的最终循环。我修复了大小的节点

\documentclass{scrartcl}
\usepackage{pgf,tikz} 
\usetikzlibrary{trees,arrows,calc} 

\makeatletter
\newcount\tkz@Berndepth
\newdimen\tkz@BernLEN
\tkz@BernLEN=24em 
\def\tkzBernTreeSet#{\pgfqkeys{/berntree}} 

\pgfqkeys{/berntree}{%
  success/.code      = \def\tkz@bern@success{#1},
  miss/.code         = \def\tkz@bern@miss{#1},
  p/.code            = \def\tkz@bern@pbsuccess{#1},
  q/.code            = \def\tkz@bern@pbmiss{#1},
  node success style/.style  = {inner sep=2pt,outer sep=3pt},
  node miss style/.style  = {inner sep=2pt,outer sep=3pt},
  edge style/.style  = {->,>=latex',shorten <= 6pt},
  root style/.style  = {draw,circle},
  success/.initial   = S,
  miss/.initial      = E, 
  p/.initial         = $p$,
  q/.initial         = $1-p$,
  gap/.code          = \def\tkz@bern@gap{#1},
  length/.code       = \def\tkz@bern@length{#1} 
} 

\def\tkz@brntree#1#2{%
  \node[/berntree/root style] {};
\global\advance\tkz@Berndepth 1\relax
\begin{scope}[level distance=\tkz@bern@length,
              level 1/.style={sibling distance=#2}]   
  \node[] (root) at (#1) {}     
  [grow=right]
  child[/berntree/edge style] {%
    node[/berntree/node miss style](tkz@E\the\tkz@Berndepth) {\tkz@bern@miss} 
            edge from parent node[fill=white] {\tkz@bern@pbmiss}}
  child [/berntree/edge style] {%
    node[/berntree/node success style] (tkz@S\the\tkz@Berndepth) {\tkz@bern@success} 
            edge from parent node[fill=white] {\tkz@bern@pbsuccess}
             };
\end{scope}}% 

\def\tkzBernTree{\pgfutil@ifnextchar[{\tkz@BernTree}{\tkz@BernTree[]}}
\def\tkz@BernTree[#1]#2{%
\begingroup  
\pgfqkeys{/berntree}{%
success = S,
miss= E,
node success style/.style  = {inner sep=2pt,outer sep=3pt,draw,minimum width=1.5em,minimum height=1.5em},
node miss style/.style  = {inner sep=2pt,outer sep=3pt,circle,draw,minimum width=1.5em},
p=$p$,
q=$q$,
gap=8cm,
length=3cm} 
\pgfqkeys{/berntree}{#1}
  \tkz@BernLEN=\tkz@bern@gap\relax    
  \tkz@Berndepth 0\relax 
  \node (tkz@S0) at (0,0){}; 
\def\tkz@bn@level{#2} 
 \ifcase\tkz@bn@level%
 \or% 
  \tkz@brntree{tkz@S0}{\tkz@BernLEN} 
 \or% 
   \tkz@brntree{tkz@S0}{\tkz@BernLEN} 
  \divide \tkz@BernLEN by 2 %
 \foreach \nd in {1}{   
   \tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
   \tkz@brntree{tkz@E\nd}{\tkz@BernLEN}}
 \or%
   \tkz@brntree{tkz@S0}{\tkz@BernLEN}  
   \divide \tkz@BernLEN by 2 %
 \foreach \nd in {1}{   
   \tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
   \tkz@brntree{tkz@E\nd}{\tkz@BernLEN}}   
  \divide \tkz@BernLEN by 2 %
 \foreach \nd in {2,3}{   
   \tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
   \tkz@brntree{tkz@E\nd}{\tkz@BernLEN}} 
 \or% 
   \tkz@brntree{tkz@S0}{\tkz@BernLEN}  
   \divide \tkz@BernLEN by 2 %
 \foreach \nd in {1}{   
   \tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
   \tkz@brntree{tkz@E\nd}{\tkz@BernLEN}}   
  \divide \tkz@BernLEN by 2 %
 \foreach \nd in {2,3}{   
   \tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
   \tkz@brntree{tkz@E\nd}{\tkz@BernLEN}} 
  \divide \tkz@BernLEN by 2 %
 \foreach \nd in {4,5,6,7}{   
   \tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
   \tkz@brntree{tkz@E\nd}{\tkz@BernLEN}}    
  \or% 
   \tkz@brntree{tkz@S0}{\tkz@BernLEN}  
   \divide \tkz@BernLEN by 2 %
 \foreach \nd in {1}{   
   \tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
   \tkz@brntree{tkz@E\nd}{\tkz@BernLEN}}   
  \divide \tkz@BernLEN by 2 %
 \foreach \nd in {2,3}{   
   \tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
   \tkz@brntree{tkz@E\nd}{\tkz@BernLEN}} 
  \divide \tkz@BernLEN by 2 %
 \foreach \nd in {4,...,7}{   
   \tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
   \tkz@brntree{tkz@E\nd}{\tkz@BernLEN}} 
   \divide \tkz@BernLEN by 2 %
 \foreach \nd in {8,...,15}{   
   \tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
   \tkz@brntree{tkz@E\nd}{\tkz@BernLEN}}   
 \fi   
 \endgroup
 }
\makeatother
\begin{document}

 \begin{tikzpicture}[yscale=1.2]
\tkzBernTree[root style/.style  = {fill,circle,outer sep =1pt,inner sep=2pt}]{4}
\makeatletter 
 \foreach \num/\lab in {8/a,9/c,10/e,11/g,12/i,13/k,14/m,15/o}{%
 \node at ($(tkz@S\num)+(2,0)$){$\lab$};
 } 
  \foreach \num/\lab in {8/b,9/d,10/f,11/h,12/j,13/l,14/n,15/p}{%
 \node at ($(tkz@E\num)+(2,0)$){$\lab$};
 }  
\makeatother  
 \end{tikzpicture} 

\end{document}

在此处输入图片描述

答案2

与往常一样,对于来说,这是一项相对容易的任务forest

参考:TikZ - 每个左/右边缘的标签相同

代码

\documentclass[tikz]{standalone}
\usepackage{forest}
\tikzset{
  root node/.style={shape=circle, fill, draw, inner sep=+0pt, minimum size=+7pt},
  el style/.style={pos=.4, inner sep=+.5pt, font=\scriptsize, fill=white},
  lr style/.style={inner sep=+1pt, minimum size=+1.2em, draw}}
\newcounter{myCounter}
\forestset{
  left node/.style ={content=E,
    edge label={node[el style]{$p$}},
    node options={shape=circle,    lr style}},
  right node/.style={content=S,
    edge label={node[el style]{$q$}},
    node options={shape=rectangle, lr style}},
  bernoulli/.style={edge=-latex,
    if={level()<#1}{
      append={[,bernoulli={#1}, left node]}, append={[,bernoulli={#1}, right node]}
    }{
      /utils/exec=\stepcounter{myCounter},
      append/.expanded={[$\salph{myCounter}$, edge={draw=none}]}}}}
\newcommand*\salph[1]{%
  \ifnum\csname c@#1\endcsname>26 \the\csname c@#1\endcsname\else\alph{#1}\fi}
\begin{document}
\begin{forest} 
[,bernoulli={5}, root node]
\end{forest}
\end{document}

输出

在此处输入图片描述

答案3

如果您愿意在代码中区分所使用的样式(bagr/bagl),以下是我的看法(纯文本)。我还添加了一些\struts 以使底部标签对齐。最重要的是 -part edge from parent path。起初我以为我可以\tikzchildnode立即获得坐标,但有趣的是,它会返回到0pt任何地方,所以我不得不使用calc库来获取某种可比较的尺寸。

\input tikz
\usetikzlibrary{calc}
\tikzpicture[
  level/.style={sibling distance=6cm/#1, level distance=3.5cm},
  bag/.style={text centered, circle, draw, inner sep=0.3em},
  bagl/.style={bag, label=left:$f$},
  bagr/.style={bag, label=right:$r$},
  head/.style={inner sep=0pt},
  edge from parent path={
    let \p0=(\tikzparentnode),
        \p{center}=($(\tikzparentnode) !.5! (\tikzchildnode) $) in
      (\tikzparentnode) -- (\tikzchildnode)
      \ifdim\x0>\x{center}
        node [pos=.5,left] {$q$}
      \else
        node [pos=.5,right] {$p$}
      \fi
    }
  ]
   \node[head] {}
   child {
     node[bagl] {}
     child{
       node[bagl]{}
       child {
         node[bag, label=below:
         {$\mathstrut a$}] {}
       }
       child {
         node[bag, label=below:
         {$\mathstrut b$}] {}
       }
     }
 child{
       node[bagr]{}
       child {
         node[bag, label=below:
         {$\mathstrut c$}] {}
       }
       child {
         node[bag, label=below:
         {$\mathstrut d$}] {}
       }
     }
   }
   child {
     node[bagr] {}
     child{
       node[bagl]{}
       child {
         node[bag, label=below:
         {$\mathstrut e$}] {}
       }
       child {
         node[bag, label=below:
         {$\mathstrut f$}] {}
       }
     }
 child{
       node[bagr]{}
       child {
         node[bag, label=below:
         {$\mathstrut g$}] {}
       }
       child {
         node[bag, label=below:
         {$\mathstrut h$}] {}
       }
     }
   };
\endtikzpicture
\bye

边标签

我怀疑有更简单的方法可以解决这一切。

相关内容