01 · Punto de partida
Generar sin despejar ni iterar
La inversa exige Q; la numérica exige resolver F(x) = u en cada muestra. ¿Y si solo sabés evaluar f(x) y muestrear una propuesta g fácil parecida? Entonces podés “filtrar” propuestas: aceptar las que caen bajo f y rechazar el resto. Lo aceptado sigue exactamente f.
Es el método más versátil del curso: sirve para densidades sin acumulada cerrada, truncamientos, a prioris bayesianas y discretas sin tabla completa.
- ¿Qué condición debe cumplir la envolvente c·g?
- ¿Cuál es el algoritmo en 3 líneas?
- ¿Qué fracción se acepta y cuántos intentos cuesta cada X?
- ¿Qué pasa si c es demasiado chico?
02 · Definición
Algoritmo y por qué es exacto
Repetir hasta aceptar: 1) Y ~ g, 2) U ~ U(0,1), 3) si U ≤ f(Y)/(c·g(Y)) devolver Y. La prueba: P(Y ≤ x y aceptada) = ∫₋∞ˣ f/c = F(x)/c, y al condicionar a “aceptada” (prob. 1/c) queda F(x).
Objetivo f
La densidad que querés. Basta evaluarla (no integrarla ni invertirla). Puede ser no normalizada si ajustás c.
Propuesta g
Densidad fácil de muestrear (uniforme, exponencial, normal, triangular) con el mismo soporte que f. Mientras más parecida, mayor aceptación.
Constante c ≥ 1
Infla g hasta mayorizar f: c ≥ sup f/g. 1/c es la tasa de aceptación; c es el costo medio en intentos por muestra.
| Caso | Propuesta | Aceptar si |
|---|---|---|
| Continuo | Y ~ g, U ~ U(0,1) | U ≤ f(Y)/(c·g(Y)) |
| Discreto | Y ~ q, U ~ U(0,1) | U ≤ p(Y)/(c·q(Y)) |
| Beta(2,5) con U(0,1) | Y = U, g = 1 | U₂ ≤ f(Y)/c, c ≈ 2,46 |
03 · Anatomía
Las tres piezas que no pueden fallar
- Soporte cubierto
- Donde f > 0 debe cumplirse g > 0. Si g deja un hueco con masa de f, lo aceptado jamás visita ese hueco: sesgo irrecuperable.
- Mayorización f ≤ c·g
- Si en algún x la envolvente queda por debajo, esos x se aceptan de más: el histograma supera a f ahí. Validar con gráfico f vs c·g.
- Muestreador de g + evaluador de f
- Necesitás ambos. g se muestrea por inversa directa (uniforme, exponencial) y f se evalúa punto a punto, incluso sin constante normalizadora.
- Costo aleatorio
- Número de intentos ~ Geométrica(1/c), media c. Con c = 2,46 pagás ~2,46 propuestas por muestra; con c = 20, el método es inviable.
Envolvente válida
Exacto aunque lento
c·g por encima de f en todo x. El histograma calza con f; el precio es 1 − 1/c de rechazos.
Envolvente rota
Rápido pero sesgado
c menor que sup f/g: acepta de más donde f supera a c·g. Más “eficiencia” aparente y distribución equivocada.
04 · Dónde rinde
El comodín cuando no hay Q
- 1Beta / truncadas con uniforme.
Soporte [0,1] o [a,b]: g uniforme, c = máx f. Simple y suficiente si el pico no es extremo. (Tema 27)
- 2Gamma con exponencial.
Propuesta exponencial con igual tasa: c chico si α cercano a 1; si no, método dedicado. (Tema 26)
- 3Normal con exponencial (polar alternativo).
Clásico didáctico; en producción Box-Muller/polar son directos. (Temas 24–25)
- 4Discretas sin tabla.
Poisson grande o binomial con propuesta geométrica/uniforme: evita acumular infinito. (Temas 19–20)
05 · Representación en Python
Rechazo genérico en 10 líneas
Ejemplo guía: Beta(2,5) con propuesta U(0,1). f(x) = 30·x·(1−x)⁴, c = 2,4576 (máximo en x = 0,2).
Python en tu navegador. Bajá c a 1,8 y mirá cómo la media se sesga: la envolvente rota deja de ser exacta.
import random
import math
random.seed(60)
C = 2.4576 # sup de f Beta(2,5) con propuesta U(0,1)
def f_beta(x):
return 0.0 if x < 0 or x > 1 else 30 * x * (1 - x) ** 4
def rechazo_beta():
while True:
y = random.random() # Y ~ g = U(0,1)
u = random.random() # decisión independiente
if u <= f_beta(y) / C:
return y
N = 6000
m = [rechazo_beta() for _ in range(N)]
print("media muestral:", round(sum(m) / N, 3), "teórica:", round(2 / 7, 3))
print("P(X>0.5):", round(sum(1 for x in m if x > 0.5) / N, 3))
Media teórica Beta(2,5) = a/(a+b) = 2/7 ≈ 0,286. Con C válido debe dar ≈ 0,28–0,29; con C = 1,8 se desplaza visiblemente.
06 · Exploración
Laboratorio: envolvente que cubre o que rompe
Movete c con N fijo. La curva azul es f Beta(2,5); la línea es c·g = c. Si c < 2,46 la envolvente corta a f (zona inválida sombreada) y el histograma se deforma. La tasa teórica es 1/c.
Rechazo Beta(2,5) ← U(0,1)
aceptar si U ≤ f(Y) / c
Con c 2,46, tasa ≈ 0,407 y envolvente válida.
Histograma en densidad de las aceptadas vs f teórica. Probá c = 1,8 (rota) y c = 4 (válida pero derrochadora).
Preguntas para explorar
- Con c = 2,46, ¿qué tasa esperás? ¿Cuántas aceptadas salen de 6000 propuestas?
- Bajá a c = 1,8. ¿Dónde se deforma el histograma y por qué justo en el pico x ≈ 0,2?
- Subí a c = 4. ¿Sigue exacta? ¿Qué pagás a cambio?
Ver respuestas sugeridas
- 1/2,46 ≈ 0,407: unas 2440 aceptadas.
- Se aplasta el pico: ahí f > c y esos Y se aceptan con prob. 1 (de más), achatando la forma.
- Sí, exacta, pero tasa 0,25: 3 de cada 4 propuestas a la basura. Válida ≠ eficiente.
07 · Comprensión
Confusiones frecuentes
«Acepto si U ≤ f(Y) a secas»
Falta dividir por c·g(Y). Sin el denominador aceptás de más donde g es chica y la muestra no es f.
«Reutilizo el mismo U para Y y para decidir»
Si Y = U₁ y la decisión usa el mismo U₁, Y y el umbral quedan acoplados. Dos roles, dos uniformes independientes.
«Si c es más chico, más eficiente»
Más tasa aparente, pero envolvente rota = sesgo. La eficiencia solo se compara entre c válidos (Temas 9–10).
«Rechazo no necesita validar»
Al contrario: graficar f vs c·g es obligatorio. Un hueco de soporte o un pico no mayorizado se ven ahí antes que en el histograma.
08 · Práctica guiada
Ejercicios con Python
Ejercicio 1: tasa que coincide con 1/c
Con C = 2,4576 y 20000 propuestas (semilla 61), medí aceptados/intentos y compará con 1/C ≈ 0,407.
import random
random.seed(61)
C = 2.4576
def f(x):
return 30 * x * (1 - x) ** 4
acc = 0
N = 20000
for _ in range(N):
y, u = random.random(), random.random()
if u <= f(y) / C:
acc += 1
print(acc / N, "vs", round(1 / C, 3))
Ver solución razonada
Debe dar ≈ 0,407 (típicamente 0,40–0,41). Si da ≈ 0,55, probablemente dividiste por C mal o contaste solo aceptadas.
Ejercicio 2: envolvente rota a propósito
Repetí con C = 1,8 y compará media muestral vs 0,286. El sesgo debe ser visible.
import random
random.seed(62)
C = 1.8
def f(x):
return 30 * x * (1 - x) ** 4
m = []
while len(m) < 6000:
y, u = random.random(), random.random()
if u <= f(y) / C:
m.append(y)
print(round(sum(m) / len(m), 3), "vs 0.286")
Ver solución
La media cae (≈ 0,25 o menos): el pico recortado aplasta la distribución hacia abajo. Exactamente lo que muestra el laboratorio.
Ejercicio 3: discreto por rechazo
Objetivo p = [0,5 · 0,3 · 0,2] en {1,2,3} con propuesta uniforme q = 1/3. Calculá c = máx p/q y generá por rechazo.
Ver una posible respuesta
import random
random.seed(63)
p = [0.5, 0.3, 0.2]
q = 1 / 3
c = max(pi / q for pi in p) # 1.5
print("c =", c, "tasa =", round(1 / c, 3))
def propuesta():
return random.choice([1, 2, 3])
m = []
while len(m) < 6000:
y = propuesta()
u = random.random()
if u <= (p[y-1] / q) / c:
m.append(y)
for v in [1, 2, 3]:
print(v, round(m.count(v) / len(m), 3))
c = 1,5, tasa 0,667. Frecuencias ≈ 0,5 · 0,3 · 0,2. El mismo algoritmo, con masas en vez de densidades.
09 · Síntesis
Ideas para recordar
- Rechazo = proponer desde g y filtrar con U ≤ f/(c·g), con f ≤ c·g.
- Lo aceptado ~ f exacto; P(aceptar) = 1/c; intentos medios = c.
- Dos uniformes independientes por intento: uno propone, otro decide.
- c chico inválido sesga; c grande válido derrocha. El óptimo es sup f/g.
- Graficar f vs c·g es el test previo obligatorio.
En el próximo tema aprenderemos a elegir esa envolvente g y su c sin adivinar.