Números Pseudoaleatorios · Tema 05

Semillas

El valor inicial que define toda la historia: cómo elegirlo, registrarlo y evitar las trampas clásicas de la semilla cero y la hora como semilla.

01 · Punto de partida

Un número para gobernarlos a todos

En el Tema 4 viste que una secuencia nace de x₀ → x₁ = f(x₀) → x₂ = f(x₁) → …. Ese x₀ es la semilla: el único grado de libertad que te deja un generador determinista. Fijada la semilla y la fórmula, toda la historia de millones de valores queda decidida.

Por eso la semilla es a la vez superpoder y responsabilidad: te da control total (repetir, depurar, compartir), pero un descuido —semilla cero en el generador equivocado, hora en segundos, semilla no anotada— arruina un experimento o una contraseña.

  • ¿Qué es exactamente una semilla y qué no es?
  • ¿Cómo se elige una buena semilla para simular y para variar?
  • ¿Por qué la semilla 0 a veces «mata» al generador?
  • ¿Qué hay que anotar junto a la semilla para ser reproducible?

02 · Definición

Semilla, estado y entropía de siembra

Tres ideas que suelen mezclarse y conviene separar:

◈

Semilla

El x₀ que vos proveés. Puede ser un entero chico (42), un timestamp o 64 bits del sistema. Es pública en simulación, secreta en seguridad.

⇄

Estado inicial

Lo que el generador carga en memoria al arrancar. En un LCG es la semilla misma; en uno moderno es un vector derivado de ella por una función de mezcla.

▣

Siembra

El acto de inicializar: random.seed(42). Sembrar dos veces con lo mismo rebobina la secuencia al inicio, no la «mezcla».

La semilla en distintos generadores.
GeneradorSemilla válidaTrampa típica
LCG mixto (a·x+c) mod mCualquiera en 0..m-1Creer que cambia el período (solo cambia el arranque)
LCG multiplicativo (a·x) mod mNunca 0Con x₀=0 todo da 0 para siempre
Moderno (PCG, Mersenne)Entero de 32/64 bits o vectorSemillas 1, 2, 3 correlacionadas al inicio si no hay mezcla

03 · Elección y registro

Cómo elegir y anotar semillas sin sufrir

Elegir semilla no es arte: es decidir qué querés (repetir o variar) y dejarlo por escrito:

Fija documentada
Un entero arbitrario pero anotado: seed = 2026 en el código y en el informe. Es el estándar para papers, depuración y este curso.
Aleatoria del SO
Pedida a os.urandom o secrets cuando querés variedad entre corridas. La imprimís y la guardás: variedad con trazabilidad.
Tiempo
int(time.time()) solo para demos y juegos casuales. Colisiona en el mismo segundo y se adivina. Nunca para seguridad ni ciencia seria.
Secuencia de semillas
Para réplicas: [101, 102, …] o mejor, enteros espaciados al azar. Semillas 1, 2, 3 seguidas pueden dar arranques parecidos en algunos generadores (Tema 37).

Buena práctica

Semilla + contexto

Guardás semilla, algoritmo, versión de código y N. Con esos 4 datos cualquiera repite tu experimento bit a bit.

Mala práctica

Semilla fantasma

«Usé random sin seed y me dio 0,62». Nadie puede repetirlo, ni vos mismo. El resultado es anecdótico.

04 · Ejemplos

La misma fórmula, cuatro destinos

Con el LCG didáctico m = 16 se ven a ojo los destinos que una semilla puede tener:

Elegir x₀→Iterar f→Historia u(n)
  1. 1
    Semilla normal en mixto.

    x₀=7, a=5, c=3: ciclo completo de 16, arranque en 7. Cambiar a 8 solo rota el anillo.

  2. 2
    Semilla cero en mixto.

    x₀=0, a=5, c=3: funciona igual, entra al mismo anillo por otra puerta. El cero no es trampa aquí.

  3. 3
    Semilla cero en multiplicativo.

    x₀=0, a=5, c=0: 5·0 mod 16 = 0 para siempre. Secuencia muerta 0, 0, 0….

  4. 4
    Semillas correlativas.

    1, 2, 3 en un generador sin mezcla arrancan parecido las primeras posiciones. Para réplicas independientes conviene espaciarlas (Tema 37).

05 · Siembra en Python

Fijar, variar y registrar

Tres líneas cubren el 95 % de tus necesidades: fijar para repetir, pedir entropía para variar y guardar lo usado.

Python en tu navegador. Probá sembrar dos veces con lo mismo y observá el «rebobinado» exacto.

import random

random.seed(42)
print("primera:", [random.random() for _ in range(3)])
random.seed(42)
print("rebobinada:", [random.random() for _ in range(3)])

Idénticas: sembrar no agrega azar, reinicia la película desde el mismo fotograma.

Pedir una semilla al sistema y guardarla

Cuando querés variedad con trazabilidad, el sistema te da la semilla y vos la imprimís para el diario del experimento:

import os
import random

semilla = int.from_bytes(os.urandom(4), "big")
random.seed(semilla)
print("semilla usada:", semilla)
print([round(random.random(), 4) for _ in range(5)])

06 · Exploración

Laboratorio: la semilla elige la historia

Elegí semilla, tipo de generador y N. El modo mixto usa (5·x+3) mod 16; el multiplicativo usa (5·x) mod 16. Probá la semilla 0 en ambos y mirá qué pasa.

EXPERIMENTO 05

Semilla cero bajo la lupa

mixto vs. multiplicativo

Los resultados numéricos aparecen debajo.
Primer u—
Valores distintos—
¿Secuencia muerta?—
Lectura—

Con semilla 7 ambos tipos parecen azar en N chico.

Cada punto es u(n) = x(n)/16. La línea plana en cero delata la trampa de la semilla cero en el multiplicativo.

Preguntas para explorar

  1. Con semilla 0 y tipo multiplicativo, ¿qué valores salen? ¿Y con semilla 0 y mixto?
  2. Con semilla 7, ¿distinguís a ojo mixto de multiplicativo en 32 valores? ¿Qué necesitarías para decidir?
  3. Si tu simulación dio un resultado raro con semilla 7, ¿cómo lo repetís exactamente para depurar?
Ver respuestas sugeridas
  1. Multiplicativo + 0 = todo cero (punto fijo absorbente). Mixto + 0 funciona normal: el +3 lo saca del cero.
  2. No a ojo: ambos cubren valores parecidos en N chico. Necesitás período, tests y N grande (Temas 10 y 26+).
  3. Resembrando con 7 y corriendo el mismo código y N: obtendrás bit a bit lo mismo para inspeccionar el paso raro.

07 · Comprensión

Confusiones frecuentes

«Cualquier semilla sirve en cualquier generador»

No: el 0 mata a los multiplicativos puros y algunas semillas reservadas (todo ceros) son ilegales en generadores modernos. Leé el rango válido de tu generador.

«Resiembro con la hora en cada tiro para más azar»

Es peor: colisiona en el mismo segundo y correlaciona tus «azarosos». Se siembra una vez; después se itera.

«Semillas 1, 2, 3 dan réplicas independientes»

Pueden arrancar demasiado cerca y contaminar comparaciones. Para réplicas usá semillas espaciadas o derivadas con mezcla (Tema 37).

«La semilla no se anota, total el promedio da igual»

Sin semilla no hay depuración ni publicación: un promedio sin semilla es un rumor. Anotarla cuesta una línea.

08 · Práctica guiada

Ejercicios con Python

Ejercicio 1: el rebobinado

Demostrá que sembrar dos veces rebobina: generá 3 valores, generá 3 más, resembrá y compará con los primeros 3.

import random

random.seed(99)
a = [random.random() for _ in range(3)]
b = [random.random() for _ in range(3)]
random.seed(99)
c = [random.random() for _ in range(3)]
print(a)
print(b)
print(c)
print("c == a:", c == a)
Ver solución razonada

c == a es True y b es la continuación, no una repetición. La semilla marca el inicio de la cinta, no un «batido».

Ejercicio 2: matar un generador con cero

Compará mixto y multiplicativo desde semilla 0 con el mismo a. ¿Cuál sobrevive?

def gen(semilla, a, c, m, n=8):
    x = semilla
    sal = []
    for _ in range(n):
        x = (a * x + c) % m
        sal.append(x)
    return sal


print("mixto:", gen(0, 5, 3, 16))
print("multi:", gen(0, 5, 0, 16))
Ver solución

El mixto produce valores variados; el multiplicativo queda en [0, 0, …]. Moraleja: c = 0 y semilla 0 son incompatibles.

Ejercicio 3: diario de experimento

Empaquetá semilla, parámetros y primeros valores para que tu yo del futuro pueda repetirlo.

Ver una posible respuesta
import random

corrida = {"semilla": 2026, "a": 5, "c": 3, "m": 16, "n": 6}
random.seed(corrida["semilla"])
vals = [round(random.random(), 4) for _ in range(corrida["n"])]
print(corrida)
print(vals)

Guardar el diccionario junto a la salida es tu «caja negra» de vuelo. En el Tema 6 lo convertiremos en protocolo completo de reproducibilidad.

09 · Síntesis

Ideas para recordar

  • La semilla es el estado inicial: decide toda la secuencia futura.
  • Sembrar dos veces con lo mismo rebobina, no agrega azar.
  • Elegí fija documentada para ciencia, del SO para variedad; la hora solo para demos.
  • El 0 es letal en generadores multiplicativos puros.
  • Anotá semilla + algoritmo + versión + N: sin eso no hay experimento repetible.

En el próximo tema convertiremos esto en método: reproducibilidad mediante semillas, el protocolo para que tus simulaciones siempre puedan repetirse bit a bit.