# procesos-estocasticos-discretos-simulacion-estados-y-tiempos-de-absorcion-con-pydtmc
Procesos Estocásticos Discretos: Simulación, Estados y Tiempos de Absorción con PyDTMC
Volver a la portada del cursoEjercicio de Simulación con PyDTMC
Sección 2 · Simulación de Cadenas de Markov
Ejercicio de simulación con PyDTMC
En este notebook construyes tu primera cadena de Markov con PyDTMC, la simulas, la pronosticas y compruebas que la simulación y el cálculo exacto coinciden. El ejemplo es un modelo de clima con tres estados: Soleado, Nublado y Lluvioso. Descarga el notebook adjunto a esta lección y ejecútalo celda por celda.
Antes de empezar
Instala la biblioteca con pip install pydtmc. Este material se probó con PyDTMC 9.0, NumPy 2.4 y Matplotlib 3.10. No necesitas descargar datos: todo se genera con semillas fijas, así que tus números deben coincidir con los del notebook.
Paso 1: crear la cadena
Una MarkovChain recibe la matriz de transición y, opcionalmente, los nombres de los estados. Al imprimirla obtienes un resumen de sus propiedades:
from pydtmc import MarkovChain
P = [[0.9, 0.1, 0.0],
[0.3, 0.5, 0.2],
[0.0, 0.4, 0.6]]
clima = MarkovChain(P, ["Soleado", "Nublado", "Lluvioso"])
print(clima)
print(clima.is_ergodic, clima.period)
Esta cadena es ergódica: desde cualquier estado se llega a cualquier otro y no hay ciclos forzados (periodo 1). Si una fila no suma 1, el constructor lanza un ValidationError; es tu primera red de seguridad.
Paso 2: simular trayectorias
simulate(steps, initial_state, seed) genera una trayectoria. Ojo: devuelve steps + 1 estados, porque incluye el estado inicial. Con next obtienes un solo paso.
ruta = clima.simulate(10, initial_state="Soleado", seed=42)
print(len(ruta))
print(ruta)
print(clima.next("Lluvioso", seed=3))
La semilla hace que el experimento sea reproducible. Sin ella, cada ejecución da una trayectoria distinta, que es lo correcto en producción pero confuso al aprender.
Paso 3: pronosticar con redistribute
La simulación responde "qué podría pasar"; la redistribución responde "con qué probabilidad". redistribute(n, initial_status) calcula $\pi_0 P^n$ sin que tengas que escribir la potencia de la matriz:
for n in (1, 3, 10, 30):
print(n, clima.redistribute(n, initial_status="Lluvioso").round(3))
print("estacionaria:", clima.pi[0].round(3))
Aunque empieces en Lluvioso, después de unos 30 pasos la distribución ya no recuerda el punto de partida y se acerca a la distribución estacionaria $\pi$, que cumple $\pi = \pi P$. Para este clima, $\pi \approx (0.667, 0.222, 0.111)$. Observa que pi es una lista de vectores: una cadena con varias clases recurrentes tiene varias distribuciones estacionarias.
Paso 4: frecuencias simuladas contra $\pi$
La ley de los grandes números para cadenas ergódicas dice que la fracción de tiempo que una trayectoria larga pasa en cada estado converge a $\pi$. Lo verificas así:
import numpy as np
larga = clima.simulate(20000, initial_state="Soleado", seed=7)
valores, conteos = np.unique(larga, return_counts=True)
print(dict(zip(valores, (conteos / conteos.sum()).round(3))))
print(clima.mean_recurrence_times())
Los tiempos medios de recurrencia son $1/\pi_i$: si llueve el 11% de los días, en promedio pasan 9 días entre un día lluvioso y el siguiente.
Paso 5: recuperar la matriz desde datos
En la práctica no conoces $P$; tienes una secuencia observada. MarkovChain.fit_sequence("mle", estados, secuencia) estima cada $p_{ij}$ como el conteo de transiciones $i \to j$ dividido entre las salidas de $i$. Con 20,000 pasos la estimación queda a menos de 0.01 de la matriz real. El notebook también grafica la trayectoria con plot_sequence y la evolución de la distribución con plot_redistributions.
Trampas comunes
simulate(10)devuelve 11 estados, no 10.pidevuelve una lista; usaclima.pi[0]cuando la cadena es ergódica.plot_graphsolo acepta ciertos valores dedpi(75, 100, 150, 200, 250, 300 o 600).- Una trayectoria corta da estimaciones ruidosas: con 50 pasos, un estado poco frecuente puede no aparecer nunca.
Cierre
Termina el notebook cambiando una sola probabilidad (por ejemplo, que Lluvioso siga a Lluvioso con 0.8) y observa cómo se mueven $\pi$ y los tiempos de recurrencia. Ese ejercicio de sensibilidad es la base del análisis de escenarios que harás en el proyecto.