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

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

  • 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 '18 at 20:42
  • 1
    @chsk I added a proposal. – marmot Dec 15 '18 at 21:02
  • Perfect. Thank you again, and happy holidays! – chsk Dec 16 '18 at 8:49

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.