ÁRBOLES DE DECISIÓN
📐 Fundamento Teórico Un árbol de decisión es un grafo dirigido acíclico que modela problemas de decisión secuencial. A diferencia de la tabla de pagos (estática, una sola etapa), el árbol captura la temporalidad: primero decides, luego observas la naturaleza, luego vuelves a decidir. Es el modelo estándar cuando el decisor puede recibir información entre decisiones.
🟦 Nodo de Decisión Cuadrado azul. El decisor elige qué rama tomar 🔀. Se resuelve tomando la alternativa de máximo VME 🔝. Las ramas rechazadas se “podan” (∥) para limpiar el camino hacia la mejor opción ✂️.
🟠 Nodo de Azar Círculo naranja. La naturaleza determina el resultado 🎲. Cada rama lleva su probabilidad 📊. Su valor es igual al VME ponderado de sus ramas (la suma de resultados por sus chances) ⚖️.
🟩 Nodo Terminal Triángulo/Rectángulo verde al final. Representa el payoff final o resultado económico ($) 💰. Es el punto de partida del backward induction: el análisis se realiza de derecha a izquierda ⬅️.
⏸️ Poda (Pruning) Marca de doble barra en ramas no óptimas de nodos de decisión 🚫. La rama óptima queda “viva” ✅. Es el equivalente visual a aplicar la regla de maximización en cada paso del proceso.
Algoritmo de Backward Induction (Plegado del Árbol)
Principio de Optimalidad de Bellman: Una estrategia óptima tiene la propiedad de que, cualquiera que sea el estado inicial y la decisión inicial, las decisiones restantes deben formar una estrategia óptima con respecto al estado resultante de la primera decisión.
Pasos del algortimo
1 Construir el árbol (izquierda → derecha) Raíz = primera decisión. Expandir alternativas → nodos de azar con probabilidades → nodos terminales con payoffs.
2 Evaluar nodos terminales Los payoffs ya están definidos. Son los valores “hoja” del árbol. No requieren cálculo adicional.
3 Retroceder: nodos de AZAR → calcular VME VME(nodo) = Σⱼ pⱼ × valor(ramaⱼ). Propagar este valor hacia la izquierda.
4 Retroceder: nodos de DECISIÓN → podar Elegir max VME entre las ramas disponibles. Marcar las demás con ∥. Propagar el valor óptimo hacia la izquierda.
5 Leer la estrategia óptima El VME de la raíz es el valor esperado del plan óptimo. La secuencia de ramas no podadas define qué hacer en cada escenario
Ejemplo: CASO REAL 1
Exploración Petrolera — ¿Perforar, Vender o Hacer Estudio Sísmico? Una empresa posee un terreno que puede contener petróleo. Tiene tres opciones: Vender el terreno ahora por 90,000, Perforar directamente por 100,000 de inversión (si hay petróleo gana $600,000; si no, pierde los 100,000), o Contratar un estudio sísmico por 30,000 (que predice con cierta exactitud si hay petróleo). Probabilidad previa: P(petróleo) = 0.45.
Codigo en R:
library(ggplot2) # Librería para gráficos
library(tidyr) # Transformación de datos (formato largo/ancho)
library(scales) # Formato de ejes (porcentajes, separadores, etc.)
library(data.tree)
# ---------------- PARAMETROS ----------------
p_petrol <- 0.45 # Probabilidad de encontrar petróleo
ingreso <- 600000 # Ganancia si se encuentra petróleo
costo_perf <- 100000 # Costo de perforación
precio_venta <- 90000 # Precio de venta del terreno
costo_sismico <- 30000 # Costo del estudio sísmico
p_pos_si <- 0.80 # P(Sísmico positivo | hay petróleo)
p_pos_no <- 0.25 # P(Sísmico positivo | no hay petróleo)
VALIDACION
# ---------------- VALIDACION ----------------
# Verifica que todas las probabilidades estén entre 0 y 1
if (any(c(p_petrol, p_pos_si, p_pos_no) < 0 | c(p_petrol, p_pos_si, p_pos_no) > 1)) {
stop("Las probabilidades deben estar entre 0 y 1") # Detiene ejecución si hay error
}
# ---------------- BAYES ----------------
p_no <- 1 - p_petrol # Probabilidad de que NO haya petróleo
# Probabilidad total de resultado sísmico positivo (Ley de probabilidad total)
p_s_pos <- p_pos_si * p_petrol + p_pos_no * p_no
p_s_neg <- 1 - p_s_pos # Probabilidad de resultado sísmico negativo
# Probabilidad posterior de petróleo dado resultado positivo (Teorema de Bayes)
post_si_pos <- (p_pos_si * p_petrol) / p_s_pos
# Probabilidad posterior de petróleo dado resultado negativo
post_si_neg <- ((1 - p_pos_si) * p_petrol) / p_s_neg
VME
# ---------------- VME ----------------
# Función para calcular el Valor Monetario Esperado al perforar
vme_perf <- function(p_si) {
p_si * (ingreso - costo_perf) + # Ganancia esperada si hay petróleo
(1 - p_si) * (-costo_perf) # Pérdida si no hay petróleo
}
# VME sin información adicional (decisión directa)
vme_directo <- vme_perf(p_petrol)
# VME condicionado a resultado positivo
vme_perf_pos <- vme_perf(post_si_pos)
# VME condicionado a resultado negativo
vme_perf_neg <- vme_perf(post_si_neg)
DECISIONES
# ---------------- DECISIONES ----------------
# Mejor decisión si el resultado es positivo (perforar o vender)
dec_pos <- max(vme_perf_pos, precio_venta)
# Mejor decisión si el resultado es negativo
dec_neg <- max(vme_perf_neg, precio_venta)
# VME total considerando el estudio sísmico
vme_estudio <- p_s_pos * dec_pos + p_s_neg * dec_neg - costo_sismico
# ---------------- REPORTE ----------------
cat("===== ARBOL PETROLERO =====\n")
## ===== ARBOL PETROLERO =====
# Imprime VME de cada alternativa
cat(sprintf("VME(Perforar directo): $%s\n", format(round(vme_directo), big.mark=",")))
## VME(Perforar directo): $170,000
cat(sprintf("VME(Vender): $%s\n", format(precio_venta, big.mark=",")))
## VME(Vender): $90,000
cat(sprintf("VME(Con estudio): $%s\n", format(round(vme_estudio), big.mark=",")))
## VME(Con estudio): $181,475
# Resultado si el estudio es positivo
cat(sprintf(" Sismico+: P(petroleo)=%.3f -> %s ($%s)\n",
post_si_pos,
ifelse(dec_pos == vme_perf_pos, "Perforar", "Vender"),
format(round(dec_pos), big.mark=",")))
## Sismico+: P(petroleo)=0.724 -> Perforar ($334,171)
# Resultado si el estudio es negativo
cat(sprintf(" Sismico-: P(petroleo)=%.3f -> %s ($%s)\n",
post_si_neg,
ifelse(dec_neg == vme_perf_neg, "Perforar", "Vender"),
format(round(dec_neg), big.mark=",")))
## Sismico-: P(petroleo)=0.179 -> Vender ($90,000)
# Vector de alternativas
opts <- c(vme_directo, precio_venta, vme_estudio)
# Nombres de alternativas
noms <- c("Perforar directo", "Vender", "Contratar estudio")
# Selección de la mejor decisión
cat(sprintf("DECISION OPTIMA: %s ($%s)\n",
noms[which.max(opts)],
format(round(max(opts)), big.mark=",")))
## DECISION OPTIMA: Contratar estudio ($181,475)
ARBOL CON data.tree
# ====================================================
# ARBOL CON data.tree
# ====================================================
# Nodo raíz
arbol <- Node$new("Decision Principal")
# -------- Rama 1: Perforar --------
r1 <- arbol$AddChild(sprintf("Perforar\nVME=%sk", round(vme_directo/1e3)))
# Nodo: hay petróleo
h1 <- r1$AddChild(sprintf("Petroleo p=%.2f", p_petrol))
h1$payoff <- ingreso - costo_perf # Ganancia neta
# Nodo: no hay petróleo
h2 <- r1$AddChild(sprintf("Sin petroleo p=%.2f", p_no))
h2$payoff <- -costo_perf # Pérdida
# -------- Rama 2: Vender --------
r2 <- arbol$AddChild(sprintf("Vender\n%s", format(precio_venta, big.mark=",")))
r2$payoff <- precio_venta # Ganancia fija
# -------- Rama 3: Estudio --------
r3 <- arbol$AddChild(sprintf("Estudio\nVME=%sk", round(vme_estudio/1e3)))
# Resultado sísmico positivo
sp <- r3$AddChild(sprintf("Sismico+ p=%.3f", p_s_pos))
# Decisión si es positivo: perforar
sp1 <- sp$AddChild(sprintf("Perforar\n%sk", round(vme_perf_pos/1e3)))
sp1$payoff <- vme_perf_pos
# Decisión si es positivo: vender
sp2 <- sp$AddChild(sprintf("Vender\n%sk", round(precio_venta/1e3)))
sp2$payoff <- precio_venta
# Resultado sísmico negativo
sn <- r3$AddChild(sprintf("Sismico- p=%.3f", p_s_neg))
# Decisión si es negativo: perforar
sn1 <- sn$AddChild(sprintf("Perforar\n%sk", round(vme_perf_neg/1e3)))
sn1$payoff <- vme_perf_neg
# Decisión si es negativo: vender
sn2 <- sn$AddChild(sprintf("Vender\n%sk", round(precio_venta/1e3)))
sn2$payoff <- precio_venta
# Mostrar estructura del árbol
print(arbol, "payoff")
## levelName payoff
## 1 Decision Principal NA
## 2 ¦--Perforar\nVME=170k NA
## 3 ¦ ¦--Petroleo p=0.45 500000.000
## 4 ¦ °--Sin petroleo p=0.55 -100000.000
## 5 ¦--Vender\n90,000 90000.000
## 6 °--Estudio\nVME=181k NA
## 7 ¦--Sismico+ p=0.498 NA
## 8 ¦ ¦--Perforar\n334k 334170.854
## 9 ¦ °--Vender\n90k 90000.000
## 10 °--Sismico- p=0.502 NA
## 11 ¦--Perforar\n7k 7462.687
## 12 °--Vender\n90k 90000.000
# Graficar árbol
plot(arbol)
#
ANALISIS DE SENSIBILIDAD
# ANALISIS DE SENSIBILIDAD
# ====================================================
# Secuencia de probabilidades de petróleo
ps <- seq(0.05, 0.95, 0.01)
# Evaluación del modelo para cada valor de p
sens <- sapply(ps, function(p) {
pn <- 1 - p # Probabilidad de no petróleo
# Recalculo probabilidades
p_s_pos_i <- p_pos_si * p + p_pos_no * pn
p_s_neg_i <- 1 - p_s_pos_i
# Posteriores
post_pos_i <- p_pos_si * p / p_s_pos_i
post_neg_i <- (1 - p_pos_si) * p / p_s_neg_i
# Decisiones óptimas
dec_pos_i <- max(vme_perf(post_pos_i), precio_venta)
dec_neg_i <- max(vme_perf(post_neg_i), precio_venta)
# Retorna VME de cada alternativa
c(
Perforar = vme_perf(p),
Vender = precio_venta,
Estudio = p_s_pos_i * dec_pos_i + p_s_neg_i * dec_neg_i - costo_sismico
)
})
# Convertir a dataframe
df_s <- as.data.frame(t(sens))
# Agregar variable independiente
df_s$p_petrol <- ps
# Convertir a formato largo para ggplot
df_long <- pivot_longer(df_s, -p_petrol,
names_to = "Alternativa",
values_to = "VME")
GRAFICO
# ---------------- GRAFICO ----------------
ggplot(df_long, aes(x = p_petrol, y = VME/1000, color = Alternativa)) +
geom_line(linewidth = 1.2) + # Líneas
geom_vline(xintercept = p_petrol, linetype = "dashed") + # Línea vertical
scale_color_manual(values = c(
Perforar = "#3a7fbd",
Vender = "#d97706",
Estudio = "#0f7a52"
)) +
scale_x_continuous(labels = percent) + # Eje en porcentaje
labs(
title = "Sensibilidad del VME ante P(Petroleo)",
x = "P(Petroleo)",
y = "VME (miles $)"
) +
theme_minimal() # Estilo limpio
Interpretación: El gráfico de sensibilidad muestra cómo el Valor
Monetario Esperado (VME) de cada alternativa cambia en función de la
probabilidad de encontrar petróleo. Cuando esta probabilidad es baja, la
mejor decisión es vender el terreno, ya que perforar implica un alto
riesgo de pérdida y el estudio sísmico no logra compensar su costo. A
medida que la probabilidad aumenta hacia valores intermedios, el estudio
sísmico se convierte en la alternativa óptima, porque permite reducir la
incertidumbre mediante la actualización bayesiana y tomar decisiones más
informadas (perforar o vender según el resultado), generando así un
mayor VME. Sin embargo, cuando la probabilidad de encontrar petróleo es
alta, la mejor decisión pasa a ser perforar directamente, ya que el
beneficio esperado es suficientemente grande y el estudio deja de
aportar valor adicional. En el caso específico del problema, donde
𝑃(petroleo)=0.45, el gráfico indica que la opción óptima es contratar el
estudio sísmico, ya que maximiza el VME, reflejando que en contextos de
incertidumbre moderada la información tiene un valor significativo en la
toma de decisiones.