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.
| Concepto | ¿Dura? | Ejemplo en el banco | Cómo se modela |
|---|---|---|---|
| Evento | No: instante | Llegada a las 10:02 | (10:02, llegada) en el FEL |
| Actividad | Sí: duración conocida | Atención de 3 min | Evento inicio + evento fin (10:02 → 10:05) |
| Demora | Sí: duración incierta | Espera en fila | Consecuencia de eventos, no se agenda directo |
| Estado | Permanece | “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.
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:
| Sistema | Eventos exógenos | Eventos endógenos | Condicionado típico |
|---|---|---|---|
| Banco, 1 caja | Llegada | Fin de atención | Iniciar atención |
| Servidor web | Arribo HTTP | Fin de procesamiento, timeout | Asignar worker |
| Inventario | Demanda / venta | Arribo de reposición | Emitir pedido (si stock ≤ punto) |
| Taller, 2 máquinas | Llegada de trabajo | Fin en máquina A / B | Mover pieza A → B |
| Urgencias | Arribo paciente | Alta, derivación | Priorizar por triage |
- 1Llegada.
Exógena e incondicionada una vez sorteada. Efecto: N+1, agenda la próxima llegada, intenta inicio.
- 2Salida / fin.
Endógena e incondicionada (el servicio en curso terminará). Efecto: N−1, acumula espera, si hay cola agenda la próxima salida.
- 3Inicio.
Condicionado: solo si hay servidor libre y alguien esperando. No lleva hora propia en el FEL.
- 4Falla / reparación.
Endógenos que interrumpen: la falla cambia “servidor disponible” y re-agenda salidas. (Temas 7 y 40)
- 5Fin 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.
Exógenos arriba, endógenos abajo
llegadas fijas · salidas generadas · empates con regla
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
- Con A=2 y S=3 desde vacío, ¿las salidas caen en tiempos regulares? ¿Por qué son endógenas?
- 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?
- Con A=4 y S=2, ¿cuántas salidas hay? ¿Qué significa que haya llegadas sin cola posterior?
Ver respuestas sugeridas
- 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.
- 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.
- 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,
heapqcomo FEL ydictde 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.