6

I am trying to create a "classic" decision tree with forest. I have never used forest before and struggle with a couple of things. Unfortunately, I did not find the documentation an easy read. I found an answer that broad me a bit along the way (https://tex.stackexchange.com/a/251452/36836). I have adapted and changed it a bit. However, I would like to make the following further changes (partly) illustrated in the diagram below.

  1. Move the node labels (n_0, n_1, etc.) above the nodes (boxes/circles).
  2. Let the branches start at the east of the nodes (so that they don't interfere with the node labels.
  3. Make the nodes (boxes/circles) smaller (since they have no content anymore).
  4. Remove the triangles from the end and put the outcomes, o_1, o_2, etc, at directly after the edge (where the triangles were).
  5. Possibly, change the ordering so that the numbering starts from above rather than below, e.g. n_1 should be the node on top above n_2 and n_3.
  6. Move all settings into the preamble so that they are applied to all trees (maybe naming it "decision tree").

enter image description here

\documentclass{article}

\usepackage{etex,forest}

\usetikzlibrary{shapes,snakes}

\tikzset{
    decision/.style={rectangle, minimum height=10pt, minimum width=10pt, draw=black, fill=white, thick, inner sep=0pt},
    chance/.style={circle, minimum width=10pt, draw=black, fill=white, thick, inner sep=0pt},
    leaf-chance/.style={isosceles triangle, minimum width=10pt, draw=black, thick, fill=white, inner sep=0pt, shape border rotate=180, outer sep=-\pgflinewidth}
  }

\forestset{
  declare toks={optimality}{},
  sub optimal/.style={
    optimality={
      node [midway, sloped]
    }
  },
  declare toks={edge label below}{},
}

\begin{document}
\begin{forest}
   my label/.style={
     edge label={node[midway,above,font=\scriptsize,text width=1.5cm,align=left]{#1}}
   },
    for tree={
      grow=0,
      font=\scriptsize,
      child anchor=west,
      anchor=west,
      text ragged,
      inner sep=1mm,
      edge={thick},
      l sep+=15mm,
      s sep+=5mm,
      if n children=0{
        before typesetting nodes={
          label/.wrap pgfmath arg={right:#1}{content()},
          content={},
          leaf-chance,
        },
      }{},
      edge path={
        \noexpand\path[\forestoption{edge}]
        (!u.parent anchor) -- ([xshift=-15mm].child anchor)\forestove{optimality} --  (.child anchor)\forestoption{edge label below}\forestoption{edge label};
  },
    }
    [$n_0$,decision
      [$n_1$,decision,my label={$s_1$, $s_2$}
        [$o_1$,chance,my label=$s_1(n_1)$]
        [$o_2$,decision,my label=$s_2(n_1)$]
      ]
      [$n_2$,decision,my label={$s_3$, $s_4$}
        [$o_3$,decision,my label=$s_3(n_2)$]
        [$o_4$,decision,my label=$s_4(n_2)$]
      ]
      [$n_3$,decision,my label={$s_5$, $s_6$}
        [$o_5$,decision,my label=$s_5(n_3)$]
        [$o_6$,decision,my label=$s_6(n_3)$]
      ]
    ]
\end{forest}
\end{document}
2
  • Please do not edit answers into questions: the site format is A&A, and it helps all users to keep the two parts separate.
    – Joseph Wright
    Mar 29, 2018 at 13:45
  • @JosephWright I might understand why one should not include an answer in ones Question. But why did you remove a link to an answer?
    – Daniel
    Mar 30, 2018 at 20:18

2 Answers 2

11

like this?

enter image description here

edit: an attempt to make tree code slightly shorter

  • from preamble of your mwe is relevant only package forest
  • styles of nodes and edges labels are defined as for tree options
  • style for labels is moved in forest environment
  • to tree code are added comments for short its explanation

\documentclass[margin=3mm]{standalone}
\usepackage{forest}

\begin{document}
\begin{forest}
/tikz/every label/.append style={xshift=-1pt,inner sep=1pt,font=\footnotesize},
  for tree={
    grow'=east,
  % node style
    line width=0.4pt,
    minimum size=2pt,
    inner sep=2pt,
    if n children=0{}{draw}, % <--- added
  % anchors <------- solve basic problem 
    parent anchor=children,  
    child anchor=parent,     
  % distances of nodes
      l sep=17mm,           % <-- *l*: level distance
      s sep=2mm,            % <-- *s*: sibling distance between leaves
  % edges
    edge={draw},
    edge path'={
       (!u.parent anchor) -- ([xshift=-13mm].child anchor) -- (.child anchor)
                },
  % labels on edges
    delay={
      edge label/.wrap value={node[midway, inner sep=1pt,
                                   font=\scriptsize, above]{#1}},
           },
  }, % end for tree
  [ , label=$n_0$
    [, label=$n_3$, edge label={$s_5,s_6$}
      [$o_6$, edge label={$s_6(n_3)$}]
      [$o_5$, edge label={$s_5(n_3)$}]
    ]
    [ , label=$n_2$, edge label={$s_3,s_4$}
      [$o_4$, edge label={$s_4(n_2)$}]
      [$o_3$, edge label={$s_3(n_2)$}]
    ]
    [ , label=$n_1$, edge label={$s_1,s_2$}
      [$o_2$, edge label={$s_2(n_1)$}]
      [$o_1$, edge label={$s_1(n_1)$}]
    ]
  ]
\end{forest}
\end{document}
4
  • Awesome! I have to look at the difference and study what needed to be changed. One more thing: Is it possible to move all the to the preamble?
    – Daniel
    Mar 26, 2018 at 19:05
  • Also, is there a specific reason you removed the possibility to draw chance nodes (circles)? Also, the line thickness of the choice nodes (boxes) is too thinner now.
    – Daniel
    Mar 26, 2018 at 19:17
  • i remove all what is not needed for this tree. you can always return what you need somewhere else. increasing thickness of node border should not be a problem: increaseline width=0.2pt in in forest={... options for example to line width=1pt.
    – Zarko
    Mar 26, 2018 at 19:52
  • Thanks. I reduced it even further and moved it into a "decision tree" (see my edit).
    – Daniel
    Mar 26, 2018 at 20:13
1

enter image description here

\documentclass{article}
\usepackage{forest}

\forestset{
  declare toks={elo}{},
    my label/.style={
        edge label={node[midway,above,text width=1.7cm,align=left]{#1}}
    },
    decision tree/.style={
    for tree={
        grow=east,
        minimum size=2pt,
        inner sep=2pt,
        parent anchor=east,
        child anchor=west,
        l sep+=20mm,
        s sep+=3mm,
        edge path'={(!u.parent anchor) -- ([xshift=-18mm].child anchor)\forestove{elo} -- (.child anchor)},
    }
    }
}

\begin{document}
{\small
\begin{forest} decision tree
    [,label=$n_0$,draw
      [,label=$n_3$,draw ,my label={$s_5,s_6$}
        [$o_6$, my label=$s_6(n_3)$]
        [$o_5$, my label=$s_5(n_3)$]
      ]
      [,label=$n_2$,draw, my label={$s_3,s_4$}
        [$o_4$, my label=$s_4(n_2)$]
        [$o_3$, my label=$s_3(n_2)$]
      ]
      [,label=$n_1$,draw, my label={$s_1,s_2$}
        [$o_2$, my label=$s_2(n_1)$]
        [$o_1$, my label=$s_1(n_1)$]
      ]
    ]
\end{forest}}
\end{document}
6
  • You could also use edge path'={(!u.parent anchor) -- ([xshift=-18mm].child anchor)\forestove{elo} -- (.child anchor)}, which is a bit easier (and less typing) than using the edge path key.
    – cfr
    Mar 27, 2018 at 10:11
  • can you explain, what is in your answer different from mine and what is improved? can you show obtained result, please?
    – Zarko
    Mar 27, 2018 at 13:29
  • @Zarko Sure. I've added an image of the result. First, it aligns the edge labels to the left (as in the original example). Second, it (unfortunately) manually turns the numbering around (reading from left to right and top to bottom). Third, it removes a couple of unnecessary things, like the tikz shapes and snakes library.
    – Daniel
    Mar 27, 2018 at 18:22
  • @cfr Nice. I have replaced it in my answer accordingly.
    – Daniel
    Mar 27, 2018 at 18:24
  • 1
    if you say so ... but as i see, your answer essentially doesn't give anything new to mine. sorry, it seems to me more or less as duplicate (except what is done according to @cfr comment).
    – Zarko
    Mar 27, 2018 at 18:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .