Modelos y Simulación · Tema 25

Del papel al programa

Transformar el modelo conceptual en computacional: traducir sin traicionar.

01 · Punto de partida

Traducir es decidir

Entre la ecuación y el programa hay decisiones que la matemática no toma: ¿en qué orden se actualiza?, ¿con qué paso?, ¿en qué estructura viven los datos? Cada decisión puede traicionar al modelo sin que el programa falle: el bug más silencioso del curso.

  • ¿Qué orden de actualización respeta la ecuación?
  • ¿Qué estructuras guardan estado, historia y parámetros?
  • ¿El paso elegido detecta todos los eventos?
  • ¿Cómo demuestro que el código dice lo mismo que el papel?

02 · El puente en 5 pasos

Del esquema al programa verificado

  1. 1
    Esquema.

    Cajas, flechas y frontera validados (Tema 21).

  2. 2
    Ecuaciones.

    Recurrencias y bordes escritos (Tema 24).

  3. 3
    Algoritmo.

    Orden de cálculo, estructuras y paso, en palabras.

  4. 4
    Código.

    Funciones puras de transición + bucle + métricas.

  5. 5
    Verificación.

    Casos con resultado conocido: ecuación contra programa.

La misma idea en tres idiomas.
EsquemaEcuaciónCódigo
Flecha 1 → 2f₁₂ = k × n₁f = k * n1
Stock niveln(t+1) = n(t) + e − sn = n + e - s
Tope 40n = mín(n, 40)n = min(n, 40)
①

Orden

Calcular todo con valores viejos y asignar después: actualización simultánea.

②

Estructuras

Estado en tuplas, historia en listas, parámetros en argumentos.

③

Prueba

Casos conocidos que empatan papel y programa al decimal.

03 · Trampas de traducción

El bug que no falla

Simultáneo (bien)

Foto del instante

Todos los flujos se calculan con el estado viejo y luego se asignan. Respeta la ecuación.

Secuencial (mal)

Mezcla tiempos

El segundo cálculo usa el primero ya actualizado: el flujo lleva un futuro que no ocurrió.

Actualización simultánea
Leer todo lo viejo, escribir todo lo nuevo.
Artefacto numérico
Comportamiento del código sin correlato en el modelo.
Fidelidad
Igualdad verificada entre papel y programa.
Caso testigo
Escenario con resultado conocido que custodia la traducción.

04 · Regla de oro

Primero lo viejo, después lo nuevo

Leer estado viejo→Calcular flujos→Asignar estado nuevo

Variables temporales para los flujos (f) y asignación al final: tres líneas que salvan la fidelidad.

05 · En Python

La misma cascada, dos traducciones

Python en tu navegador. Una respeta la ecuación; la otra mezcla tiempos. Adiviná cuál antes de ejecutar.

def paso_bien(n1, n2, entrada, k, salida2):
    # Simultáneo: el flujo usa los niveles viejos.
    f = k * n1
    return round(n1 + entrada - f, 2), round(n2 + f - salida2, 2)


def paso_mal(n1, n2, entrada, k, salida2):
    # Secuencial: el segundo usa n1 ya actualizado. BUG.
    n1 = n1 + entrada - k * n1
    n2 = n2 + k * n1 - salida2
    return round(n1, 2), round(n2, 2)


print("bien:", paso_bien(10, 5, 3, 0.2, 2))
print("mal: ", paso_mal(10, 5, 3, 0.2, 2))

El error se acumula

def paso_bien(n1, n2, entrada, k, salida2):
    f = k * n1
    return round(n1 + entrada - f, 2), round(n2 + f - salida2, 2)


def historia(paso, n1, n2, pasos):
    h = []
    for t in range(pasos):
        n1, n2 = paso(n1, n2, 3, 0.2, 2)
        h.append(n2)
    return h


print(historia(paso_bien, 10, 5, 4))

06 · Exploración

Laboratorio: la traición acumulada

Dos traducciones de la misma cascada: la correcta (lima) y la secuencial (naranja). Al principio coinciden; con los pasos se separan. Movete el acople.

EXPERIMENTO 25

Simultáneo contra secuencial

tanque 2 · pasos configurables

Los resultados numéricos aparecen debajo.
Correcto final12,34
Secuencial final13,27
Brecha0,93
LecturaCrece

Con 12 pasos la traición suma 0,93 sin ningún error visible.

La brecha entre curvas es puro artefacto de traducción: ningún supuesto la explica.

Preguntas para explorar

  1. Con k = 0,05, ¿la brecha crece o se achica? ¿Por qué?
  2. Llevá los pasos a 24. ¿La traición se estabiliza o sigue sumando?
  3. ¿Qué caso testigo pondrías para cazar este bug?
Ver respuestas sugeridas
  1. Se achica: con poco acople el flujo es chico y mezclar tiempos duele menos.
  2. Sigue sumando: el error es sistemático, no ruido; cada paso agrega su parte.
  3. Un paso a mano: paso_bien(10, 5, 3, 0.2, 2) == (11.0, 5.0) y el secuencial debe dar distinto.

07 · Comprensión

Confusiones frecuentes

«Si corre, traduce bien»

Correr prueba sintaxis, no fidelidad. Solo los casos testigo prueban la traducción.

«El orden da igual con pasos chicos»

Duele menos pero sigue sumando: es sistemático. Además el orden correcto no cuesta nada.

«Traducir es copiar la fórmula»

Es decidir orden, estructuras y paso: la fórmula no dice cómo iterarla.

«Verificar es para el final»

Se verifica cada traducción en el acto, con su caso testigo al lado.

08 · Práctica guiada

Ejercicios con Python

Ejercicio 1: cazar la mezcla

Ejecutá ambas versiones con (10, 5, 3, 0.2, 2). ¿Dónde está la diferencia?

def paso_bien(n1, n2, entrada, k, salida2):
    f = k * n1
    return round(n1 + entrada - f, 2), round(n2 + f - salida2, 2)

def paso_mal(n1, n2, entrada, k, salida2):
    n1 = n1 + entrada - k * n1
    n2 = n2 + k * n1 - salida2
    return round(n1, 2), round(n2, 2)


print(paso_bien(10, 5, 3, 0.2, 2))
print(paso_mal(10, 5, 3, 0.2, 2))
Ver solución razonada

Dan (11.0, 5.0) y (11.0, 5.2): el tanque 2 recibe 2,2 en vez de 2,0 porque el flujo usó el n1 nuevo. Un paso, 0,2 de traición.

Ejercicio 2: acumular la prueba

Corré 4 pasos bien y compará el tanque 2 contra [5.0, 5.2, 5.56, 6.05].

def historia_bien(pasos):
    n1, n2, h = 10, 5, []
    for t in range(pasos):
        f = 0.2 * n1
        n1, n2 = n1 + 3 - f, n2 + f - 2
        h.append(round(n2, 2))
    return h


print(historia_bien(4))
Ver solución

Da [5.0, 5.2, 5.56, 6.05]: coincide con el cálculo a mano del Tema 22. La cadena de testigos se alarga.

Ejercicio 3: escribir el testigo

Escribí un assert que falle con la versión secuencial y pase con la simultánea.

Ver una posible respuesta
def paso_bien(n1, n2, entrada, k, salida2):
    f = k * n1
    return round(n1 + entrada - f, 2), round(n2 + f - salida2, 2)


assert paso_bien(10, 5, 3, 0.2, 2) == (11.0, 5.0)
print("testigo OK")

El secuencial da (11.0, 5.2) y falla: el testigo caza la traición en cada cambio futuro.

09 · Síntesis

Ideas para recordar

  • Traducir es decidir orden, estructuras y paso.
  • Actualización simultánea: leer lo viejo, escribir lo nuevo.
  • El error secuencial es sistemático e invisible sin testigos.
  • Cada traducción trae su caso testigo al lado.
  • En Python: transición pura + bucle + asserts.

En el próximo tema veremos el proyecto completo: el ciclo de vida de la simulación.