01 · Punto de partida
El evento que cae entre dos revisiones
Una llegada real ocurre a las 10:02:22 (t=2.37). Con revisiones cada 1 minuto la ves a las 10:03 (t=3): llegás 0.63 tarde. Con despertador exacto la ves a las 10:02:22: llegás justo.
Ese retraso no es gratis: altera esperas, ordena mal eventos cercanos y, si achicás dt a 0.01 para disimularlo, pasás de 13 a 1201 revisiones. La elección del avance cuesta CPU o cuesta exactitud: hay que elegir con criterio.
- ¿Cuántas revisiones hace cada método en el horizonte T?
- ¿Qué error de tiempo introduce redondear a la grilla?
- ¿Qué pasa si dos eventos caen en el mismo intervalo dt?
- ¿Cuándo empatan y cuándo gana por lejos el próximo evento?
02 · Definición
Las dos máquinas, pieza por pieza
Fijo: t += dt
Grilla 0, dt, 2dt… Se chequea cada casilla aunque esté vacía. Simple de programar, ciego entre casillas.
Eventos: t = próximo
Saltos a tiempos exactos del FEL (2.37, 4.10…). Solo trabaja donde hay eventos. Exacto y ralo-eficiente.
Error de grilla
Redondear 2.37 a 3.0 atrasa 0.63. Achicar dt lo reduce pero multiplica revisiones: no hay almuerzo gratis.
| Aspecto | Incremento fijo | Próximo evento |
|---|---|---|
| Revisiones | T/dt + 1 (13 con dt=1, 121 con dt=0.1) | E = nº eventos (ej. 8) |
| Exactitud | Aproximada: redondea a la grilla | Exacta: floats del FEL |
| Orden en el intervalo | Pierde el orden dentro de dt | Conserva el orden total |
| Mejor caso | Cambios en casi cada paso | Eventos ralos o irregulares |
| Riesgo | dt grande pierde eventos; dt chico explota CPU | FEL desordenado rompe causalidad |
03 · Detalle fino
Tres trampas del incremento fijo
- 1Cuantización.
Todo evento se ve en el próximo múltiplo de dt: atraso medio ≈ dt/2. Con dt=1 y llegadas en .37, el reloj vive 0.63 atrasado.
- 2Colisión en el intervalo.
Dos eventos en (2, 3] se ven “juntos” en t=3 y su orden se pierde. Con llegadas y salidas cercanas, el error cambia quién esperó.
- 3Dilema dt.
Achicar dt de 1 a 0.1 divide el error por 10 pero multiplica las revisiones por 10. En un año simulado, dt=1 min son 525 601 revisiones por un puñado de eventos.
- dt (paso)
- Resolución de la grilla fija. Parámetro del método, no del sistema: no figura en ninguna fórmula de colas.
- E (nº eventos)
- Costo del método por eventos. No depende de T sino de la actividad: noche quieta cuesta casi nada.
- Denso vs. ralo
- Denso: evento en casi cada dt → empatan. Ralo: huecos largos → eventos gana por lejos.
- Híbrido
- Pasos fijos para lo continuo + eventos para lo discreto (heladera con termostato). Cada motor en lo suyo. (Tema 1)
04 · Ejemplos
Los números del dilema
| Método | Revisiones | Error máx. | Cuándo |
|---|---|---|---|
| Fijo dt=2 | 7 | 2.0 (pierde orden) | Solo si nada fino importa |
| Fijo dt=1 | 13 | 1.0 | Juguete didáctico |
| Fijo dt=0.1 | 121 | 0.1 | Caro y aún aproximado |
| Próximo evento | 8 | 0 | Colas reales |
05 · Representación en Python
Dos bucles frente a frente
El fijo recorre la grilla y redondea; el de eventos salta exacto. Mismo sistema, distinto costo y exactitud.
Python en tu navegador. Ejecutá ambos: el fijo revisa 13 y atrasa; el de eventos visita 3 exactos. Cambiá dt y mirá el costo.
# Fijo dt=1: el evento de 2.37 se ve en 3.0 (atraso 0.63)
dt, T = 1.0, 12.0
reloj, revisiones = 0.0, 0
while reloj <= T:
revisiones += 1
reloj += dt
print("revisiones fijas:", revisiones) # 13
print("2.37 se ve en:", 3.0, "| atraso:", round(3.0 - 2.37, 2))
import heapq
fel = [(2.37, "llegada"), (4.10, "llegada"), (5.02, "salida")]
heapq.heapify(fel)
reloj, visitas = 0.0, [0.0]
while fel:
t, _ = heapq.heappop(fel)
reloj = t
visitas.append(round(reloj, 2))
print("visitas exactas:", visitas, "| revisiones:", len(visitas) - 1)
06 · Exploración
Laboratorio: la grilla atrasa, el evento clava
Llegadas cada A (permitimos decimales como 2.5) y servicio S en 1 caja. Verde: tiempo exacto del evento. Gris: cuándo lo vería la grilla fija con tu dt. El segmento rojo es el atraso. Achicá dt y mirá cómo el error baja pero las revisiones explotan.
Exactitud vs. revisiones
vista = techo(real / dt) × dt · atraso = vista − real
Mueve dt para ver el dilema.
Cada par vertical: punto verde (real) y gris (visto). Rojo: atraso. Con decimales la grilla siempre atrasa; con enteros y dt=1 el error se esconde.
Preguntas para explorar
- Con A=2.5, S=2 y dt=1, ¿cuánto atrasa en promedio? ¿Y el máximo?
- Pasá a dt=0.5: ¿el error cae a la mitad? ¿Y las revisiones?
- Poné A entero (2) con dt=1: ¿el error desaparece? ¿Significa que fijo es exacto o que el ejemplo lo favorece?
Ver respuestas sugeridas
- Atraso medio ≈0.4–0.5 y máximo ≈1.0: cada evento con decimal se redondea al entero siguiente.
- Sí, el error se parte; las revisiones pasan de 13 a 25. En un año, de 366 a 731: el costo escala con 1/dt.
- Se esconde porque los eventos caen justo en la grilla. Es un caso amañado: en colas reales los tiempos son 2.37, no 2. El método por eventos es exacto siempre.
07 · Comprensión
Confusiones frecuentes
«dt chico = exacto»
dt chico = menos error pero nunca cero, y cuesta 1/dt. Exacto solo es el salto al tiempo real del FEL.
«Si los tiempos son enteros, da igual»
Con enteros y dt=1 el error se esconde, pero basta un sorteo exponencial (2.37) para que aparezca. Lo entero es un juguete.
«Más revisiones = mejor simulación»
Más revisiones fijas = más CPU mirando huecos vacíos. Mejor es revisar menos veces en los instantes justos.
«El orden dentro de dt no importa»
Llegada en 2.1 y salida en 2.9 vistas “juntas” en 3.0 pierden quién fue primero: con capacidad finita cambia quién es rechazado.
08 · Práctica guiada
Ejercicios con Python
Ejercicio 1: costo de la grilla
Con T=12, compará revisiones con dt=1, 0.5 y 0.1.
T = 12
for dt in [1, 0.5, 0.1]:
print("dt =", dt, "->", int(T / dt) + 1, "revisiones")
Ver solución razonada
13, 25 y 121. Bajar el error de 1.0 a 0.1 cuesta 9× CPU. El método por eventos visita solo los ~8 reales con error 0.
Ejercicio 2: atraso de un evento
Evento real en 2.37 con dt=1: ¿cuándo se ve y cuánto atrasa?
import math
real, dt = 2.37, 1.0
vista = math.ceil(real / dt) * dt
print("vista:", vista, "| atraso:", round(vista - real, 2))
Ver solución
Vista 3.0, atraso 0.63. Ese atraso se suma a la espera medida y contamina Wq sin que ningún assert lo atrape.
Ejercicio 3: colisión en el intervalo
Llegada en 2.1 y salida en 2.9 con dt=1: ¿qué ve la grilla? ¿Y eventos?
Ver una posible respuesta
import math
for real in [2.1, 2.9]:
print(real, "-> grilla:", math.ceil(real / 1.0), "| eventos:", real)
Grilla: ambos en 3.0 (orden perdido). Eventos: 2.1 antes que 2.9 (orden total). Con cola llena, el orden decide el rechazo.
09 · Síntesis
Ideas para recordar
- Fijo:
t+=dt, costo T/dt+1, error ≤ dt y pierde orden intra-dt. - Eventos:
t=próximo, costo E, error 0 y orden total. - Achicar dt reduce error pero multiplica CPU: no hay almuerzo gratis.
- En colas ralas e irregulares, eventos gana en costo y exactitud.
- Lo entero con dt=1 esconde el error; lo decimal lo revela.
En el próximo tema veremos el calendario de eventos: la agenda ordenada que hace posibles esos saltos.