Archivo de la etiqueta: covid

Modelo de epidemia básico con álgebra lineal y Python

Por Leonardo Ignacio Martínez Sandoval

Introducción

En esta entrada voy a platicar de una forma en la que se puede plantear un modelo de epidemia básico usando álgebra lineal. Es un modelo bastante simple, sin embargo a partir de él se pueden verificar varias de las lecciones que hemos estado aprendiendo durante la crisis del coronavirus. A grandes rasgos, haremos algunas suposiciones razonables para plantear una epidemia como un modelo de Markov.

Ya que hagamos esto, estudiaremos dos escenarios posibles: en el que la gente sale de sus casas y en el que la gente se queda en sus casas. Para ello usaremos las librerías NumPy y Matplotlib de Python para hacer las cuentas y generar bonitas gráficas como la siguiente:

Gráfica de evolución de la población con contagio bajo, bajo las suposiciones de nuestro modelo de epidemia básico
Ejemplo del tipo de gráficas que obtendremos en la entrada

En particular, veremos que incluso de este modelo simple se notan contrastes importantes en ambos escenarios. En particular, se puede deducir la importancia de #QuédateEnCasa para retrasar el contagio y no saturar los sistemas de salud.

Advertencia: De ninguna forma esta entrada pretende modelar, específicamente, la evolución del coronavirus. Para ello hay expertos trabajando en el tema, y están usando modelos mucho más sofisticados que el que platicaré. Esta entrada es, en todo caso, una introducción al tema y ayuda a explicar, poco a poco, algunos de los argumentos que se usan en modelación matemática de epidemias.

Suposiciones y modelo tipo Markov

Comenzemos a plantear el modelo de epidemia básico. Pensemos en una enfermedad imaginaria, que se llama «Imagivid» y en un territorio imaginario que se llama «Imagilandia», donde la población inicial es de $100,000$ habitantes sanos, en el día $0$.

Vamos a pensar que una persona puede estar en alguno de los siguientes cinco estados:

  • Sano
  • Síntomas leves
  • Síntomas graves
  • Recuperado
  • Fallecido

Para cada día $n$, consideremos el vector $$X(n)=(s(n),l(n),g(n),r(n),f(n))$$ de $5$ entradas cuyas entradas son los sanos, de síntomas leves, de síntomas graves, recuperados y fallecidos al día $n$. Por ejemplo al día $0$ dijimos que todos están sanos, así que $X(0)=(100000,0,0,0,0)$.

Haremos las siguientes suposiciones de cómo se pasa de un estado a otro

  • Los únicos fallecidos del periodo de tiempo que tendremos son por Imagivid. Sólo se puede fallecer de ello tras tener síntomas graves. Si alguien tiene síntomas graves, entonces tiene cierta probabilidad $g_f$ de fallecer al día siguiente, $g_r$ de recuperarse y por lo tanto $1-g_r-g_f$ de quedarse como enfermo grave.
  • Imagivid se contagia de persona a persona, y de un día a otro una persona tiene probabilidad $s_l$ de pasar de estar sana a tener síntomas leves. No se puede pasar directamente a tener síntomas graves, recuperarse o morir. De modo que se queda sana de un día a otro con probabilidad $1-s_l$
  • Si una persona tiene síntomas leves, tiene probabilidad $l_g$ de pasar a tener síntomas graves y $l_r$ de pasar a recuperarse. Por lo tanto, tiene probabilidad $1-l_g-l_r$ de quedarse con síntomas leves.
  • Una persona que se recupera desarrolla inmunidad a Imagivid, así que se queda en ese estado.
  • Una persona que fallece, se queda en ese estado.

En otras palabras, tenemos el siguiente diagrama de cómo se pasa de tener un estado a otro, en donde los números en las flechas muestran la probabilidad de pasar de un estado a otro:

Diagrama de probabilidades de transición entre estados en el modelo de epidemia básico
Diagrama de probabilidades de transición

En lenguaje técnico, estamos modelando a la epidemia como un proceso de Markov. Sin embargo, no es necesario entender toda la teoría de procesos de Markov para entender lo que sigue, pues la idea es bastante intuitiva.

Con estos números y suposiciones, podemos entender, en valor esperado, cómo será el vector de población $$X(n+1)=(s(n+1), l(n+1), g(n+1), r(n+1), f(n+1))$$ si sabemos cómo es el vector $$X(n)=(s(n), l(n), g(n), r(n), f(n)).$$ Por ejemplo, podemos esperar que la cantidad de recuperados al día $n+1$ sea $$r(n+1)=l_r \cdot l(n)+ g_r \cdot g(n) + 1 \cdot r(n),$$ pues de los de síntomas leves del día $n$ habrá una proporción $l_r$ de ellos que se recuperen, de los graves del día $n$ habrá una proporción $g_r$ de ellos que se recuperen, y todos los recuperados del día $n$ se quedan recuperados. De esta forma, obtenemos el siguiente sistema de ecuaciones de lo que podemos esperar:
\begin{align*}
s(n+1)&=(1-s_l) \cdot s(n)\\
l(n+1)&=s_l \cdot s(n) + (1-l_r-l_g) \cdot l(n)\\
g(n+1)&= l_g \cdot l(n) + (1-g_r-g_f) \cdot g(n)\\
r(n+1)&=l_r \cdot l(n) + g_r \cdot g(n) + 1 \cdot r(n)\\
f(n+1)&=g_f \cdot g(n) + 1 \cdot f(n),
\end{align*}

Este sistema de ecuaciones se puede escribir de una forma mucho más compacta. Si definimos la matriz $$A=\begin{pmatrix} 1-s_l & 0 & 0 & 0 & 0 \\s_l & 1-l_r-l_g & 0 & 0 & 0 \\0 & l_g & 1-g_r-g_f & 0 & 0 \\ 0 & l_r & g_r & 1 & 0\\ 0 & 0 & g_f & 0 & 1 \end{pmatrix},$$ las ecuaciones anteriores se pueden abreviar simplemente a $$X(n+1)=AX(n).$$

De esta forma, si queremos entender qué esperar del día $n$, basta hacer la multiplicación matricial $X(n)=A^n X(0)$.

Un ejemplo concreto en Python

El modelo de epidemia básico que planteamos arriba depende de cinco parámetros:

  • $s_l$, la probabilidad de pasar de estar sano a tener síntomas leves,
  • $l_g$, la probabilidad de pasar de tener síntomas leves a graves,
  • $l_r$, la probabilidad de pasar de tener síntomas leves a recuperarse,
  • $g_r$, la probabilidad de pasar de tener síntomas graves a recuperarse y
  • $g_f$, la probabilidad de pasar de tener síntomas graves, a fallecer.

Hagamos un ejemplo concreto, en el que estos parámetros para Imagivid son los siguientes: $s_l=0.30$, $l_g=0.10$, $l_r=0.20$, $g_r=0.10$ y $g_f=0.10$. En «la vida real», para hacer una modelación correcta se tienen que estimar estos parámetros de lo que ya se sepa de la enfermedad.

Si ponemos estos valores, la matriz que obtenemos es la siguiente:

$$A=\begin{pmatrix} 0.7 & 0 & 0 & 0 & 0 \\0.3 & 0.7 & 0 & 0 & 0 \\0 & 0.1 & 0.8 & 0 & 0 \\ 0 & 0.2 & 0.1 & 1 & 0\\ 0 & 0 & 0.1 & 0 & 1 \end{pmatrix}.$$

Vamos a usar la fórmula que obtuvimos en la sección anterior para entender cómo va evolucionando la epidemia de Imagivid. Para no hacer las cuentas a mano, usaremos Python. Trabajaremos con Python 3 y usaremos Numpy (para las cuentas de matrices) y Matplotlib (para visualizar gráficas). En el siguiente código definimos la población inicial, los parámetros de transición y la matriz de la sección anterior.

import numpy as np
import matplotlib.pyplot as plt
# En cada momento tendremos un vector
# de la distribución de la población
# (sanos, sintomas leves, sintomas graves,
# recuperados, fallecidos)

# Población inicial
x_0=(100000,0,0,0,0)

# Definimos las probabilidades de
# transición

S_L = 0.30
L_G = 0.10
L_R = 0.20
G_R = 0.10
G_F = 0.10

# Definimos la matriz A
A=np.array([[1-S_L,0,0,0,0],[S_L,1-L_G-L_R,0,0,0],[0,L_G,1-G_R-G_F,0,0],[0,L_R,G_R,1,0],[0,0,G_F,0,1]])

Vamos a estudiar la evolución de Imagivid por 60 días. Por ello, vamos a hacer un bucle en Python que calcule cómo son los vectores de población de todos estos 60 días. Para empezar a entender cómo funciona nuestro modelo de epidemia, también pediremos que muestre los valores para los días 1, 2 y 3.

# Encontramos la evolución de la
# epidemia los primeros 60 días
evolution=[x_0]
for j in range(60):
    evolution.append(np.matmul(A,evolution[-1]))
# Mostramos lo que pasa los primeros
# 3 días
for j in range(1,4):
    print(evolution[j])

Los valores que obtenemos son
\begin{align*}
X_1 &= (70000,30000,0,0,0)\\
X_2 &= (49000, 42000, 3000, 6000)\\
X_3 &= (34300, 44100, 6600, 14700, 300).
\end{align*}

Esto nos dice que al primer día hay $70000$ sanos y $30000$ con síntomas leves. En los primeros dos días no hay fallecidos, pues de acuerdo a nuestro modelo de epidemia un habitante primero debe presentar síntomas leves, luego graves y luego ya tal vez fallece. Al día 3 el modelo predice $300$ fallecidos.

Esto son sólo tres días, pero sería bueno poder entender qué sucede en todo el periodo de 60 días. Para ello, vamos a pedir a Python que nos muestre una gráfica de cómo evoluciona la población a través del tiempo. Para ello hacemos lo siguiente

# Hacemos gráfica para mostrar la evolución de todo el tiempo
plt.plot([j[0] for j in evolution], label="Sanos")
plt.plot([j[1] for j in evolution], label="Síntomas leves")
plt.plot([j[2] for j in evolution], label="Síntomas graves")
plt.plot([j[3] for j in evolution], label="Recuperados")
plt.plot([j[4] for j in evolution], label="Fallecidos")
plt.title("Evolución de la población, contagio=0.30")
plt.legend()
plt.show()

Obtenemos la siguiente imagen

Evolución de la población con contagio $0.30$

La gráfica tiene sentido es de esperarse que, tras cierta cantidad de tiempo, ya sólo haya habitantes recuperados y fallecidos. Notemos que hay un momento el el que la población con síntomas leves es de aproximadamente $40,000$ habitantes y que la población con síntomas graves llega a ser, en algún momento, como de $12,000$ habitantes.

¿Qué sucede al final de nuestro periodo de estudio? Si le pedimos a Python que nos de las últimas dos entradas del vector de población al día $60$,

#Mostramos recuperados y fallecidos al último día
print(evolution[-1][3])
print(evolution[-1][4])

obtenemos $\sim 83,333$ recuperados y $\sim 16,666$ fallecidos al día $60$, de modo que en este escenario la epidemia cobró $16,666$ vidas de Imagilandia. De hecho una observación muy importante, viendo la gráfica, es que ya se tenía prácticamente esta cantidad de víctimas desde el día 30.

Disminuir la tasa de infección para retrasar la epidemia

Antes de que sucediera la tragedia, las autoridades de Imagilandia estudiaron el modelo de epidemia que acabamos de mencionar y se dieron cuenta de que tenían que tomar una acción inmediata para mejorar la situación. Decidieron que una cosa muy importante para que la situación mejorara era pedirle a la gente que se quedara en sus casas lo más posible, pues con ello se disminuiría la tasa de contagio. Para ello sacaron la campaña #QuédateEnCasa. Las personas hicieron caso.

Habiendo más personas sanas y enfermas en su propia casa, ahora ni los enfermos pueden contagiar a sanos, ni los sanos estar expuestos a enfermos. Así, una persona sana ahora tiene menor probabilidad de estar enferma al día siguiente. Supongamos que $s_l$ pasa de ser $0.30$ a ahora ser $0.05$. De esta forma, ahora tenemos una nueva matriz que ayuda a calcular la evolución de la pandemia:

$$A=\begin{pmatrix} 0.95 & 0 & 0 & 0 & 0 \\0.05 & 0.7 & 0 & 0 & 0 \\0 & 0.1 & 0.8 & 0 & 0 \\ 0 & 0.2 & 0.1 & 1 & 0\\ 0 & 0 & 0.1 & 0 & 1 \end{pmatrix}.$$

Vamos a pedirle de nuevo a Python que haga las cuentas para los primeros 60 días bajo las suposiciones de nuestro modelo de epidemia y que nos muestre una gráfica de la evolución de la población.

# Definimos las probabilidades de transición, que son iguales salvo que ahora la tasa de contagio es menor, y por lo tanto S_L es menor

S_L = 0.05
L_G = 0.10
L_R = 0.20
G_R = 0.10
G_F = 0.10

# Definimos la matriz A
A=np.array([[1-S_L,0,0,0,0],[S_L,1-L_G-L_R,0,0,0],[0,L_G,1-G_R-G_F,0,0],[0,L_R,G_R,1,0],[0,0,G_F,0,1]])

evolution2=[x_0]
for j in range(60):
    evolution2.append(np.matmul(A,evolution2[-1]))

plt.plot([j[0] for j in evolution2], label="Sanos")
plt.plot([j[1] for j in evolution2], label="Síntomas leves")
plt.plot([j[2] for j in evolution2], label="Síntomas graves")
plt.plot([j[3] for j in evolution2], label="Recuperados")
plt.plot([j[4] for j in evolution2], label="Fallecidos")
plt.title("Evolución de la población, contagio=0.05")
plt.legend()
plt.show()

La gráfica que obtenemos es la siguiente:

Evolución de la población con contagio $0.05$

Una cosa fantástica en este escenario es que nunca hay muchas personas enfermas simultáneamente. En el peor día, parece haber como $12,000$ personas enfermas con síntomas leves, y parece que nunca hay más de $6000$ personas con síntomas graves. ¿Qué sucede con la mortalidad? Si le pedimos a Python que nos diga el número de habitantes recuperados y fallecidos al día 60,

print(evolution2[-1][3])
print(evolution2[-1][4])

obtenemos $\sim 78,419$ recuperados y $\sim 15,438$ fallecidos. Esto es ligeramente mejor que en la situación anterior, en donde había $\sim 16,000$ fallecidos. Donde sí hay una diferencia es en lo que sucede al día $30$. Si pedimos a Python que nos muestre la cantidad de fallecidos al día $30$ en ambos escenarios obtenemos lo siguiente.

print(evolution[30][4])
print(evolution2[30][4])

En el primer escenario, en el que la gente no se queda en casa, al día $30$ tenemos $\sim 16,493$ fallecidos, que es prácticamente ya todos los que habrá. Cuando la gente se queda en casa, al día $30$ sólo hay $\sim 10,963$, una buena parte menos.

Esto parece estar mejor, sin embargo, el tiempo va a seguir pasando, y de todas formas llegaremos al día $60$, en donde ambos escenarios son muy parecidos ¿Por qué entonces todo el esfuerzo de pedirle a la gente que se quede en casa, si la diferencia es mínima? Porque el tiempo es oro.

La carrera contra el tiempo

Hay muchas razones por las cuales es conveniente retrasar la epidemia de Imagivid en Imagilandia, aunque el modelo sencillo que mostramos arriba muestre qe a los 60 días parecería que habrá la misma cantidad de fallecidos.

Primero, es importante retrasar los contagios pues existe la posibilidad de que los científicos de Imagilandia entiendan mejor a Imagivid y, por ejemplo, desarrollen una vacuna o un tratamiento. ¿Qué sucedería si los científicos encuentran una cura al día $30$? En el primer escenario sólo se salvan unas $\sim 150$ vidas, pero en el segundo escenario se salvan unas $\sim 4,500$, osea, unas $\sim 4350$ más. En otras palabras, en el primer escenario el desarrollo científico llega demasiado tarde.

Segundo, también es importante retrasar la epidemia pues permite tener el número de casos simultáneos bajo control. Esto ya lo discutimos un poco arriba, pero pidamos a Python una gráfica más, para poder discutirlo de manera más clara. Supondremos, además, que Imagilandia cuenta con solamente $6000$ camas de hospital en donde se pueden tratar los casos severos de Imagivid, y le pediremos a Python que ponga esto como una línea horizontal.

plt.plot([j[1] for j in evolution2], color="green", linestyle=":", label="Leves, Contagio=0.05")
plt.plot([j[2] for j in evolution2], color="green", label="Severos, Contagio=0.05")
plt.plot([j[1] for j in evolution], color="red", linestyle=":", label="Severos, Contagio=0.30")
plt.plot([j[2] for j in evolution], color="red", label="Severos, Contagio=0.30")
plt.hlines(6000,0,60, color="black", label="Capacidad sistema salud")
plt.title("Enfermos a través del tiempo")
plt.legend()
plt.plot()

Obtenemos la siguiente gráfica:

Comparación de enfermos leves y graves. Rojo es con alto contagio y verde con bajo.

Cuando la gente sí se queda en sus casas y la tasa de contagio es baja (en verde), siempre hay suficiente espacio en el sistema de salud para tratar a a los enfermos graves.

Cuando la gente no se queda en sus casas y la tasa de contagio es alta (en rojo), notemos que los casos severos sobrepasan al sistema de salud. Aproximadamente entre los días $3$ y $15$ se tienen muchos enfermos graves que no podrán ser atendidos correctamente. Por ejemplo, al día 9 hay aproximadamente $\sim 6000$ enfermos graves por encima de la capacidad del sistema de salud. Sin atención médica, probablemente en vez de que sólo fallezcan el $10\%$ de ellos (según nuestro modelo), fallecerán casi todos, dando $5400$ víctimas más que no hemos contado.

De esta forma, siguiendo los consejos de quedarse en casa, la población de Imagilandia puede salvar, potencialmente, $\sim 4350$ personas por la vacuna y $\sim 5400$ personas por evitar saturar el sistema de salud, osea, salvar unas $\sim 9750$ vidas. Para ello es necesario que las autoridades hagan el llamado a quedarse, y que la población de Imagilandia haga caso. De aquí la importancia del #QuédateEnCasa.

Más contenido

Todo el código de Python del modelo lo corrí en una libreta de Jupyter. Puedes ver una versión en PDF de todo el código a continuación.

Si quieres el archivo de Jupyter para jugar con el modelo, puedes obtenerlo en el GitHub del proyecto: https://github.com/leomtz/linear-epidemid.

El modelo de epidemia que presentamos es una aplicación muy sencilla de álgebra lineal. En este blog hemos estado subiendo material de un curso de álgebra lineal que se imparte en la UNAM, y que ahora estamos impartiendo a distancia por la contingencia. A continuación ponemos el enlace a este curso y a otro material que te puede interesar.

Un problema de saltamontes en cuarentena

Por Adán Medrano

Nota de Leo: Esta es una entrada invitada de Adán Medrano Martín del Campo. Nos platicará de un problema de saltamontes (de hecho, de dos) y de funciones en los enteros.

$$\text{Tu}\in \text{Casa}$$

$$\text{Tu}\in \text{Casa}$$

$$\text{Tu}\in \text{Casa}$$

Esto nos aconsejó muy atinadamente el Dr. Hugo López-Gatell Ramírez hace unos pocos días, ya que México y la mayoría del mundo está en cuarentena a causa de la enfermedad COVID19.

Cada vez más y más personas buscamos nuevas actividades para hacer en casa. Junto con Leo Martínez, David Torres (aka Gato) y Pablo Meré, administro el grupo de facebook InsOMMnia, el cual sirve de plataforma para discutir y realizar actividades olímpicamente productivas. A modo de amenizar la cuarentena, hice un video en vivo explicando la solución a un problema que me pareció particularmente agradable por varias razones:

En esta entrada, quisiera platicarles el problema y su solución. Antes de esto, recordemos el problema que apareció en la OMM 2019.

La Momia: OMM 2019

Problema 5. Sean $a>b$ dos números enteros positivos, primos relativos entre sí. En un camino recto, en el cual está marcado cada centímetro $n$, para todo entero $n$, un saltamontes hará algunos saltos comenzando en la marca de $0$ cm y siguiendo las siguientes reglas:

  • Cuando cierto minuto sea múltiplo de $a$ y no múltiplo de $b$, saltará $a$ centímetros hacia adelante.
  • Cuando cierto minuto sea múltiplo de $b$ y no múltiplo de $a$, saltará $b$ centímetros hacia atrás.
  • Cuando cierto minuto sea múltiplo de $a$ y múltiplo de $b$, saltará $a-b$ centímetros hacia adelante.
  • Cuando un minuto no es múltiplo de $a$ ni de $b$, el saltamontes no se mueve del lugar en el que está.

Determina todas las marcas a las que puede llegar el saltamontes.

Nota de Leo: Este es un excelente problema para explorarse buscando un patrón.

Sin dar un spoiler de la solución a dicho problema, el enunciado puede traducirse al siguiente problema de equivalente.

Problema 5′: Sean $a>b$ enteros primos positivos primos relativos entre sí y sea $f:\mathbb{N}\to\mathbb{Z}$ la función dada por
$$f(n)=a\left\lfloor\frac{n}{a}\right\rfloor-b\left\lfloor\frac{n}{b}\right\rfloor.$$
Determina la imagen de $f$.

Uno puede jugar un poco con la función definida arriba, y llegar a la respuesta usando propiedades de dicha función. El objetivo de mostrarles este enunciado equivalente, es que muchas veces ciertos problemas que hablan de ciertos procesos pueden describirse (y resolverse) en términos de funciones construidas apropiadamente.

El problema que resolveremos cae en la categoría opuesta, pues es un problema sobre una función, al cual se le puede dar una interpretación de un saltamontes haciendo… algo.

El Vampiro: Romania TST 2019

Problema: Sean $a<b<c$ enteros positivos y sea $f:\mathbb{N}\to \mathbb{N}$ una función dada por
$$f(n)=\begin{cases}
n-a & n>c \\
f(f(n+b)) & n\leq c
\end{cases}$$
Determina la cantidad de enteros positivos $n$ tales que $f(n)=n$.

«Y eso qué tiene que ver con un saltamontes?» podrías pensar en este momento. ¡Ha ha! Mira ahora este problema de saltamontes.

Problema’: Sean $a<b<c$ enteros positivos. Un saltamontes se encuentra sobre un entero $n>0$ en la recta real positiva, donde hay pasto en los enteros positivos menores o iguales que $c$, y lava en los enteros mayores a $c$. Inicialmente, el saltamontes tiene una vida, y mientras el saltamontes tenga al menos una vida, se dispondrá a saltar de la siguiente manera:

  • Si el saltamontes se encuentra en el pasto, el saltamontes gana una vida y salta $b$ enteros hacia adelante.
  • Si el saltamontes se encuentra en la lava, el saltamontes pierde una vida y salta $a$ enteros hacia atrás.

Cuando el saltamontes tiene $0$ vidas, este muere y deja de moverse. Determina todas las posiciones iniciales del saltamontes tal que el saltamontes morirá en su posición inicial.

Saltamontes, lava, pasto y vidas
Problema visto como vidas, pasto, lava y saltamontes.

A que no se lo esperaban. (Honestamente yo tampoco, pero últimamente tengo más tiempo libre). Tal vez este problema inspire algún mini juego en alguna entrega futura de The Legend of Zelda.

Y, ¿cómo resolvemos algo así?

El Santo: venciendo a la momia y al vampiro

Spoiler Alert:

A continuación resolveremos los problemas, en caso que estés intentándolos y no quieras ver sus soluciones

La clave para ambos problemas es: ¡usar residuos y propiedades de las funciones en juego!

Solución al problema 5 del nacional

Notemos que al dividir $n$ entre $a$ y entre $b$, obtenemos
$$n=a\left\lfloor \frac{n}{a}\right\rfloor+r_{a}$$ y $$n=b\left\lfloor \frac{n}{b}\right\rfloor+r_{b}$$
donde

$$0\leq r_{a}\leq a-1$$ y $$0\leq r_{b}\leq b-1$$
son precisamente los residuos que resultan de la división. Notemos entonces que

\begin{align*}
f(n)&=a\left\lfloor\frac{n}{a}\right\rfloor-b\left\lfloor\frac{n}{b}\right\rfloor\\
&=\left(n-b\left\lfloor \frac{n}{b}\right\rfloor\right)-\left(n-a\left\lfloor \frac{n}{a}\right\rfloor\right)\\
&=r_{b}-r_{a}
\end{align*}

por lo que $f(n)$ simplemente depende de la diferencia entre $r_{b}$ y $r_{a}$. Por el Teorema Chino del Residuo, o simplemente mirando exclusivamente a los múltiplos de $a$ y de $b$ entre $1$ y $ab$, aparecen como diferencia todos los posibles enteros en el intervalo

$$[-a+1, b-1]$$
lo cual compone la imagen de $f$, que es lo que buscábamos.

$\square$

¡Genial! Mirar los residuos fue clave en el problema de saltamontes del nacional. En particular, no lo usamos en nuestra solución, pero $f$ resulta ser una función periódica, con periodo $ab$. Esto es gracias a que $a$ y $b$ son primos relativos, y por lo tanto cada pareja de residuos $r_{a}, r_{b}$ se repiten exactamente cada $ab$ enteros.

La periodicidad será una propiedad clave en la solución del problema del selectivo rumano. Comenzamos mostrando una exploración del problema.

Exploración del problema del selectivo rumano

Los puntos $n$ tales que $f(n)=n$ son llamados puntos fijos. En la formulación como problema de saltamontes, corresponden a que el saltamontes muera justo donde empezó: «muera» es que ya no haya $f$, empieza con una vida, osea una $f$.

Notemos que si $n>c$, entonces $n$ no es un punto fijo, pues

$$f(n)=n-a\neq n.$$
Esto nos dice que los puntos fijos son menores o iguales que $c$. Ahora, notemos que (recordemos que $a<b<c$)

\begin{align*}
f(c)&=f(f(c+b))\\
&=f(c+b-a)=c+b-2a
\end{align*}

y esto nos lleva a considerar que números cercanos a $c$, dentro de un intervalo de tamaño $b-a$, tendrán un valor similar. En efecto, si $0\leq r<b-a$ entonces

\begin{align*}f(c-r)&=f(f(c-r+b))\\&=f(c-r+b-a)\\&=c-r+b-2a.\end{align*}
Ahora, veamos que restando $b-a$ a $c$, perdemos este patrón, pues

\begin{align*}f(c-b+a)&=f(f(c+a))\\&=f(c)\\&=c+b-2a\end{align*}
¡Hemos regresado a un valor ya conocido! Esto nos lleva a la hipótesis de que $f$ es periódica con periodo $b-a$ en el intervalo $[1, c]$. Formalicemos estas observaciones.

Un par de lemas para el problema rumano

La manera de enunciar formalmente las observaciones anteriores esto es, por ejemplo, via el siguiente lema:

Lema 1: Sea $n=c-r-k(b-a)$ un entero positivo menor o igual que $c$ donde $k\geq 0$ y $0\leq r<b-a$. Entonces
$$f(n)=c-r+b-2a.$$

(Prueba del lema 1): Procederemos por descenso en los enteros positivos. Construiremos una secuencia de valores iguales, con distinta cantidad de $f$’s compuestas, de la siguiente manera: comenzamos con
$$z_{0}=n=c-r-k(b-a)$$
y definimos

$$z_{i+1}=\begin{cases}
z_{i}-a & z_{i}>c \\
z_{i}+b & z_{i}\leq c
\end{cases}$$

para todo $i\geq 0$. Además, escribiremos

$$z_{i}=c-r-y_{i}b+x_{i}a$$
donde $x_{0}=y_{0}=k$, y ambas secuencias $\left\{x_{i}\right\}$ y $\left\{y_{i}\right\}$ decrecen, definiendo

$$x_{i+1}=\begin{cases}
x_{i}-1 & z_{i}>c \\
x_{i} & z_{i}\leq c
\end{cases}$$ y

$$y_{i+1}=\begin{cases}
y_{i} & z_{i}>c \\
y_{i}-1 & z_{i}\leq c
\end{cases}$$
Habiendo definido esto, tenemos que

$$f(n)=f^{(1+x_{i}-y_{i})}(z_{i})$$
para todo $i\geq 0$.


Observemos que si $y_{i}=-1$ entonces $z_{i}=c-r+b+x_{i}a>c$ si se cumple que $x_{i}\geq -1$. Más aún, observemos el siguiente lema:

Lema 2: Para todo $i\geq 0$, tenemos que $y_{i}\geq 0$ implica que $y_{i+1}\leq x_{i+1}$.

(Prueba del lema 2): Procedemos por inducción. Para $i=0$ esto es claro, pues
$$y_{1}=k-1<k=x_{1}.$$
Ahora, supongamos que $x_{i}\geq y_{i}\geq 0$. Si $x_{i}>y_{i}$ entonces

$$x_{i+1}\geq x_{i}-1\geq y_{i}\geq y_{i+1}.$$
Si $x_{i}=y_{i}$ entonces tenemos que

$$z_{i}=c-r-y_{i}(b-a)\leq c$$
por lo que $z_{i+1}=z_{i}+b$ y esto implica que

$$x_{i+1}=x_{i}>y_{i}-1=y_{i+1}.$$

$\square$

Hemos probado pues que las secuencias $\left\{x_{i}\right\}$ y $\left\{y_{i}\right\}$ decrecen, y mientras $y_{i}\geq 0$, tendremos que $x_{i+1}\geq y_{i+1}$. ¿Cómo hemos de proseguir con esto?

La clave es notar la existencia de la menor $m$ tal que $y_{m}=-1$, donde es claro que $y_{m-1}=0$. Si $m=1$ entonces $y_{0}=x_{0}=k=0$, y ya hemos cubierto ese caso arriba, así que asumiremos que $m>1$. Tenemos que $y_{m-2}\geq 0$ por lo que, por el lema 2,

$$x_{m-1}\geq y_{m-1}=0$$
y como $y_{m}=y_{m-1}-1$ entonces $x_{m}=x_{m-1}\geq 0$. Esto implica que

\begin{align*}z_{m}&=c-r+b+x_{m}a\\&\geq c-r+b\\&>c\end{align*}
por lo que para todo $j>m$ se tiene que $x_{j+1}=x_{j}-1$

$$z_{m+x_{m}+1}=c-r+b-a$$
y tenemos que $y_{m+x_{m}+1}=x_{m+x_{m}+1}=-1$, lo que muestra que

\begin{align*}f(n)&=f(z_{m+x_{m}+1})\\&=f(c-r+b-a)\\&=c-r+b-2a.\end{align*}

$\square$

Juntando todo

Vaya, después de arduo trabajo hemos mostrado la periodicidad de $f$. Lo que falta únicamente, es usar esto para hacer una conclusión sobre los puntos fijos. Notemos que los únicos valores de $f$ en el dominio $[1, c]$ son $c-r+b-2a$ para $0\leq r<b-a$, así que solo estos valores pueden ser puntos fijos de $f$. De hecho, cada uno de esos valores es un punto fijo si y solo si podemos encontrar una $k\geq 0$ tal que

$$c-r-k(b-a)=c-r+b-2a$$, lo cual sucede si y sólo si $(k+1)(b-a)=a$, o bien justo cuando $b-a\mid a$, por lo que si $b-a$ divide a $a$, todos nuestros $b-a$ valores son puntos fijos, y si $b-a$ no divide a $a$, ningún valor es un punto fijo. Hemos concluido entonces.

$\square$

Antes de regresar a la cuarentena

Espero que hayan pasado un rato agradable pensando en este problema, y espero que hayan entendido 4 lecciones:

  • Quédate en casa
  • Quédate en casa
  • Quédate en casa
  • Es una buena idea usar residuos y secuencias jugando con enteros.

Con esto me despido y, ¡hasta la próxima!

COVID 2019 – Reflexión y estrategia sobre clases a distancia

Por Leonardo Ignacio Martínez Sandoval

Es fundamental durante la crisis del COVID implementar estrategias de distanciamiento social que eviten la propagación del virus. Si bien el virus tiene efectos tenues en el 80% de la población, queremos alentar lo más posible la propagación del virus para que el 20% restante pueda ser atendido sin rebasar la capacidad del sistema de salud.

Con esto en mente, la UNAM ya anunció la suspensión gradual de clases. La Facultad de Ciencias suspende clases ya desde mañana martes.

En estos días he estado pensando bastante en cómo enfrentar la situación como profesor universitario en la UNAM. Tomando en cuenta lo que les he preguntado por acá y pláticas que he tenido con otros colegas, me convencido de que:

  • No podemos asumir que los estudiantes tendrán acceso a computadora o a un buen internet continuamente.
  • No podemos asumir que los estudiantes estarán disponibles exactamente a la hora en la que usualmente es la clase.
  • No a todos los profesores se les hará fácil impartir de improvisto una versión de su clase de manera inmediata.
  • El material que se prepare debe ser gratuito, de libre acceso y de calidad.
  • Hay herramientas maravillosas como Google Classroom, Moodle y otras más. Pero desde mi perspectiva, no cumplen con los estándares de universalidad y libre acceso que este caso requiere.

Debido a esto, he decidido enfrentar a la crisis mediante la siguiente estrategia:

  • No usaré streamings o «medios en vivo» como chats para impartir la clase.
  • Para cada sesión, indicaré exactamente qué contenido de la bibliografía veríamos durante la clase.
  • Para cada sesión prepararé, además, con apoyo de los ayudantes del curso, una entrada aquí en el blog para que los estudiantes tengan ejemplos y explicaciones adicionales.
  • Acabo de avisar a la Coordinación de la Carrera de Matemáticas que ayudaré a los colegas del Departamento de Matemáticas que así lo requieran en orientarlos en escribir entradas de blog (con LaTeX y todo).
  • Así mismo, ofreceré de manera gratuita espacio de almacenamiento aquí en el blog para los colegas que requieran subir entradas o tareas. Esto con el fin de que no tengan que abrir cuentas de WordPress o buscar un servidor, y puedan dedicarse a escribir material para su curso de manera inmediata.

Si eres uno de estos colegas, o cualquier otro profesor, me puedes contactar por aquí o por FB para detalles.