6

I'm fairly new to tikz and TeX but I don't have a problem writing the code for the tree. I just would like to have a human readable tree. Here's a minimal expample of the tree without edge labels or options:

\begin{tikzpicture}

\tikzstyle{every node}=[draw,shape=circle,fill=black,inner sep=0pt,minimum size=2mm]
\tikzstyle{level 1}=[sibling distance =35mm,level distance=20mm]
\tikzstyle{level 2}=[sibling distance = 18mm,level distance=15mm]
\tikzstyle{level 3}=[sibling distance = 12mm,level distance=10mm]
\tikzstyle{level 4}=[sibling distance = 7mm]

\node {}
  [grow=right]
  child { node {} 
    child { node {} } 
    child { node {} 
      child { node {} }
      child { node {} 
        child { node {} }
        child { node {} } } } }
  child { node {} 
    child { node {} }
    child { node {} } };

\end{tikzpicture}

This is the same tree, just with additional options and edge labels:

\begin{tikzpicture}

\tikzstyle{every node}=[draw,shape=circle,fill=black,inner sep=0pt,minimum size=2mm]
\tikzstyle{level 1}=[sibling distance =28mm,level distance=15mm]
\tikzstyle{level 2}=[sibling distance = 18mm,level distance=15mm]
\tikzstyle{level 3}=[sibling distance = 12mm,level distance=15mm]
\tikzstyle{level 4}=[sibling distance = 7mm,level distance=15mm]

\node {}
  [grow=right]
  child { node {} 
    child { node {} 
      child[level distance=30mm] { node {} edge from parent node [below=1mm,fill=none,draw=none] { $1-w_i$ } }
      child { node {} 
        child { node {} edge from parent node [below=0.02mm,fill=none,draw=none] { $1-g_i$ } }
        child { node {} edge from parent node [above=1mm,fill=none,draw=none] { $g_i$ } } 
      edge from parent node [above=1mm,fill=none,draw=none] { $w_i$ } }
    edge from parent node [below=1mm,fill=none,draw=none] { $1-a$ } }
    child[level distance=45mm] { node {} edge from parent node [above=1mm,fill=none,draw=none] { $a$ } } 
  edge from parent node [below=1mm,fill=none,draw=none] { $1-c$ } }
  child { node {} 
    child[level distance=45mm] { node {} edge from parent node     [below=1mm,fill=none,draw=none] { $1-a$ } }
    child[level distance=45mm] { node {} edge from parent node [above=1mm,fill=none,draw=none] { $a$ } } 
  edge from parent node [above=1mm,fill=none,draw=none] { $c$ } };

\end{tikzpicture}

It seems to me that the tree has now become barely readable. Especially, due to the syntax of tikz which requires me to insert the edge label at the end of a child node. It is very likely that I will hand this tree to someone else for further use and adaptation but I fear that the tree will be useless in this state. Finding an error or changing something seems very, very dangerous and error prone. In fact, after making an error it was usually easier for me to start a new tree than debug the existing one. However, I can't do that with a much larger tree.

So, here's my question: Could you suggest using macros, style definitions or anything else to simplify this tree and make it readable again?

One note: Since I'm under pressure I can't use a different package because I would like to finish this project within this week. So, learning new syntax is not efficient right now. However, please feel free to include recommendations for other users who might stumble upon this post.

Edit: If someone knows a way to write the syntax so that it becomes less obfuscated, I'd also be happy.

  • 2
    forest package seems to be the way to go (built on top of TikZ specifically for such purposes). If you feel adventurous download the CVS version of TikZ and use the graphdrawing library – percusse Nov 27 '13 at 12:08
  • Related question: What is a more efficient way to draw this tree? – Alan Munn Nov 27 '13 at 20:39
  • @AlanMunn you were right, tikz-qtree is not a good option here, however I attempted at an answer which does not use forest but is flexible enough for this example. – Bordaigorl Nov 28 '13 at 17:22
4

Using tikz keys you can express the same tree in a more concise way

\begin{tikzpicture}[
    tree node/.style={
        draw,
        shape=circle,
        fill=black,
        inner sep=0pt,
        minimum size=2mm},
    every child node/.style={tree node},
    root/.style={tree node},
    level/.style={sibling distance=30mm/#1,level distance=15mm},
    % Skip a level in the tree
    skip level/.default={1},
    skip level/.style={
        level distance=\tikzleveldistance*#1+\tikzleveldistance},
    skip level spaced/.default={1},
    skip level spaced/.style={
        skip level=#1,
        sibling distance=\tikzsiblingdistance*#1+\tikzsiblingdistance},
    % Probability on edge:
    prob/.style={
        insert path={edge from parent node[prob label] {$#1$}}},
    prob label/.style={outer sep=.5mm},
]
    \node[root] {}
      [grow=right]
      child { node {} 
        child { node {} 
          child[skip level spaced] {
              node {} [below, prob=1-w_i]}
          child { node {} 
            child { node {} [below, prob=1-g_i] }
            child { node {} [above, prob=g_i] } 
          [above, prob=w_i ] }
        [below, prob=1-a] }
        child[skip level=2,yshift=3mm] {
            node {} [above, prob=a] } 
      [below left, prob=1-c] }
      child { node {} 
        child[skip level=2] { node {} [below, prob=1-a] }
        child[skip level=2] { node {} [above, prob=a] } 
      [above,prob=c] };
\end{tikzpicture}

The only pity is that the edge labels have to be set at the end of the child, with, in the presence of subtrees, takes it apart from the child instruction it refers to. Indentation can help matching them however.

This solution presents:

  1. clean-up of styles
  2. some new keys to make the tree expression more "semantic" and with less noise

Clean-up

I prefer to follow the tikz manual and set styles in the optional argument of tikzpicture using pgfkeys' syntax. The every child node style allows you to avoid setting draw=none,fill=none in the edge labels nodes.

The root style is just a synonym and makes the code readable (you need to install the tree node style on the root manually since it is not a child node).

Instead of setting manually the distances for each level I factor out the common level distance and compute the sibling distance wrt the current level (stored in #1).

The prob and skip level styles

I assumed the edge labels represent probabilities and defined the style prob to set them. I could not use label since it is already in use for different purposes but feel free to rename it depending on the real meaning of the labels.

The prob style injects the edge operation creating a node with mathematical content passed as argument.

The skip level=N style pushes the current child node N levels down in the tree. You can further manipulate the height of the node using shifting (or other styles).

  • This looks very nice and clean. Now, tree construction and style definition is seperate. What I really like is that this way the styles can be reused for other trees too. – Gerome Bochmann Nov 28 '13 at 17:11
  • Your assumptions were correct btw. It's a probability tree. – Gerome Bochmann Nov 28 '13 at 17:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.