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.