01 · Punto de partida
Sin atributos, todos son iguales
En el Tema 5 seguimos a C5, C6 y C7 por su ID. Pero si solo sabemos el ID, la fila solo puede ser FIFO: pasa el que llegó primero. En la realidad hay embarazadas que pasan primero, requests premium, piezas urgentes y pacientes graves.
¿Cómo sabe el simulador quién es quién? Por los atributos: campos pegados a cada entidad que se fijan al nacer (prioridad, tipo), se completan al vivir (inicio, fin) y se leen al decidir y al medir (espera = inicio − llegada).
- ¿Qué dato decide el orden cuando hay dos esperando?
- ¿Qué dato permite medir la espera individual?
- ¿Qué dato nunca cambia y cuál se completa con el tiempo?
- ¿Dónde vive el atributo: en la entidad, en el estado o en la estadística?
02 · Definición
Tres familias de atributos
Fijos al nacer
Se sortean en la llegada y no cambian: tipo (normal/premium), prioridad (1/2), operación requerida.
De historia
Se completan al vivir: llegada, inicio, fin. Con ellos se deriva todo lo medible.
Derivados
Se calculan, no se guardan: espera = inicio − llegada, vida = fin − llegada. Guardarlos duplica y desincroniza.
Regla de oro: los fijos y la historia se guardan en la entidad; los derivados se calculan con funciones. Si guardás espera como campo y después cambiás inicio, la espera vieja miente.
| Atributo | Familia | Ejemplo | Se usa para |
|---|---|---|---|
| id | Fijo | C7 | Trazabilidad |
| prioridad | Fijo | 1 = alta, 2 = baja | Ordenar la cola |
| tipo | Fijo | jubilado / premium / normal | Reglas y estadísticas por clase |
| llegada, inicio, fin | Historia | 8.0, 10.0, 13.0 | Medir esperas y vidas |
| espera, vida | Derivado | 2.0, 5.0 | Reportar (calcular, no guardar) |
03 · Para qué sirven
Decidir y medir: los dos trabajos
- 1Ordenar.
La disciplina deja de ser “el primero que llegó” y pasa a ser “el de menor
(prioridad, llegada)”. Dos campos deciden todo el orden. (Temas 25–26 y 39) - 2Enrutar.
El
tipoelige servidor o cola: premium → caja 1, piezas tipo B → máquina B, request de video → worker GPU. - 3Medir por clase.
Con atributos podés reportar “espera media de prioritarios vs. normales” y descubrir que el promedio global esconde una injusticia.
- 4Auditar.
Con
llegada/inicio/finreconstruís la película de C7 ante un reclamo: cuándo llegó, cuánto esperó, quién lo atendió.
- Atributo de entidad
- Vive en la entidad (C7.prioridad). Viaja con ella si migra de cola en cola.
- Atributo de recurso
- Vive en la estática (caja.velocidad, worker.GPU). Decide quién atiende qué.
- Variable global
- Vive en el sistema (reloj, contador). No es atributo aunque lo lea todo el mundo.
- Etiqueta vs. medida
- La etiqueta clasifica (tipo, prioridad); la medida cuantifica (espera, vida). Ambas son atributos, distinto uso.
Sin atributos
FIFO ciego
Todos iguales, un solo promedio, cero políticas. Simple pero injusto e inútil para dimensionar por clases.
Con atributos
Políticas y lupa
Prioridades, tipos, esperas por clase y auditoría. Cuesta un dict por entidad y una regla de orden.
04 · Ejemplos
Los mismos clientes, distintas etiquetas
- 1Banco.
C7 (jubilado, prio 1, llegó 8) pasa antes que C5 (normal, prio 2, llegó 4). Sin prioridad, C5 pasaba primero.
- 2Web.
R12 (premium) salta la cola de 20 normales. El atributo
plandecide latencias por clase. - 3Guardia.
Triage rojo/amarillo/verde: el color es un atributo fijo que ordena vidas, no llegadas.
- 4Fábrica.
Pieza tipo B requiere máquina B: el atributo
operaciónenruta, no el orden.
05 · Representación en Python
Dict con campos + orden por tupla
La entidad es un dict; el orden es ordenar por (prioridad, llegada). Los derivados son funciones puras.
Python en tu navegador. El primer bloque ordena por atributos; el segundo mide por clase. Cambiá prioridades y re-ejecutá.
cola = [
{"id": "C5", "prio": 2, "llegada": 4.0},
{"id": "C6", "prio": 2, "llegada": 6.0},
{"id": "C7", "prio": 1, "llegada": 8.0}, # prioritario aunque llegó último
]
cola_ordenada = sorted(cola, key=lambda e: (e["prio"], e["llegada"]))
print([e["id"] for e in cola_ordenada]) # ['C7', 'C5', 'C6']
def espera(e):
return e["inicio"] - e["llegada"] # derivado: no se guarda
atendidas = [
{"id": "C5", "prio": 2, "llegada": 4.0, "inicio": 10.0},
{"id": "C7", "prio": 1, "llegada": 8.0, "inicio": 9.0},
]
for e in atendidas:
print(e["id"], "esperó", espera(e))
06 · Exploración
Laboratorio: la misma fila, dos justicias
Cinco clientes con llegadas fijas (1, 2, 4, 6, 8). Con el interruptor elegí FIFO (ordena por llegada) o Prioridades (ordena por (prio, llegada)). El control prioridad de C5 lo convierte en normal (2) o VIP (1). Mirá cómo cambia quién sigue y la espera media por clase.
El campo que cambia el orden
FIFO: min(llegada) · Prioridades: min(prio, llegada)
Cambiá la disciplina para comparar.
Barras: espera de cada cliente en orden de atención (lima VIP, naranja normal). La etiqueta muestra id + espera. Con FIFO manda la llegada; con prioridades manda el campo prio.
Preguntas para explorar
- Con FIFO, ¿quién es primero y quién último? ¿Importa la prioridad de C5?
- Con Prioridades y C5 normal, ¿quién salta al frente? ¿Cuánto espera C5?
- Convertí a C5 en VIP (prio 1, llegó primero): ¿qué pasa con las medias por clase?
Ver respuestas sugeridas
- FIFO atiende por llegada: C5 primero aunque sea normal; la prioridad se ignora por diseño.
- Con C5 normal, el VIP (C7, prio 1) salta al frente aunque llegó 4º; C5, primero en llegar, termina esperando lo que dure vaciar a los VIP.
- Si C5 también es VIP, los VIP copan el frente y los normales esperan más: la media global puede igualarse pero la brecha por clase se invierte. Los atributos revelan la injusticia que el promedio esconde.
07 · Comprensión
Confusiones frecuentes
«El ID es un atributo más»
El ID identifica, no clasifica ni mide. Prioridad y tipo deciden; llegada/inicio/fin miden. Mezclarlos lleva a ordenar por ID, que es arbitrario.
«La espera se guarda en la entidad»
La espera se deriva de inicio − llegada. Guardarla congela un valor que se desactualiza al reprogramar el inicio.
«Más atributos = mejor modelo»
Cada atributo debe decidir o medir algo. El color favorito del cliente no ordena ni mide: es ruido que cuesta memoria y confunde.
«Cambiar atributos en la fila está bien»
Cambiar prioridad a mano para “desempatar” falsea la política. La regla se escribe una vez y se aplica; los atributos se leen.
08 · Práctica guiada
Ejercicios con Python
Ejercicio 1: ordenar por dos claves
Ordená esta cola por (prio, llegada) y decí quién sigue.
cola = [
{"id": "A", "prio": 2, "llegada": 1.0},
{"id": "B", "prio": 1, "llegada": 5.0},
{"id": "C", "prio": 1, "llegada": 3.0},
]
orden = sorted(cola, key=lambda e: (e["prio"], e["llegada"]))
print([e["id"] for e in orden])
Ver solución razonada
['C', 'B', 'A']: primero los prio 1 entre sí por llegada (C antes que B), y al final los prio 2. La tupla decide sin if enredados.
Ejercicio 2: espera por clase
Calculá la espera media de VIP y de normales con estos atendidos.
ats = [
{"id": "C5", "prio": 2, "llegada": 4.0, "inicio": 10.0},
{"id": "C7", "prio": 1, "llegada": 8.0, "inicio": 9.0},
{"id": "C8", "prio": 1, "llegada": 9.0, "inicio": 12.0},
]
for p in [1, 2]:
esp = [a["inicio"] - a["llegada"] for a in ats if a["prio"] == p]
print("prio", p, "->", sum(esp) / len(esp))
Ver solución
VIP: (1.0 + 3.0)/2 = 2.0; normal: 6.0. El promedio global (10/3 ≈ 3.3) esconde que los normales esperan el triple: por eso se mide por clase.
Ejercicio 3: constructor único
Escribí nueva_entidad() que fije claves estables y evitá el caos de nombres.
Ver una posible respuesta
contador = 0
def nueva_entidad(llegada, prio=2, tipo="normal"):
global contador
contador += 1
return {"id": f"C{contador}", "llegada": llegada,
"prio": prio, "tipo": tipo, "inicio": None, "fin": None}
print(nueva_entidad(8.0, prio=1, tipo="vip"))
Todas nacen con las mismas claves; inicio/fin en None hasta vivir. Ninguna rutina falla por clave inexistente.
09 · Síntesis
Ideas para recordar
- Atributo = dato de la entidad que distingue, decide y mide; sin ellos solo hay FIFO.
- Fijos (prio, tipo) se sortean al nacer; historia (llegada, inicio, fin) se completa; derivados (espera, vida) se calculan.
- Ordenar es
min(prio, llegada); enrutar es leertipo; medir es agrupar por clase. - En Python: dict con claves estables +
sorted(key=…)+ funciones para derivados. - Los atributos se leen, no se reescriben para forzar el orden.
En el próximo tema veremos los recursos: las entidades estáticas con capacidad limitada por las que compiten las entidades.