01 · Punto de partida
La computadora solo sabe hacer uniformes
Cuando simulamos una fila, una epidemia o un servidor necesitamos tiempos exponenciales, llegadas Poisson, decisiones Bernoulli, errores normales. Pero si mirás la librería estándar de casi cualquier lenguaje, la única fuente de azar es una función que devuelve uniformes en [0,1): random(), Math.random(), runif().
Este tema responde la pregunta fundacional del curso: ¿cómo se convierte ese chorro plano de uniformes en cualquier variable aleatoria X con distribución F? La respuesta corta es: con un método de transformación determinista. La respuesta larga es todo este curso.
- ¿Qué significa exactamente “X ~ Bernoulli(0,3)” cuando la escribimos en código?
- ¿Por qué comparar un uniforme con un umbral ya genera azar no uniforme?
- ¿Cómo sabemos que el generador respeta la distribución pedida?
- ¿Cómo lo hacemos reproducible con una semilla?
02 · Definición
Qué es generar una variable aleatoria
Una variable aleatoria queda definida por su distribución: en el caso discreto por su masa P(X = k), en el continuo por su densidad f(x) y su acumulada F(x) = P(X ≤ x). Generarla es producir valores x₁, x₂, … cuya frecuencia a largo plazo reproduzca esa distribución.
Uniforme base
U ~ U(0,1) cumple P(U ≤ u) = u. Es “plano”: cualquier subintervalo de igual largo tiene igual probabilidad. Es lo que entrega el generador base.
Método
Función g tal que X = g(U₁, U₂, …) tiene distribución F. Ejemplos: umbral, F⁻¹, aceptación-rechazo, alias, Box-Muller.
Muestra
Los valores xᵢ generados. No son “la distribución”: son evidencia finita que debe parecerse a F y que validaremos con histogramas y pruebas.
El ejemplo mínimo es la Bernoulli(p): vale 1 con probabilidad p y 0 con probabilidad 1 − p. Basta una regla:
Como P(U < p) = p, la salida es exactamente Bernoulli(p). Acabás de transformar un azar plano en un azar sesgado. Todos los métodos del curso son generalizaciones de esta idea.
| Quiero X ~ | Método más simple | Idea en una línea |
|---|---|---|
| Bernoulli(p) | Umbral | 1 si U < p, si no 0 |
| Uniforme discreta {1,…,6} | Escala y piso | 1 + piso(6·U) |
| Exponencial(λ) | Inversa | −ln(1−U)/λ |
| Normal(0,1) | Box-Muller | Dos uniformes → dos normales |
03 · Anatomía
Los cuatro ingredientes de todo generador
- Fuente uniforme
- Generador pseudoaleatorio que produce U₁, U₂, … en [0,1). Es determinista dada una semilla: misma semilla, misma secuencia. Eso permite reproducir experimentos. (Temas 21 y 41)
- Distribución objetivo F
- Lo que queremos imitar, descripta por su masa, densidad o acumulada F. Sin F escrita no hay forma de saber si el método es correcto. (Tema 4)
- Método de transformación
- La receta g: inversa, rechazo, composición, alias, urnas, Box-Muller, Fisher-Yates. Cada uno tiene supuestos, costo y rango de uso. (Temas 5–15)
- Validación
- Histograma, CDF empírica y pruebas (chi-cuadrado, Kolmogorov-Smirnov) que comparan la muestra con F. Generar sin validar es adivinar. (Temas 36–38)
Generador correcto
Respeta F por construcción
Hay un argumento probabilístico (P(U < p) = p, cambio de variable, etc.) y la muestra lo confirma al crecer N.
Imitación ingenua
Parece aleatorio pero sesga
Usar U directamente como si fuera normal, o round() donde va floor(), deforma bordes y colas aunque “se vea azaroso”.
04 · Mapa del curso
A dónde lleva esta idea
El umbral Bernoulli es el caso n = 1. El resto del curso escala la misma arquitectura U → g → X:
- 1Fundamentos (Temas 2–7).
Discretas y continuas, función F y transformada inversa analítica y numérica.
- 2Métodos generales (Temas 8–15).
Rechazo, envolvente y eficiencia, composición, mezclas, alias y urnas.
- 3Catálogo (Temas 16–27).
Bernoulli, uniforme discreta, geométrica, binomial, Poisson, uniforme continua, exponencial, normal, Box-Muller, polar, gamma y otras continuas.
- 4Muestreo y calidad (Temas 28–41).
Correlación, vectores, con/sin reemplazo, permutaciones, Fisher-Yates, empíricas, histogramas, pruebas, eficiencia y biblioteca final.
- 5Regla de oro.
Elegí el método más simple que respete F con el costo que tu N permite. La sofisticación sin validación es deuda técnica.
05 · Representación en Python
Del uniforme al primer generador
En Python, random.random() es nuestra U ~ U(0,1). Todo lo demás es transformación pura. Fijar seed vuelve el experimento repetible.
Python en tu navegador. Estos bloques se ejecutan localmente con Pyodide, sin instalar nada. Podés editar p, N o la semilla y volver a ejecutar.
import random
random.seed(7)
p = 0.3
N = 10
def bernoulli(p):
return 1 if random.random() < p else 0
muestra = [bernoulli(p) for _ in range(N)]
print(muestra)
print("proporción de unos:", sum(muestra) / N)
Cambiá p a 0,8 y reejecutá: la proporción de unos debe subir cerca de 0,8. Con N = 10 hay ruido; con N = 10 000 se estabiliza.
El mismo patrón sirve para otras distribuciones
Una vez entendido el umbral, el resto es cambiar g. Dos adelantos que desarrollaremos a fondo:
import random
import math
random.seed(11)
def uniforme_discreta(a, b):
# Enteros equiprobables {a, ..., b} con U ~ U(0,1).
return a + int((b - a + 1) * random.random())
def exponencial(lam):
# Inversa de la exponencial: F(x) = 1 - exp(-lam*x).
u = random.random()
return -math.log(1 - u) / lam
print([uniforme_discreta(1, 6) for _ in range(8)])
print([round(exponencial(0.5), 2) for _ in range(5)])
06 · Exploración
Laboratorio: el umbral U < p
Movete la probabilidad p y el tamaño N y observá la ley de los grandes números en acción: con N chico la proporción salta; con N grande se pega a la línea teórica p. La semilla es fija para que el experimento sea repetible.
Bernoulli por umbral
X = 1 si U < p, si no 0
Con p 0,3 y N 1000, la proporción ronda 0,3.
La barra naranja es la frecuencia de unos; la línea punteada es p. Al subir N, la barra se acerca a la línea para cualquier p.
Preguntas para explorar
- Con p = 0,5 y N = 100, mové p a 0,9. ¿Qué barra crece y por qué P(U < p) = p lo explica?
- Dejá p = 0,3 y subí N de 100 a 5000. ¿Qué le pasa al error absoluto?
- Si olvidás la semilla y repetís el experimento, ¿cambia la proporción? ¿Sigue siendo válido el generador?
Ver respuestas sugeridas
- Crece la barra de unos: un intervalo más largo [0,p) captura más uniformes, exactamente con probabilidad p.
- Tiende a achicarse (con fluctuaciones): es la convergencia de la frecuencia a la probabilidad.
- Cambia la muestra concreta pero no la distribución: con N grande cualquier semilla da proporción ≈ p. La semilla solo fija qué réplica ves.
07 · Comprensión
Confusiones frecuentes
«random() ya me da normales si pido muchos»
No: muchos uniformes siguen siendo planos. Promediarlos o sumarlos cambia la distribución (teorema central del límite), pero eso ya es otro método con otra F, no “usar uniformes directamente”.
«Si sale 0,72, 0,73, 0,71, el generador anda mal»
Rachas y cercanías son normales en el azar. La calidad se juzga con N grande, histogramas y pruebas, no con 3 valores consecutivos.
«Con N = 50 ya valido»
Con N chico el ruido tapa el sesgo. Un error de método (por ejemplo, usar round en vez de floor) solo se ve claro con miles de réplicas y comparando contra F.
«La semilla hace más aleatorio»
La semilla no mejora ni empeora el azar: solo fija la secuencia para reproducirla. Lo que importa es el algoritmo base y el método g.
08 · Práctica guiada
Ejercicios con Python
Ejercicio 1: calibrar el umbral
Generá 5000 Bernoulli(0,2) con semilla 1 y calculá la proporción. Debe dar ≈ 0,2 con error menor a 0,02.
import random
random.seed(1)
p, N = 0.2, 5000
muestra = [1 if random.random() < p else 0 for _ in range(N)]
prop = sum(muestra) / N
print(prop)
print(abs(prop - p) < 0.02)
Ver solución razonada
Da ≈ 0,20 (típicamente 0,19–0,21) y True. Si cambiás la semilla, el valor exacto cambia pero sigue cumpliendo la tolerancia con N = 5000.
Ejercicio 2: dado justo con uniformes
Sin ejecutar primero: ¿qué valores produce 1 + int(6 * random.random())? ¿Por qué int() (piso) y no round()? Comprobalo generando 6000 tiros.
import random
random.seed(2)
tiros = [1 + int(6 * random.random()) for _ in range(6000)]
for cara in range(1, 7):
print(cara, tiros.count(cara) / len(tiros))
Ver solución
Produce {1,…,6} cada uno con ≈ 1/6. int(6U) parte [0,6) en 6 intervalos iguales de largo 1; round(6U) daría 7 valores con los bordes a mitad de probabilidad.
Ejercicio 3: primer vistazo a la exponencial
Generá 5000 exponenciales con λ = 0,5 y compará la media muestral con la teórica 1/λ = 2. Es el adelanto del Tema 22.
Ver una posible respuesta
import random
import math
random.seed(3)
lam, N = 0.5, 5000
muestra = [-math.log(1 - random.random()) / lam for _ in range(N)]
media = sum(muestra) / N
print(round(media, 3))
print("teórica:", 1 / lam)
La media muestral cae cerca de 2 (típicamente 1,95–2,05). Si da muy lejos, revisá la fórmula: es -ln(1-U)/λ, no -ln(U·λ).
09 · Síntesis
Ideas para recordar
- Generar X ~ F es transformar U ~ U(0,1) con un método g determinista.
- El umbral U < p ya es un generador exacto de Bernoulli(p) porque P(U < p) = p.
- Todo generador combina fuente uniforme, objetivo F, método y validación.
- La semilla fija la secuencia para reproducir; la calidad la dan el algoritmo base y el método.
- Ningún generador se acepta sin comparar muestra vs. F con N grande.
En el próximo tema generalizaremos el umbral a cualquier variable discreta: inversión de la CDF por acumuladas y búsqueda por intervalos.