Modelos Continuos · Tema 45

Proyecto de simulación continua

Un simulador dinámico completo en Python: modelo, método, escenarios y decisión.

01 · Punto de partida

El curso en un programa

El proyecto integra los 44 temas en un simulador SIR con intervención: estados S/I/R (Temas 3, 10, 20), EDOs con tasas (7–8), equilibrio y R₀ (25–26), Euler vectorial con dt validado (29–36), escenarios base/intervenido (42), umbral de camas y gatillo (44). Un solo archivo, una sola decisión: ¿cuándo intervenir y con qué eficacia?

Al final tendrás un laboratorio reutilizable: cambiar la enfermedad es cambiar (β, γ); cambiar la política es cambiar (día, eficacia).

  • ¿El integrador conserva N y converge con dt/2?
  • ¿R₀ y el pico base reproducen el Tema 20?
  • ¿La intervención baja del umbral con costo aceptado?
  • ¿La decisión aguanta en el abanico β ± 20 %?

02 · Definición

¿Qué entrega el proyecto?

Cinco piezas chequeables:

ƒ

Modelo f

SIR con β(t) por tramos: base hasta el día D, reducida después. Conserva N.

∑

Método

Euler vectorial dt = 0,5 validado contra dt = 0,25 y RK4: pico ±2.

✓

Decisión

Base vs intervenido en pico, ataque y días > camas, con abanico β ± 20 %.

La intervención es un híbrido por tiempo (Tema 38): el flujo es continuo, el día D es el evento.

Entregables y su tema de origen.
PiezaVerificaciónTemas
f_sir + R₀Tasas suman 0; R₀ = β/γ.10, 20, 25.
Euler vectorialConserva N; converge con dt/2.29–36.
EscenariosMismo dt, T y métrica en todos.41–42.
Umbral y gatilloDías > camas por escenario.43–44.

03 · Anatomía

Lista de aceptación del simulador

El proyecto está terminado cuando pasa estos cinco tests:

Conserva
S + I + R = N en cada nodo (assert ≤ 1e−6). Si deriva, el paso mezcla tiempos.
Converge
Pico dt = 0,5 vs 0,25 difieren ≤ 2: el método está verificado.
Reproduce
Base β = 0,3: pico ≈ 301, ataque ≈ 94 % (Tema 20). El modelo es el mismo.
Decide
Intervenido baja días > 150 con costo declarado: la métrica dispara.
Aguanta
Con β ± 20 % la decisión no se da vuelta: robustez factorial.

Simulador terminado

Cinco tildes verdes

Conserva, converge, reproduce, decide y aguanta. Se entrega con tabla de corridas.

Simulador a medias

Curvas sin tests

Dibuja lindo pero no conserva, no converge o no compara con igual dt. No decide.

04 · Ruta del proyecto

Del enunciado a la decisión en cinco fases

El orden que evita retrabajo:

f + tests→Método→Escenarios
  1. 1
    Modelo.

    f_sir con β(t) + assert de conservación + R₀. (Temas 10, 20.)

  2. 2
    Método.

    Euler vectorial + convergencia dt/0,25 + chequeo RK4. (Temas 29–36.)

  3. 3
    Escenarios.

    Base, temprana, tardía: mismo dt, T y métricas. (Temas 41–42.)

  4. 4
    Visualización.

    Tiempo (pico), fase (ataque), log (tasa). (Tema 43.)

  5. 5
    Decisión.

    Umbral, días evitados, costo, abanico β ± 20 %. (Tema 44.)

05 · Representación en Python

El simulador completo en un bloque

Todo el curso en 30 líneas: f por tramos, Euler vectorial con assert, métricas y escenarios. Copialo, ejecutalo y extendelo.

Python en tu navegador. Este bloque se ejecuta localmente con Pyodide, sin instalar nada. Cambiá el día D a 60 y observá que la intervención llega tarde.

def simular(beta0=0.3, gamma=0.1, eficacia=0.5, dia=30, n=1000, i0=10, dias=160, dt=0.5, camas=150):
    s, i, r, t = n - i0, float(i0), 0.0, 0.0
    pico, sobre = i, 0.0
    while t < dias - 1e-9:
        h = min(dt, dias - t)
        beta = beta0 if t < dia else beta0 * (1 - eficacia)
        c = beta * s * i / n
        s, i, r = s - c * h, i + (c - gamma * i) * h, r + gamma * i * h
        assert abs(s + i + r - n) < 1e-6
        pico = max(pico, i)
        if i > camas:
            sobre += h
        t += h
    return {"pico": round(pico, 1), "ataque": round(r / n * 100, 1), "dias": round(sobre, 1)}


base = simular(eficacia=0.0)
med = simular()
print("base:", base)
print("medida:", med, "evita:", round(base["dias"] - med["dias"], 1))

Base: pico 300,8, ataque 94 %, 40 días. Medida día 30: pico ≈ 180, días ≈ 12. El proyecto decide.

Robustez en el abanico

La decisión debe aguantar β ± 20 %:

for b in [0.24, 0.30, 0.36]:
    m = simular(beta0=b)
    v = simular(beta0=b, eficacia=0.5, dia=30)
    print(b, "base:", m["dias"], "medida:", v["dias"])

06 · Exploración

Laboratorio: el día D decide

SIR base (tenue) contra intervención que baja β a la mitad desde tu día D (teal), con camas 150 punteadas. Movete D de 10 a 60 y observá que la misma eficacia evita 40 días o apenas 5: intervenir temprano es otro modelo que intervenir tarde.

EXPERIMENTO 45

Temprano o tarde

β₀ = 0,3 · −50 % desde D · camas 150

Los resultados numéricos aparecen debajo.
Pico base300,80
Pico medida180,40
Días evitados28,00
SemáforoAlivia mucho

Con D 30 se evitan 28 días: temprano alivia, tardío lamenta.

La curva intervenida copia la base hasta D y ahí se dobla: el codo marca el día de la medida.

Preguntas para explorar

  1. Con D = 10, ¿los días evitados llegan a 40? ¿Y con D = 60?
  2. Con eficacia 0 %, ¿las curvas se superponen? ¿Qué valida eso?
  3. Si β base fuera 0,5, ¿tu medida del 50 % desde D = 30 alcanza el verde?
Ver respuestas sugeridas
  1. D = 10 evita casi todo; D = 60 apenas 5: el día decide más que la eficacia.
  2. Sí: eficacia 0 reproduce la base. Test de humo del simulador.
  3. No: β = 0,25 efectivo sigue en R₀ = 2,5. Hay que adelantar D o subir eficacia.

07 · Comprensión

Confusiones frecuentes

«El proyecto es el gráfico»

Es la tabla de decisión con tests: el gráfico ilustra, los cinco tildes entregan.

«Intervenir es bajar β»

Es bajar β desde D con costo y fatiga: el día es tan parámetro como la eficacia.

«Con dt = 2 alcanza»

El pico se pasa en 20: la decisión con dt grueso exagera. dt = 0,5 validado o nada.

«Un escenario basta»

Sin base no hay resta y sin abanico no hay robustez: mínimo base + medida + β ± 20 %.

08 · Práctica guiada

Ejercicios con Python

Ejercicio 1: test de humo

Con eficacia 0, ¿la medida iguala a la base? Verificá pico y días.

print(simular(eficacia=0.0, dia=30))
print(simular(eficacia=0.0, dia=10))
Ver solución

Ambas dan la base (pico 300,8, 40 días): eficacia 0 es no-intervenir. El simulador pasa el humo.

Ejercicio 2: día que decide

Compará días evitados con D = 15 y D = 45 (eficacia 50 %). ¿Cuánto cuesta demorar?

base = simular(eficacia=0.0)["dias"]
for d in [15, 45]:
    m = simular(dia=d)["dias"]
    print(d, m, "evita:", round(base - m, 1))
Ver solución

D = 15 evita ≈ 38; D = 45 evita ≈ 12: demorar 30 días triplica la crisis. El día es la medida.

Ejercicio 3: entrega final

Armá la tabla base / temprana (D = 15) / tardía (D = 45) con (pico, ataque, días) y el veredicto robusto con β ± 20 %.

Ver una posible respuesta
for nombre, kw in {"base": {"eficacia": 0.0}, "temprana": {"dia": 15}, "tardía": {"dia": 45}}.items():
    print(nombre, simular(**kw))
for b in [0.24, 0.36]:
    print("β", b, simular(beta0=b, dia=15)["dias"], "vs base", simular(beta0=b, eficacia=0.0)["dias"])

Temprana evita en las tres β; tardía falla en β = 0,36: veredicto intervenir día ≤ 15. Proyecto cerrado.

09 · Síntesis

Ideas para recordar

  • Proyecto = f + método + escenarios + umbral + robustez, con cinco tests verdes.
  • β(t) por tramos: la intervención es un híbrido fechado en D.
  • El día D decide tanto como la eficacia: temprano evita, tardío lamenta.
  • En Python: simular() con assert + escenarios + abanico β ± 20 %.
  • Entregar tabla versionada, no solo curvas: la decisión se audita.

Fin del curso: del sistema continuo a la decisión robusta, pasando por la ecuación, el número y el escenario. ¡A simular!