01 · Punto de partida
Seis letras, cero malentendidos
“Tengo una cola con 2 cajas” no dice nada: ¿arribos con cita o al azar? ¿atenciones fijas o con trabados? ¿caben 10 o infinitos? ¿hay prioridades? La notación de Kendall cierra esa ambigüedad con un código: M/M/2 (banco poissoniano), M/D/1 (cajero de tiempo fijo), M/M/8/50 (call center con cupo).
Leer ese código es leer el sistema: anticipa qué fórmula existe (Erlang, Pollaczek-Khinchine) y qué hay que simular cuando no hay fórmula.
- ¿Qué dice cada posición A/B/c/K/N/D?
- ¿Qué se asume cuando se omiten K, N o D?
- ¿Cómo paso de mi sistema al código y del código a la herramienta?
- ¿Qué códigos tienen fórmula exacta y cuáles piden simulación?
02 · Definición
Seis posiciones, un idioma
Arribos y servicio
M (exponencial), D (fijo), Ek (k etapas), G/GI (general). Miden lo visto en Temas 23–24.
Servidores
Nº en paralelo (Temas 28–29). c = 1 caso base; c > 1 pooling con fila única.
Cupo, población, regla
K sistema (Tema 27), N fuente finita (Tema 22), D disciplina (Temas 25–26). Infantables si son ∞/FIFO.
| Letra | Significa | Variabilidad | Ejemplo |
|---|---|---|---|
| M | Markoviano (exponencial, sin memoria) | 1 | Banco sin turno, request web |
| D | Determinista (fijo) | 0 | Cajero 1 min, pieza robotizada |
| Ek | Erlang de k etapas | 1/k | Trámite en 2 ventanillas parejas |
| G / GI | General / general independiente | cualquiera | Soporte con trabados, lotes |
03 · El corazón: del código a la herramienta
Leer el código es elegir el camino
El código no resuelve nada: apunta. M/M/1 apunta a las fórmulas del Tema 28; M/M/c a Erlang C (Tema 29); M/M/c/c a Erlang B (Tema 27); M/G/1 a Pollaczek-Khinchine; D/D/1 a aritmética de turnos; G/G/c con prioridades a simulación (lo que ya sabés programar).
- AClasificar arribos.
CV ≈ 0 ⇒ D; ≈ 1 ⇒ M; intermedio ⇒ Ek; rachas/lotes ⇒ G. (Tema 23)
- BClasificar servicio.
Cs² ≈ 0 ⇒ D; ≈ 1 ⇒ M; k etapas ⇒ Ek; mezcla con gigantes ⇒ G. (Tema 24)
- c·K·N·DContar y nombrar.
c servidores; K total (Q + c); N fuente si es cerrada; D regla (FIFO por defecto).
- →Elegir herramienta.
M/M/1, M/M/c, M/M/c/c, M/G/1 ⇒ fórmula. El resto ⇒ tu simulador validado en los casos con fórmula.
- D con doble sentido
- En A/B, D = determinista; en la 6ª posición, D = discipline (disciplina). El contexto manda: M/M/1/D no existe, M/D/1 sí.
- Omitir = ∞/FIFO
- M/M/2 significa M/M/2/∞/∞/FIFO. Si el cupo o la población importan, se escriben: M/M/1/50, M/M/1/10/10.
- K vs Q
- K es sistema (espera + servicio). “Cola de 3” con c=1 puede ser K=3 o K=4: el código exige el total.
- N finita
- N = 10 máquinas que circulan (reparación): la tasa efectiva cae cuando muchas están caídas. Modelo cerrado.
Código corto
Fórmula lista
M/M/1, M/D/1, M/M/c: hay capítulo entero con solución exacta. El simulador se usa para validar, no para descubrir.
Código largo
Simulación manda
G/G/3/40 con prioridades y abandono: sin fórmula cerrada. El código igual sirve: fija supuestos y réplicas.
04 · Ejemplos
Cuatro sistemas, cuatro códigos
- 1Banco 2 cajas, sin turno.
M/M/2: Poisson + Exp + 2. Erlang C predice; el simulador valida.
- 2Cajero automático.
M/D/1: arribos Poisson, 1 min fijo. Wq = mitad que M/M/1.
- 3Call center 8 agentes + 42 en espera.
M/M/8/50: K = 50 total. Erlang C con bloqueo predice espera y fuga.
- 4Taller 10 máquinas, 1 técnico.
M/M/1/10/10: población cerrada de 10. La λ efectiva depende de cuántas estén sanas.
05 · Representación en Python
El código como dato (con defaults)
Un dict con las seis claves y un clasificador que sugiere herramienta: parsear Kendall es programar el Tema 30.
Python en tu navegador. El primero parsea con defaults ∞/FIFO; el segundo sugiere fórmula o simulación. Probá tus sistemas.
# Parsear Kendall con defaults K=N=inf, D=FIFO
def kendall(codigo):
p = (codigo.split("/") + ["∞", "∞", "FIFO"])[:6]
A, B, c, K, N, D = p
return {"A": A, "B": B, "c": c, "K": K, "N": N, "D": D}
for k in ["M/M/1", "M/D/1", "M/M/8/50", "M/M/1/10/10"]:
print(k, "->", kendall(k))
# ¿Fórmula o simulación?
def herramienta(k):
A, B, c, K = k["A"], k["B"], k["c"], k["K"]
if A == "M" and B == "M" and K == "∞" and c == "1":
return "M/M/1 exacto (Tema 31)"
if A == "M" and B == "M" and K == "∞":
return "Erlang C (Tema 32)"
if A == "M" and B == "M" and K == c:
return "Erlang B, pérdida pura (Tema 27)"
if A == "M" and K == "∞" and c == "1":
return "M/G/1 Pollaczek-Khinchine"
return "Simulación (validada en casos M)"
print(herramienta(kendall("M/M/2")))
print(herramienta(kendall("M/G/1")))
print(herramienta(kendall("G/G/3/40")))
06 · Exploración
Laboratorio: armar el código y ver qué promete
Elegí A, B y c (K = ∞, FIFO; λ = 0.5/min, S medio = 2). El panel arma el código, calcula ρ y estima Wq con la aproximación de Lee-Longton Wq ≈ ErlangC·(1+Cs²)/2/(cμ−λ) (exacta en M/M/c y M/D/c). Cambiá letras a igual ρ y mirá cómo B mueve la espera.
El código anticipa la espera
A/B/c · λ=0.5 S=2
Cambiá B a igual ρ y mirá la espera.
Casilleros A/B/c con K = ∞ y FIFO por defecto; barras = Wq estimada para cada B a igual ρ. D es piso, G es techo.
Preguntas para explorar
- Con c=1: ¿Wq con B=M vs B=D? ¿Qué factor las separa y por qué?
- Con c=2 y B=G (Cs²=2): ¿Wq vs M/M/2? ¿Qué castiga la mezcla?
- ¿Qué códigos del lab tienen fórmula exacta y cuál es solo aproximación?
Ver respuestas sugeridas
- D da la mitad que M (factor (1+0)/2 vs (1+1)/2): sin variabilidad de servicio no hay tiempo residual gigante.
- G da 1.5× M/M/2 (factor 3/2): los gigantes de S se heredan en la espera de todos.
- M/M/c y M/D/c exactas (Erlang); E2 y G aproximadas aquí (la exacta de E2 pide cadenas, la de G no existe).
07 · Comprensión
Confusiones frecuentes
«D significa disciplina»
Solo en la 6ª posición (M/M/1/FIFO vs …/PRIO). En A/B, D es determinista (M/D/1 = servicio fijo). El lugar manda.
«M/M/2 es dos veces M/M/1»
No: es pooling con Erlang C, no dos filas separadas. Dos M/M/1 con λ/2 esperan más que un M/M/2 con λ.
«Si omito K es porque no hay cupo»
Omitir K afirma K = ∞ (nadie se pierde). Si tu bar echa al 31, escribí /30 o tu Pb no existe.
«M/G/1 tiene fórmula como M/M/1»
Tiene media exacta (PK) pero no la distribución completa simple de M/M/1. Para percentiles con G, simulá.
08 · Práctica guiada
Ejercicios con Python
Ejercicio 1: leer códigos
¿Qué sistema es M/D/1? ¿Y M/M/5/5? ¿Y M/M/1/10/10?
print("M/D/1: Poisson + fijo + 1 (cajero)")
print("M/M/5/5: 5 líneas sin espera (Erlang B)")
print("M/M/1/10/10: 10 máquinas y 1 técnico (cerrado)")
Ver solución razonada
Los tres del Tema 27–28 con nombre corto: el código ahorra un párrafo por sistema.
Ejercicio 2: escribir el código
Call center Poisson, atención exponencial, 8 agentes, 42 en espera, FIFO. ¿Código y K?
c, espera = 8, 42
print(f"M/M/{c}/{c + espera}") # M/M/8/50: K incluye a los 8 en servicio
Ver solución
M/M/8/50: K = 50 total, no 42. El error clásico es codificar la fila en vez del sistema.
Ejercicio 3: del código a la herramienta
Clasificá D/D/1, M/E2/2 y G/G/2/PRIO con tu función.
Ver una posible respuesta
# D/D/1: aritmética de turnos (sin azar). M/E2/2: Erlang, casi M/M/2 pero menor Wq.
# G/G/2/PRIO: simulación con tu motor + key (prio, arr).
print("Turnos -> Erlang -> simulador: el código ordena la caja de herramientas")
D/D/1 se resuelve a mano; M/E2/2 con Erlang o simulación validada; G/G/2/PRIO solo con simulación.
09 · Síntesis
Ideas para recordar
- A/B/c/K/N/D clasifica arribos, servicio, servidores, cupo, población y disciplina.
- Omitir es afirmar: K = ∞, N = ∞, D = FIFO.
- M/D/Ek/G ordenan variabilidad 0 → 1/k → 1 → cualquiera.
- El código elige herramienta: Erlang, PK o tu simulador.
- Sin (λ, μ) el código no dimensiona: tasas + código = experimento.
En el próximo tema abriremos el primero de la familia: el modelo M/M/1.