Simulación de Eventos Discretos · Tema 03

Concepto de evento

Qué es un evento, qué datos lleva, qué tipos existen y cómo diseñarlos para que el simulador cambie el estado en el instante exacto — ni antes ni después.

01 · Punto de partida

El “clic” que cambia la historia

Volvamos al banco: a las 10:00 hay 4 personas. A las 10:02 entra una → hay 5. A las 10:05 termina una atención → hay 4. Cada cambio tiene un instante exacto y una causa puntual. Ese “clic” es el evento.

Fijate lo que el evento no es: atender a una persona dura 3 minutos (eso es una actividad), y esperar en la fila dura lo que dure (eso es una demora). El evento es solo el borde: el instante en que empieza o termina algo. La atención ocupa un intervalo; su inicio y su fin son dos eventos.

  • ¿Dura tiempo o ocurre en un instante?
  • ¿Qué dato del estado cambia por su culpa?
  • ¿Estaba anunciado (en el FEL) o depende de una condición?
  • ¿Qué nuevos eventos provoca hacia el futuro?

02 · Definición

Anatomía de un evento

En el simulador, un evento no es una idea vaga: es un dato con tres campos obligatorios y dos opcionales:

◷

Cuándo

Tiempo t de ocurrencia. Puede ser 2, 2.37 o 104.8: el reloj salta exactamente allí.

◆

Qué

Tipo: llegada, salida, falla, reposición. El tipo elige la rutina que se ejecuta.

◈

A quién / con qué

Datos: qué cliente, qué servidor, con qué prioridad, cuánto durará lo que inicia.

Ejemplo concreto: (5.0, "salida", {"caja": 2}) significa “a las 5.0, la caja 2 termina de atender”. La rutina de salida resta uno del sistema, suma la espera a las estadísticas y, si hay cola, agenda la próxima salida.

Evento frente a lo que no es evento.
Concepto¿Dura?Ejemplo en el bancoCómo se modela
EventoNo: instanteLlegada a las 10:02(10:02, llegada) en el FEL
ActividadSí: duración conocidaAtención de 3 minEvento inicio + evento fin (10:02 → 10:05)
DemoraSí: duración inciertaEspera en filaConsecuencia de eventos, no se agenda directo
EstadoPermanece“Hay 5 personas”Variable que los eventos actualizan

03 · Clasificación

Cuatro distinciones que evitan simuladores rotos

No todos los eventos nacen igual. Estas dos preguntas los clasifican y deciden dónde van en tu programa:

Exógeno vs. endógeno
Exógeno: viene de afuera (llegadas de clientes, pedidos). Se genera con el modelo de llegadas. Endógeno: lo genera el propio sistema (fin de servicio, falla al terminar un lote). Lo agenda una rutina.
Incondicionado vs. condicionado
Incondicionado: ocurrirá sí o sí a su hora (la próxima llegada ya sorteada → va al FEL). Condicionado: solo si se cumple una condición (“iniciar servicio” exige servidor libre y cola no vacía → se intenta tras cada evento, no se agenda a ciegas).
Primario vs. secundario
Primario: llega, sale. Secundario: el que el primario provoca (una llegada con servidor libre provoca “inicio” y agenda “salida”). Diseñar es decidir esta cadena.
Programado vs. sorpresivo
En la simulación todo evento procesado estaba en el FEL (programado por otro). Lo “sorpresivo” para el cliente es determinista para el simulador una vez sorteado.

Va al FEL

Incondicionado

Próxima llegada, próxima salida de un servicio en curso, reposición ya pedida. Tienen hora firme y se extraen por tiempo.

No va al FEL

Condicionado

Iniciar atención, tomar un recurso, desviarse a otra fila. Se evalúan con if después de cada evento incondicionado.

llegada→inicio (si puede)→salida agenda próxima salida

04 · Ejemplos

Qué eventos lleva cada sistema

Diseñar eventos es responder: ¿qué instantes pueden cambiar mi estado? Esta tabla es tu checklist inicial para cualquier cola:

Par mínimo de eventos por sistema (inicio/fin de cada actividad).
SistemaEventos exógenosEventos endógenosCondicionado típico
Banco, 1 cajaLlegadaFin de atenciónIniciar atención
Servidor webArribo HTTPFin de procesamiento, timeoutAsignar worker
InventarioDemanda / ventaArribo de reposiciónEmitir pedido (si stock ≤ punto)
Taller, 2 máquinasLlegada de trabajoFin en máquina A / BMover pieza A → B
UrgenciasArribo pacienteAlta, derivaciónPriorizar por triage
  1. 1
    Llegada.

    Exógena e incondicionada una vez sorteada. Efecto: N+1, agenda la próxima llegada, intenta inicio.

  2. 2
    Salida / fin.

    Endógena e incondicionada (el servicio en curso terminará). Efecto: N−1, acumula espera, si hay cola agenda la próxima salida.

  3. 3
    Inicio.

    Condicionado: solo si hay servidor libre y alguien esperando. No lleva hora propia en el FEL.

  4. 4
    Falla / reparación.

    Endógenos que interrumpen: la falla cambia “servidor disponible” y re-agenda salidas. (Temas 7 y 40)

  5. 5
    Fin de simulación.

    Evento especial stop a hora T: vacía el FEL y cierra estadísticas. (Tema 19)

05 · Representación en Python

El evento es una tupla; la rutina es un diccionario

En Python, un evento cabe en una tupla (tiempo, tipo) —o (tiempo, prioridad, tipo, datos) si hay empates— y cada tipo apunta a una función. El heapq hace de FEL y el dict hace de centralita.

Python en tu navegador. Ejecutá los bloques: el primero crea y ordena eventos; el segundo los despacha a rutinas. Cambiá tiempos y tipos y re-ejecutá.

import heapq

fel = []
heapq.heappush(fel, (4.0, 1, "llegada", {"cliente": "A"}))
heapq.heappush(fel, (2.0, 1, "llegada", {"cliente": "B"}))
heapq.heappush(fel, (2.0, 0, "salida", {"caja": 1}))  # prioridad 0: sale antes

while fel:
    t, prio, tipo, datos = heapq.heappop(fel)
    print(round(t, 1), tipo, datos)

Observá que el evento de t=2.0 tipo salida sale primero por prioridad 0: así se implementa la regla “salidas antes que llegadas”.

import heapq

N = 0  # estado
esperas = []

def al_llegar(datos):
    global N
    N += 1
    print("llega", datos["cliente"], "-> N =", N)

def al_salir(datos):
    global N
    N = max(0, N - 1)
    print("sale caja", datos["caja"], "-> N =", N)

rutinas = {"llegada": al_llegar, "salida": al_salir}
fel = [(1.0, "llegada", {"cliente": "C1"}), (2.5, "salida", {"caja": 1})]
heapq.heapify(fel)

while fel:
    t, tipo, datos = heapq.heappop(fel)
    rutinas[tipo](datos)  # despacho por tipo

06 · Exploración

Laboratorio: la línea de tiempo de eventos

Cada cuánto llega uno (A) y cuánto dura cada atención (S) definen cuándo habrá eventos. Las llegadas son exógenas (fijas en A, 2A, …); las salidas son endógenas (las genera el simulador). Cambiá A, S y la regla de empate y mirá cómo se puebla la línea de tiempo hasta t=12.

EXPERIMENTO 03

Exógenos arriba, endógenos abajo

llegadas fijas · salidas generadas · empates con regla

Los resultados numéricos aparecen debajo.
Llegadas (exógenas)0
Salidas (endógenas)0
Empates mismo t0
En sistema N(12)0

Mueve los controles para poblar la línea de tiempo.

Arriba (lima): llegadas exógenas en tiempos fijos. Abajo (naranja): salidas endógenas generadas por el servicio. Diamante blanco: empate en el mismo instante, resuelto por la regla elegida.

Preguntas para explorar

  1. Con A=2 y S=3 desde vacío, ¿las salidas caen en tiempos regulares? ¿Por qué son endógenas?
  2. Con A=1 y S=1, ¿cuántos empates aparecen? Cambiá la regla y observá si N(12) cambia con cola infinita. ¿Y con capacidad finita cambiaría?
  3. Con A=4 y S=2, ¿cuántas salidas hay? ¿Qué significa que haya llegadas sin cola posterior?
Ver respuestas sugeridas
  1. No: la primera salida es en 5 (2+3), la siguiente depende de si había cola. Son endógenas porque su hora la calcula el simulador al iniciar cada servicio, no viene de afuera.
  2. Hay empate en casi cada t. Con cola infinita el N final coincide con ambas reglas, pero el orden afecta esperas individuales y, con capacidad finita, quién es rechazado. Por eso la regla debe fijarse.
  3. Hay 3 llegadas (4, 8, 12) y 3 salidas (6, 10, y 14→ fuera del horizonte solo 2 visibles). Cada llegada encuentra servidor libre: el sistema casi no forma cola.

07 · Comprensión

Confusiones frecuentes

«La atención es un evento»

La atención es una actividad con duración. Los eventos son su inicio y su fin. Si agendas “atención” como un punto, perdés la espera en cola y la ocupación del servidor.

«La espera en fila se agenda»

La espera es una demora de duración desconocida: nadie sabe cuándo terminará hasta que el servidor se libere. No va al FEL; se mide como consecuencia.

«Todo evento va al FEL»

Solo los incondicionados con hora firme. Los condicionados (“iniciar servicio”) se intentan con if tras cada evento real.

«El orden de empates da igual»

Con cola infinita a veces empata el conteo, pero con capacidad finita, prioridades o costos por espera, el orden decide quién entra y quién se pierde. Siempre con regla explícita.

08 · Práctica guiada

Ejercicios con Python

Ejercicio 1: partir una actividad en dos eventos

La atención dura 3 desde t=2. Generá sus dos eventos y ordenalos en el FEL.

import heapq
inicio, duracion = 2.0, 3.0
fel = []
heapq.heappush(fel, (inicio, "inicio_atencion", {"cliente": "C1"}))
heapq.heappush(fel, (inicio + duracion, "salida", {"caja": 1}))
print(sorted(fel))
Ver solución razonada

FEL [(2.0, inicio), (5.0, salida)]. La actividad “atender 3” desapareció como bloque y quedó como dos instantes. Todo lo que dura se parte así.

Ejercicio 2: contar exógenos y endógenos

Sin ejecutar primero: ¿cuántos de estos son exógenos y cuántos endógenos?

eventos = ["llegada", "llegada", "salida", "salida", "llegada"]
exogenos = sum(1 for e in eventos if e == "llegada")
print("exógenos:", exogenos, "| endógenos:", len(eventos) - exogenos)
Ver solución

3 exógenos (llegadas, vienen de afuera) y 2 endógenos (salidas, las genera el servicio). La proporción cambia con la carga: saturado, hay salida por cada llegada.

Ejercicio 3: empate con prioridad explícita

Implementá la regla “salidas primero” con el formato (t, prioridad, tipo) y comprobá el orden.

Ver una posible respuesta
import heapq
fel = []
heapq.heappush(fel, (5.0, 1, "llegada"))
heapq.heappush(fel, (5.0, 0, "salida"))  # 0 antes que 1
orden = [heapq.heappop(fel)[2] for _ in range(len(fel))]
print(orden)  # ['salida', 'llegada']

El FEL ordena por tiempo y luego por prioridad: la salida libera el servidor justo antes de que entre el nuevo, evitando un rechazo fantasma con capacidad finita.

09 · Síntesis

Ideas para recordar

  • Evento = instante (t, tipo, datos) que puede cambiar el estado; lo que dura se parte en inicio + fin.
  • Exógeno viene de afuera; endógeno lo genera el sistema al procesar otro evento.
  • Solo los incondicionados con hora firme van al FEL; los condicionados se intentan con if.
  • En Python: tupla con tiempo + prioridad + tipo, heapq como FEL y dict de rutinas.
  • Los empates se resuelven con regla explícita (recomendada: salidas antes que llegadas).

En el próximo tema definiremos el estado del sistema: qué variables guardar para que cada evento sepa continuar la historia.