1

I'm trying to create a decision tree in TeX, currently using the forest package, which uses TikZ under the hood. TikZ is black magic to me, and as a result so's the forest package, but I found a very useful snippet I'm trying to adapt to my needs here.

Here's an example of a decision tree I need help with:

\documentclass{article}
\usepackage{forest}
\tikzset{
    decision/.style={rectangle, minimum height=10pt, minimum width=10pt, draw=black, fill=green!30!white, thick, inner sep=0pt},
    chance/.style={circle, minimum width=10pt, draw=black, fill=red!30!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}
}
\begin{document}
    \begin{forest}
       my edge label/.style={
         edge label = { node[auto, pos=1, anchor=north east, font=\scriptsize]{#1} }
       },
       my node label/.style={
         label = {\small{#1}}
       },
       for tree = {
         text ragged,
         grow         = 0,
         child anchor = west,
         anchor       = west,
         inner sep    = 1mm,
         edge         = { thick, draw = blue, rounded corners = 2pt },
         s sep+       = 5mm,
         l sep+       = 20mm,
         if n children = 0 {
           before typesetting nodes = {
             label/.wrap pgfmath arg = { [align = right, text width = 35pt] right:#1}{ content() },
             content                 = {},
             leaf-chance,
           },
         }{},
         edge path = {
           \noexpand\path[\forestoption{edge}]
           (!u.parent anchor) -- ([xshift=-22.5mm].child anchor) --  (.child anchor)\forestoption{edge label};
         }
       }
        [, decision, label = Price,
          [,decision, my node label = Amount ordered, my edge label = 8 \textdollar
            [,chance, my node label = Demand, my edge label = 1.000
              [,decision, my node label = Order more?, my edge label = {2.000, $p = 0,4$}
                [2.000, my edge label = No, tier = outcome]
                [4.000, my edge label = Yes, tier = outcome]
              ]
              [2.000, my edge label = {1.000, $p = 0,6$}, tier = outcome]
            ]
            [,chance, my node label=Demand, my edge label = 2.000
              [$-$1.000, my edge label = {1.000, $p = 0,6$}, tier = outcome]
              [7.000, my edge label = {2.000, $p = 0,4$}, tier = outcome]
            ]
          ]
          [,decision, my node label = Amount ordered, my edge label = 7 \textdollar
            [,chance, my node label = Demand, my edge label = 1.000
              [,decision, my node label = Order more?, my edge label = {2.000, $p = 0,7$}
                [1.000, my edge label = No, tier = outcome]
                [2.000, my edge label = Yes, tier = outcome]
              ]
              [1.000, my edge label = {1.000, $p = 0,3$}, tier = outcome]
            ]
            [,chance, my node label=Demand, my edge label = 2.000
              [$-$2.000, my edge label = {1.000, $p = 0,3$}, tier = outcome]
              [5.000, my edge label = {2.000, $p = 0,7$}, tier = outcome]
            ]
          ]
        ]
    \end{forest}
\end{document}

This produces the following tree:

Example output

Which is a good start, but hardly perfect. What I'd like to do is:

  1. Move node labels so they don't clash with edges;
  2. Make edges bend at a fixed distance from the parent node, rather than a fixed distance from the child node; and
  3. Have the option of having two labels per edge, to separate the results of random chance (e.g. demand 1000 vs. 2000) and the respective probabilities.

I've made a few attempts, but ultimately drew a blank; not knowing TikZ very well at all, I feel like I'm stabbing around blindly in the dark. Any help, tips, pointers etc. would be appreciated --- I'm not hung up on using forest either, so if there's a better package for creating decision trees, by all means tell me.

Thank you!

1 Answer 1

1

Thanks for the clarification! How about this? Now my edge label has two arguments, one being the text above and the other one the text below.

\documentclass{article}
\usepackage{forest}
\tikzset{
    decision/.style={rectangle, minimum height=10pt, minimum width=10pt,
    draw=black, fill=green!30!white, thick, inner sep=0pt},
    chance/.style={circle, minimum width=10pt, draw=black, fill=red!30!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}
}
\begin{document}
    \begin{forest}
       my edge label/.style n args={2}{
         edge label = { node[auto, pos=1, anchor=east,align=right,text
         depth=0.25ex,text height=1ex,yshift=-1ex,
         font=\scriptsize]{#1\\#2}},
       },
       my node label/.style={
         label={[font=\small]right:#1}
       },
       for tree = {
         text ragged,
         grow         = 0,
         child anchor = west,
         anchor       = west,
         inner sep    = 1mm,
         edge         = { thick, draw = blue, rounded corners = 2pt },
         s sep+       = 5mm,
         l sep+       = 20mm,
         if n children = 0 {
           before typesetting nodes = {
             label/.wrap pgfmath arg = { [align = right, text width = 35pt] right:#1}{ content() },
             content                 = {},
             leaf-chance,
           },
         }{},
         edge path = {
           \noexpand\path[\forestoption{edge}]
           (!u.parent anchor) -- ([xshift=5mm]!u.parent anchor |- .child anchor) --  (.child anchor)\forestoption{edge label};
         }
       }
        [, decision, label =right: Price,
          [,decision, my node label =Amount ordered, my edge label={8
          \textdollar}{}
            [,chance, my node label = Demand, my edge label={1.000}{}
              [,decision, my node label=Order more?, my edge label={2.000}{$p = 0,4$}
                [2.000, my edge label={No}{}, tier = outcome]
                [4.000, my edge label={Yes}{}, tier = outcome]
              ]
              [2.000, my edge label={1.000}{$p = 0,6$}, tier = outcome]
            ]
            [,chance, my node label=Demand, my edge label={2.000}{}
              [$-$1.000, my edge label={1.000}{$p = 0,6$}, tier = outcome]
              [7.000, my edge label={2.000}{$p = 0,4$}, tier = outcome]
            ]
          ]
          [,decision, my node label=Amount ordered, my edge label={7
          \textdollar}{}
            [,chance, my node label=Demand, my edge label={1.000}{}
              [,decision, my node label=Order more?, my edge label={2.000}{$p = 0,7$}
                [1.000, my edge label={No}{}, tier = outcome]
                [2.000, my edge label={Yes}{}, tier = outcome]
              ]
              [1.000, my edge label={1.000}{$p = 0,3$}, tier = outcome]
            ]
            [,chance, my node label=Demand, my edge label={2.000}{}
              [$-$2.000, my edge label={1.000}{$p = 0,3$}, tier = outcome]
              [5.000, my edge label={2.000}{$p = 0,7$}, tier = outcome]
            ]
          ]
        ]
    \end{forest}
\end{document}

enter image description here

3
  • That's excellent, thank you so much! Apologies if the third point wasn't clear --- what I meant is I'd like to have two labels on an edge, one above (indicateing the outcome of a random process), and one below (indicating the probability for that outcome). So for instance, in the topmost Demand note, the edge to the 5.000 outcome would have 2.000 above, and $p = 0,7$ below. It's not really important here, but it would be for bigger trees that one might have trouble fitting on a page otherwise.
    – chsk
    Dec 15, 2018 at 20:42
  • 1
    @chsk I added a proposal.
    – user121799
    Dec 15, 2018 at 21:02
  • Perfect. Thank you again, and happy holidays!
    – chsk
    Dec 16, 2018 at 8:49

You must log in to answer this question.

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