6

Consider the tree below. Is there an easy way to label every left edge q, every right edge p, every left node f and every right node r, without doing it manually for every level?

Second question: Is there a nice way to generalize this Bernoulli process tree example for n-levels?

\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}
Display Name
  • 46,933
student
  • 29,003

3 Answers3

5

I work on something like that but I need to work on this code (no time actually) You can look at \pgfqkeys{/berntree} to see all the options. The limit is 5 but it would be nice to use a recurrent method to build this tree ! I made some modifications now you can modify the styles : node success stylean node miss style. To add some labels at the end of each branch , you can use the last nodes ( it's not very easy) and for the label on the edges you can use edge style. The code is not very fine because the arrows are inside some nodes and it would be better to give the same size for each nodes. Version 4 : edge style/.style = {->,>=latex',shorten <= 6pt}for the edge's problem and see the final loops for the labels. I fixed the size's nodes

\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}

enter image description here

Alain Matthes
  • 95,075
  • @user4011 In the last example there is problem with \frac in the last branch. gap=8cm is too small or it's better to use 1/3 and 2/3. – Alain Matthes Jun 04 '11 at 12:17
  • Thanks. I changed grow=right to grow=down. How to modify it that then the labels of the edges are put to the left of the arrow for arrows pointing to the left and to the right for arrows pointing to the right? – student Jun 04 '11 at 12:21
  • In my posted example (grow=down!) there are additional labels (a,b,c,...) below each leaf. Is it possible to modify your example to include this? – student Jun 04 '11 at 12:23
  • Is it possible that the head of your tree is just one point? – student Jun 04 '11 at 12:24
  • Is it possible to have a circle around each A and a square around each B? – student Jun 04 '11 at 12:25
  • Yes it is possible but actually I updated a lot of my packages on ctan and added two packages so I don't have a lot of time to modify my code. The main problem if you want something to personal, it's the code will be more complex and you need to change a lot of things by hand.\tkzBernTree[root style/.style = {fill,circle,outer sep =1pt,inner sep=2pt}]{4} is a way to the root node – Alain Matthes Jun 04 '11 at 13:59
  • Thanks for the modifications. How to use the "last nodes"? – student Jun 04 '11 at 14:56
  • If I replace the squares by circles, there are also arrows inside the nodes. I played a bit with parent anchor and child anchor, but couldn't solve the problem – student Jun 04 '11 at 15:01
  • @user4011 I modify my code. See the edge style for the use of shorten. Perhaps there is a lighter code for the last nodes. – Alain Matthes Jun 04 '11 at 15:45
  • Whoa! This is fancy! – Concerned_Citizen Jan 23 '12 at 08:07
3

As always, a relative easy task for forest.

Reference: TikZ - same label for every left/right edge

Code

\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}

Output

enter image description here

Qrrbrbirlbel
  • 119,821
2

Here's my take (in plain-tex), if you're willing to differentiate the used style (bagr/bagl) in the code. I've also added some \struts to make the bottom labels line up. The main thing is the edge from parent path-part. At first I thought I could get the \tikzchildnode coordinate straight away, but interestingly enough, it returns 0pt everywhere, so I had to use the calc library for getting some kind of comparable dimens.

\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

edgelabels

I have a suspicion there's an easier way for all this.

morbusg
  • 25,490
  • 4
  • 81
  • 162