Modelos y Simulación · Tema 31

Implementación de la simulación

Estructuras de código, tiempo y eventos: el motor que hace correr el modelo.

01 · Punto de partida

Del modelo al motor

El modelo dice qué evoluciona; el simulador resuelve cómo: quién lleva el reloj, dónde esperan los eventos, cómo se sortea y dónde se registra todo. Implementar es construir ese motor sin traicionar el modelo.

  • ¿Reloj por pasos o agenda de eventos?
  • ¿Dónde vive el estado y quién lo toca?
  • ¿Cómo se fija y registra la semilla?
  • ¿Cada corrida deja traza reproducible?

02 · Las piezas del motor

Cinco órganos vitales

◷

Reloj

Avanza el tiempo: pasos fijos o saltos al próximo evento.

▤

Agenda

Cola de eventos futuros ordenada por tiempo: lo próximo primero.

⚄

Azar

Generador con semilla fijada y registrada por corrida.

Cada pieza en código.
PiezaEn PythonRol
Relojfor t in range(pasos)Avanza paso a paso
Agendaheapq de (tiempo, evento)Saca lo próximo primero
Azarrandom.Random(semilla)Sortea reproducible
Registrodict con parámetros y semillaHace repetible la corrida

03 · Dos motores

Paso fijo o eventos

  1. 1
    Paso fijo.

    Itera todos los instantes: simple, parejo, con pasos vacíos cuando no pasa nada.

  2. 2
    Eventos.

    Salta a lo próximo de la agenda: eficiente con actividad rala.

  3. 3
    Ambos deben empatar.

    Mismo escenario, mismos resultados: el motor no cambia el modelo.

Paso fijo

Siempre trabaja

24 pasos = 24 operaciones, haya o no eventos. Simple de escribir y verificar.

Eventos

Solo cuando pasa algo

2 operaciones por cliente (llegada + salida). Gana con poco tráfico.

Reloj
Mecanismo que avanza el tiempo simulado.
Agenda
Eventos futuros ordenados por instante.
Traza
Registro de corrida: parámetros, semilla, versión, resultados.
Motor
Bucle que procesa tiempo y eventos según el modelo.

04 · Trazas

Corridas que se pueden repetir

Parámetros+Semilla+Versión=Réplica exacta

Toda corrida devuelve su historia junto a su traza. El Tema 41 convertirá esto en reproducibilidad total del proyecto.

05 · En Python

Agenda con heapq y motor con traza

Python en tu navegador. La agenda ordenada y la traza son stdlib puro.

import heapq

agenda = []
heapq.heappush(agenda, (2, "llegada"))
heapq.heappush(agenda, (1, "cierre"))
print([heapq.heappop(agenda) for _ in range(2)])

Motor con traza incluida

def simular(n0, entradas, salida, semilla="v1"):
    n = n0
    historia = []
    for e in entradas:
        n = max(n + e - salida, 0)
        historia.append(n)
    return {"semilla": semilla, "historia": historia}


print(simular(10, [3, 3, 3], 2))

06 · Exploración

Laboratorio: contar operaciones

Llegadas al azar en 24 pasos con un servidor. El motor fijo procesa los 24 pasos; el de eventos, solo llegadas y salidas. ¿Cuándo gana cada uno?

EXPERIMENTO 31

Fijo contra eventos

24 pasos · 1 servidor

Los resultados numéricos aparecen debajo.
En sistema (t=24)0
Ops paso fijo24
Ops eventos12
GanaEventos

Con 6 llegadas, eventos usa 12 operaciones contra 24 del fijo.

Puntos: llegadas. Barras: servidor ocupado. Ambos motores describen lo mismo con distinto costo.

Preguntas para explorar

  1. Subí las llegadas a 12. ¿Sigue ganando eventos? ¿Por qué?
  2. ¿Los motores empatan en clientes en sistema? ¿Deberían?
  3. ¿Qué motor elegirías para una autopista vacía de noche?
Ver respuestas sugeridas
  1. Empatan (24 vs 24): con tráfico denso los pasos vacíos desaparecen y el fijo deja de perder.
  2. Sí: mismo escenario, mismo resultado. El motor cambia el costo, nunca el modelo.
  3. Eventos: casi todo son pasos vacíos y el fijo trabaja de balde.

07 · Comprensión

Confusiones frecuentes

«Motor rápido es motor fiel»

La velocidad no prueba fidelidad: ambos motores deben empatar en resultados ante los testigos.

«La semilla es detalle menor»

Sin semilla registrada no hay réplica posible. Es parte del resultado, no del código.

«La agenda ordena sola»

Solo si se usa estructura ordenada (heapq) y empates definidos. La lista desordenada inventa futuros.

«Registrar enlentece»

Cuesta una fracción y salva auditorías: lo no registrado se rehace entero.

08 · Práctica guiada

Ejercicios con Python

Ejercicio 1: agenda ordenada

Encolá una llegada en t = 2 y un cierre en t = 1. ¿Qué sale primero?

import heapq

agenda = []
heapq.heappush(agenda, (2, "llegada"))
heapq.heappush(agenda, (1, "cierre"))
print([heapq.heappop(agenda) for _ in range(2)])
Ver solución razonada

Salen [(1, 'cierre'), (2, 'llegada')]: el heap ordena por tiempo aunque entren desordenados.

Ejercicio 2: motor con traza

Corré 3 entradas y verificá historia y semilla en la traza.

def simular(n0, entradas, salida, semilla="v1"):
    n = n0
    historia = []
    for e in entradas:
        n = max(n + e - salida, 0)
        historia.append(n)
    return {"semilla": semilla, "historia": historia}


print(simular(10, [3, 3, 3], 2))
Ver solución

Da {'semilla': 'v1', 'historia': [11, 12, 13]}: datos y metadatos viajan juntos.

Ejercicio 3: contar operaciones

Con 6 llegadas en 24 pasos, ¿cuántas operaciones usa cada motor?

Ver una posible respuesta
print("fijo:", 24)
print("eventos:", 2 * 6)

El fijo usa 24 y eventos 12: con tráfico ralo, eventos gana por goleada.

09 · Síntesis

Ideas para recordar

  • Simulador = reloj + estado + agenda + azar + registro.
  • Paso fijo simple; eventos eficiente con tráfico ralo.
  • Ambos motores deben empatar ante los mismos testigos.
  • Toda corrida deja traza: parámetros, semilla y versión.
  • En Python: heapq para agendas y dicts para trazas.

En el próximo tema diseñaremos qué correr: el diseño de experimentos.