As a starting point, we can use datree to solve Kim's party problem, from the
Decision Analysis courses at Stanford or the Foundations of Decision Analysis
textbook by Howard and Abbas.
library(datree) # Create outcomes outdoor_sun <- o_node(~ v_os, "Outdoor-Sun") porch_sun <- o_node(~ v_ps, "Porch-Sun") indoor_rain <- o_node(~ v_ir, "Indoor-Rain") indoor_sun <- o_node(~ v_is, "Indoor-Sun") porch_rain <- o_node(~ v_pr, "Porch-Rain") outdoor_rain <- o_node(~ v_or, "Outdoor-Rain") # Uncertainty nodes at each alternative outdoor <- u_node(list(outdoor_sun, outdoor_rain), probs = c(~ p_sun, ~ 1- p_sun), name = "Outdoor") porch <- u_node(list(porch_sun, porch_rain), probs = c(~ p_sun, ~ 1- p_sun), name = "Porch") indoor <- u_node(list(indoor_sun, indoor_rain), probs = c(~ p_sun, ~ 1- p_sun), name = "Indoor") # Decision of party location location <- d_node(list(outdoor, porch, indoor), "Location")
The nodes of the tree are defined with abstract values --- expressed with
formula (starting with ~).
Actual variable values must be defined within the calling environment:
# Load initial values v_os <- 1 v_ps <- .95 v_ir <- .67 v_is <- .57 v_pr <- .32 v_or <- 0 p_sun <- .4
Once the variables are defined, you can compute the concrete value of any node
for the given parameters, using evaluate().
evaluate(outdoor) evaluate(indoor) evaluate(porch) evaluate(location)
Note that for sensitivity analysis, you can also provide a list-like data type (e.g., data.frame)
that replaces the global environment values.
evaluate(outdoor, list(p_sun = .5))
Also, for now, it's up to you to keep track and make sure the probabilities add to one!
# This makes no sense, but still works ... (unfortunately) evaluate(outdoor, list(p_sun = 500))
Use decide() to explore the different alternatives of a decision node.
decide(location)
Like evaluate(), you can also specify parameters for decide().
decide(location, list(p_sun = .8))
This setup works well for sensitivity analysis.
library(tidyverse) map_df(c(0, .5, 1), ~ cbind( decide(location, list(p_sun = .x)), p_sun = .x)) %>% ggplot(aes(x = p_sun, y = evalue)) + geom_line(aes(color = alternative))
Alternatively, the tree can be built as recursive calls to node functions, which in some situations might be more readable, especially if you don't need/want to keep track of intermediate nodes.
# Decision of party location location <- d_node(list( # Alternatives # Outdoor u_node(list( # Outcomes for Outdoor o_node(~ v_os, "Outdoor-Sun"), o_node(~ v_or, "Outdoor-Rain")), probs = c(~ p_sun, ~ 1 - p_sun), name = "Outdoor"), # Porch u_node(list( # Outcomes for Porch o_node(~ v_ps, "Porch-Sun"), o_node(~ v_pr, "Porch-Rain")), probs = c(~ p_sun, ~ 1 - p_sun), name = "Porch"), # Indoor u_node(list( # Outcomes for Indoor o_node(~ v_is, "Indoor-Sun"), o_node(~ v_ir, "Indoor-Rain")), probs = c(~ p_sun, ~ 1 - p_sun), name = "Indoor") ), "Location") decide(location)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.