Teresa de Jesus Cruz Apanco (A01595188)
The board of directors of a university would like to know whether it is a good idea to start a “traditional” online distance learning programme in addition to the regular on-site programme. The members of the board would like to gain an understanding of the likely dynamics of the number of online students and on-site students over time. Similar programmes elsewhere show that:
Students enroll when entering the programme, and unenroll when finishing the programme or when quitting. The annual number of students that passes the programme is equal to a percentage of the total number of online students, which is lower than the percentage of on-site students passing. Students unenroll due to dissatisfaction with the programme. Dissatisfaction is mainly caused by the perceived quality of the teaching. Enrollment is directly proportional to the tuition fee, the perceived quality of the programme, and is highly dependent on word of mouth advertisement by current and former students. The more students there are in the online programme, the lower the costs per student.
The quality of the teaching/professors depends on experience, expertise, and motivation. Motivation is inversely proportional to their workload and the number of complaints. Complaints are the direct result of the deterioration of the quality. Improving the educational quality raises the cost per online student. And long term teaching overload results in loss of expertise.
A traditional online programme may attract students that would otherwise enroll in the onsite programme, and hence, cannibalize the on-site programme. The work related to the online programme would have to be done by the professors that teach the on-site programme, in addition to their high workload for the on-site programme.
But what if (i) new online courses would not cost professors any additional time after the materials have been developed, (ii) there would be no limit to the number of students that could follow the online course, (iii) there would almost be no costs per student, (iv) these cases would generate a lot of attention, and they would result in attracting brighter students in more advanced and fun courses to teach? Those are the promises of Massive Online Learning Courses or MOOCs.
1.1. Desarrolla el diagrama causal del caso (10 punto, producto: diagrama causal)
1.2. Formula la hipótesis dinámica del comportamiento del sistema. Enfócate en el comportamiento de las variables que consideres son más relevantes. Describe gráficamente tu hipótesis dinámica (7 puntos, productos: hipótesis dinámica y gráfico que la respalde)
Hipóstesis dinámica: Si la universidad implementa un programa tradicional de aprendizaje en línea (COL), es probable que el número de estudiantes en línea crezca rápidamente en los primeros meses debido a la percepción inicial de calidad y a la publicidad boca a boca. Sin embargo, este crecimiento genera sobrecarga en el profesorado, lo cual deteriora la calidad percibida. A medida que la calidad baja, aumentan las quejas y la desmotivación, lo que incrementa la insatisfacción estudiantil y las deserciones. Esta dinámica puede llevar al sistema a una espiral negativa, estabilizándose en niveles bajos de calidad y matrícula, o incluso al colapso del programa, en un horizonte de aproximadamente 1 a 2 años.
En contraste, si se implementan MOOCs, se eliminan muchas de las restricciones estructurales del COL tradicional: no hay sobrecarga continua para los docentes, el costo marginal por estudiante es casi nulo y se pueden alcanzar grandes volúmenes de matrícula. Esto permite mantener e incluso mejorar la calidad sin comprometer la motivación docente. La dinámica resultante es de crecimiento sostenido tanto en la matrícula como en la percepción de calidad, con efectos positivos acumulativos que se consolidan en el mediano plazo.
1.3. ¿Qué aconsejarías hacer a la junta directiva?, ¿deben invertir en estos cursos?, justifica tu respuesta (3 puntos, producto: justificación de la recomendación solicitada)
Recomendaría a la junta directiva que invierta en el desarrollo de cursos tipo MOOC en lugar de un programa tradicional de educación en línea (COL). A diferencia del COL, que depende del tiempo y esfuerzo continuo del profesorado, los MOOCs permiten escalar la enseñanza sin generar sobrecarga adicional una vez que el curso ha sido desarrollado. Esto reduce significativamente los costos marginales por estudiante y evita el deterioro en la calidad percibida por parte de los alumnos, lo cual es clave para mantener su satisfacción y reputación institucional.
Además, como se muestra en la hipótesis dinámica y los gráficos, el sistema COL tiende a entrar en un ciclo negativo donde la sobrecarga docente deteriora la calidad, lo que a su vez aumenta las quejas y reduce la matrícula. En cambio, los MOOCs generan bucles de retroalimentación positiva: más estudiantes satisfechos atraen a más alumnos, se mejora la percepción del programa y se fortalece la motivación docente, especialmente si se orientan hacia cursos avanzados e innovadores. Por estas razones, los MOOCs representan una inversión estratégica con menor riesgo de colapso operativo y mayor potencial de sostenibilidad a mediano y largo plazo.
Suppose that burglaries are mainly committed by members of the organized crime (OC) and by occasional thieves. Burglaries by members of the OC and burglaries by occasional burglars then largely determine the total number of burglaries.
The Netherlands is such a small country and organized crime so well organized that the amount of burglaries by members of the OC depends largely on the effective chance of being caught for burglary in the Netherlands versus the chance of being caught for burglary in neighboring countries. The effective chance of being caught for burglary is proportional to the well-spent police man-hours available for burglaries and inversely proportional to the total police man-hours required for burglaries. Assume the police system is flexible but also rather inert: if total police man-hours required for burglaries increases/decreases, then so do the police man-hours available for burglaries, but with a delay.
Burglaries by occasional thieves mainly depend on the percentage of houses with opportunities for burglaries, which is seasonal (more in winter less in summer) and influenced by the relative media attention with regard to burglaries. The latter is proportional to the total number of burglaries divided by the acceptable number of burglaries.
2.1. Desarrolla el diagrama causal del caso (10 punto, producto: diagrama causal)
2.2. Formula la hipótesis dinámica del comportamiento del sistema. Enfócate en el comportamiento de las variables que consideres son más relevantes. Describe gráficamente tu hipótesis dinámica (7 puntos, productos: hipótesis dinámica y gráfico que la respalde)
Hipóstesis dinámica: Si el número total de robos aumenta, se activan dos tipos de dinámicas en el sistema: una de ajuste policial y otra de reforzamiento por parte de la atención mediática. La primera es una dinámica balanceadora: a medida que los robos aumentan, también lo hace la carga de trabajo policial, lo que lleva —aunque con cierto retraso— a una reasignación de recursos policiales hacia los robos, mejorando así la probabilidad efectiva de captura, y reduciendo en consecuencia los robos cometidos por crimen organizado. Esta es una respuesta estabilizadora, aunque lenta.
La segunda dinámica es reforzadora: el aumento en el número total de robos genera más atención mediática, especialmente cuando los robos superan un umbral considerado socialmente aceptable. Esta atención, lejos de disuadir a los delincuentes ocasionales, puede tener un efecto contrario: funciona como señal de oportunidad. Por ejemplo, si los noticiarios informan constantemente sobre robos en casas durante el invierno, personas con intención delictiva ocasional pueden interpretar que hay muchas viviendas vacías o mal protegidas en esa temporada. Esto refuerza su percepción de que es fácil robar, y los motiva a actuar. Así, la atención mediática, en lugar de prevenir, puede sin querer incentivar nuevos robos por parte de quienes no tienen una actividad delictiva habitual pero ven una oportunidad clara. Esta percepción se alimenta del propio aumento en los robos, generando un ciclo de retroalimentación positiva. Asimismo, el efecto estacional hace que el número de robos aumente o decienda si es invierno o verano.
El sistema, por tanto, presenta un comportamiento dual: mientras el crimen organizado tiende a estabilizarse por el efecto de la respuesta policial, el crimen ocasional puede amplificarse si la percepción de oportunidad no se controla. En conjunto, el número total de robos podría mostrar un crecimiento inicial acelerado, seguido de una desaceleración parcial impulsada por la respuesta institucional, pero sin lograr eliminar completamente la dinámica reforzadora.
Evolución estimada de robos por crimen organizado (línea azul) y por ladrones ocasionales (línea naranja punteada). Se observa estabilización en los primeros y crecimiento estacional reforzado en los segundos.
2.3. Diseña una política que ayude a reducir el número de burglaries, gráfica el nuevo comportamiento del sistema al incluir tu política y comparalo con tu hipótesis dinámica sin política (3 puntos, producto: gráfico contrastando el comportamiento de la hipótesis dinámica con la política propuesta)
Se propone implementar una estrategia dual de prevención que actúe sobre las dos principales fuentes del problema: el crimen organizado y los ladrones ocasionales. La primera medida consiste en una campaña de comunicación preventiva dirigida a cambiar el efecto de la atención mediática. En lugar de que los medios refuercen la percepción de oportunidad entre los ladrones ocasionales, la campaña mostraría las consecuencias legales, las detenciones y los refuerzos operativos como forma de aumentar la percepción de riesgo. La segunda medida contempla el refuerzo policial estacional, particularmente durante los meses de invierno, cuando aumentan las oportunidades para el robo residencial, con el objetivo de incrementar la efectividad de captura de manera anticipada.
Como resultado de esta política, se esperaría una reducción más rápida y sostenida en los robos cometidos por el crimen organizado, debido al aumento oportuno de recursos policiales y su efecto disuasivo. En paralelo, la curva de robos por ladrones ocasionales tendería a crecer más lentamente y con menor estacionalidad, dado que se rompe parcialmente el bucle reforzador generado por la atención mediática. En conjunto, el sistema mostraría una dinámica más controlada, con curvas de comportamiento que reflejan una tendencia decreciente o estabilizada, en contraste con el crecimiento sostenido observado en el escenario sin intervención.
Comparación del comportamiento del sistema con y sin intervención. La política reduce más rápidamente los robos por crimen organizado y desacelera el crecimiento estacional de los robos por ladrones ocasionales.
Este problema tiene como objetivo guiarte en el desarrollo y análisis de un modelo dinámico empleando el lenguaje de programación R. El objetivo es que te familiarices con las herramientas de análisis en R y que inicies el desarrollo de tus propios modelos dinámicos. Para este efecto tomaremos como referencia el caso de la epidemia COVID-19, basándonos en el modelo básico de SARS descrito por Sterman (2013).
Para iniciar tomaremos como referencia el diagrama “stock-flow” de Sterman (2013) mostrado en la siguiente figura.
Como primer paso haremos un listado del tipo de variables en el modelo:
Variables de Estado (Stock variables)
Variables de flujo (flow variables)
Variables auxiliares endógenas (endogenous auxiliary variables)
Parámetros de simulación (variables en la frontera del sistema o exogenous auxiliary variables)
Esta clasificación es útil para organizar el espacio de trabajo en Rstudio.
Tutorial de modelado del caso en R:
Iniciaremos por definir este modelo dinámico como una función definida por el usuario siguiendo los siguientes pasos.
#Carga la librería deSolve empleando la función library()
library("deSolve")
Declara el espacio de trabajo como una función definida por el usuario. En este caso sólo tienes que cambiar el nombre de la función, manteniendo el template que hemos usado en otros modelos
covid.epidemic <- function(t, state, parameters) {
with(as.list(c(state,parameters)), {
#Endogenous auxiliary variables
#Flow variables
#State (stock) variables
dpopulation.susceptible.to.COVID<-
list(c())
})
}
Ahora agregaremos las variables de estado y los flujos asociadas a ellas. Iniciaremos con la variable de estado “Population Susceptible to COVID” como se muestra en el chunk siguiente.
covid.epidemic <- function(t, state, parameters) {
with(as.list(c(state,parameters)), {
#Endogenous auxiliary variables
#Flow variables
#State (stock) variables
dpopulation.susceptible.to.COVID<-
list(c())
})
}
Nota que en R las variables no pueden ser nombradas con espacios. De manera que esta variable de estado es nombrada como: “population.susceptible.to.COVID” nota también que las variables de estado son precedidas por el símbolo diferencial “d” para indicar que esta es una variable de estado, la sintaxis completa es: “dpopulation.susceptible.to.COVID”. Después de este paso habrás creado exitosamente la primera variable de estado del modelo.
Una práctica muy recomendable es documentar tus modelos. En R puedes hacer esto empleando el símbolo “#” y escribiendo delante de éste una breve descripción de la variable que estas representando. Además de describir la variable que estas creando es muy recomendable escribir también las unidades de medición de tu variable. El siguiente chunk muestra un ejemplo:
covid.epidemic <- function(t, state, parameters) {
with(as.list(c(state,parameters)), {
#Endogenous auxiliary variables
#Flow variables
#State (stock) variables
#The population susceptible to COVID is equal to the
#population susceptible prior to the onset of the disease
#less all of those that have contracted it
dpopulation.susceptible.to.COVID<-(-1)*Infection.Rate #Stock units: People/time
#Esta linea indica que variables se imprimen como
#resultado de la integración del modelo, todas las
#variables de estado deben estar listadas
list(c())
})
}
Como se muestra en el stock-flow diagram, la variable “Infection.Rate” está conectada a la variable de estado como un flujo de salida (i.e. outflow variable), esta estructura se modela como se muestra en el chunk anterior. Nota que esta variable de flujo afecta con signo negativo a la variable de estado. Este signo negativo específica a esta variable de flujo como un flujo de salida.
Podemos seguir un proceso similar para modelar y documentar la segunda variable de estado “population.infected.with.COVID” como se muestra en la siguiente figura. Nota que en este caso la variable de flujo “Infection.Rate” es modelada como un flujo de entrada (i.e. inflow variable) y por esta razón no se incluye un signo negativo y nota también que la variable de estado “population.infected.with.COVID” es especificada precedida del signo diferencial “d”.
covid.epidemic <- function(t, state, parameters) {
with(as.list(c(state,parameters)), {
#Endogenous auxiliary variables
#Flow variables
#State (stock) variables
dpopulation.susceptible.to.COVID<-(-1)*Infection.Rate #Stock units: People/time
dpopulation.infected.with.COVID<-Infection.Rate #Stock units: People/time
list(c())
})
}
Como se muestra en el stock-flow diagram, en este modelo solo existe una sola variable de flujo que está conectada a las variables de estado. Esta variable de flujo es determinada por dos variables auxiliares: “Contacts between Infected and Uninfected People” e “Infectivity”. Para este caso especificamos la variable de flujo “Infection.Rate” como la multiplicación simple de estas dos variables auxiliares tal como se muestra en la siguiente figura. Nota que al agregar esta nueva variable también hemos incluido la documentación que describe esta variable y sus unidades de medición.
covid.epidemic <- function(t, state, parameters) {
with(as.list(c(state,parameters)), {
#Endogenous auxiliary variables
#Flow variables
Infection.Rate<-Infectivity*Contacts.bt.Infected.and.Uninfected.People #[people/time]
#State (stock) variables
dpopulation.susceptible.to.COVID<-(-1)*Infection.Rate #Stock units: People/time
dpopulation.infected.with.COVID<-Infection.Rate #Stock units: People/time
list(c())
})
}
Al definir la variable de flujo “Infection.Rate” hemos agregado dos nuevas variables que debemos especificar. La variable “Contacts between Infected and Uninfected People” es una variable auxiliar endógena que es determinada por la variable “Susceptible Contacts” y la variable “Probability of Contact with Infected Person” esta interacción es especificada de la siguiente manera:
covid.epidemic <- function(t, state, parameters) {
with(as.list(c(state,parameters)), {
#Endogenous auxiliary variables
Contacts.bt.Infected.and.Uninfected.People<-Susceptible.Contacts*Probability.of.Contact.with.Infected #[people/time]
#Flow variables
Infection.Rate<-Infectivity*Contacts.bt.Infected.and.Uninfected.People #[people/time]
#State (stock) variables
dpopulation.susceptible.to.COVID<-(-1)*Infection.Rate #Stock units: People/time
dpopulation.infected.with.COVID<-Infection.Rate #Stock units: People/time
list(c())
})
}
Al definir esta nueva variable hemos agregado dos nuevas variables auxiliares endógenas que debemos definir. La primera variable “Susceptible Contacts” es determinada por la variable de estado “Population Susceptible to COVID” y por la variable “Contact Frequency” y es especificada como se muestra en la figura siguiente. Nota que en esta ocasión al emplear la variable de estado para definir otra variable endógena auxiliar no es necesario usar el símbolo diferencial antes de la variable de estado.
covid.epidemic <- function(t, state, parameters) {
with(as.list(c(state,parameters)), {
#Endogenous auxiliary variables
Susceptible.Contacts<-population.susceptible.to.COVID*Contact.Frequency #[people/time]
Contacts.bt.Infected.and.Uninfected.People<-Susceptible.Contacts*Probability.of.Contact.with.Infected #[people/time]
#Flow variables
Infection.Rate<-Infectivity*Contacts.bt.Infected.and.Uninfected.People #[people/time]
#State (stock) variables
dpopulation.susceptible.to.COVID<-(-1)*Infection.Rate #Stock units: People/time
dpopulation.infected.with.COVID<-Infection.Rate #Stock units: People/time
list(c())
})
}
La última variable endógena auxiliar por modelar es la variable “Probability of Contact with Infected Person”. De manera similar al caso anterior, esta variable es determinada por la variable de estado “population infected with COVID” dividida por la variable exógena auxiliar “Total Population”
covid.epidemic <- function(t, state, parameters) {
with(as.list(c(state,parameters)), {
#Endogenous auxiliary variables
Probability.of.Contact.with.Infected<-population.infected.with.COVID/Total.Population #dimensionless
Susceptible.Contacts<-population.susceptible.to.COVID*Contact.Frequency #[people/time]
Contacts.bt.Infected.and.Uninfected.People<-Susceptible.Contacts*Probability.of.Contact.with.Infected #[people/time]
#Flow variables
Infection.Rate<-Infectivity*Contacts.bt.Infected.and.Uninfected.People #[people/time]
#State (stock) variables
dpopulation.susceptible.to.COVID<-(-1)*Infection.Rate #Stock units: People/time
dpopulation.infected.with.COVID<-Infection.Rate #Stock units: People/time
list(c())
})
}
Esto concluye la especificación de todos los elementos endógenos del modelo. El siguiente paso es especificar los valores de los parámetros (i.e. variables auxiliares exógenas), las condiciones iniciales de las variables de estado, el horizonte temporal de análisis y el método de integración para la simulación.
En nuestro modelo hemos especificado tres parámetros: “Contact Frequency”, “Total Population” e “Infectivity”.
En R podemos especificar los parámetros del modelo empleando un vector como se muestra en la siguiente figura. Nota que el nombre de los parámetros es idéntico al nombre empleando en la especificación descrita en los pasos anteriores. También nota que cada parámetro está asociado a un valor numérico único para el cual correremos el modelo de simulación. Finalmente nota que para cada parámetro se especifican sus unidades de medición.
parameters<-c(Infectivity = 0.1, # [1] dimmensionless
Contact.Frequency = 2, # people/day
Total.Population = 350 ) #people)
De igual manera podemos emplear un vector en R para definir las condiciones iniciales de cada variable de estado, esto se muestra en la siguiente figura. Nuevamente el nombre de las variables de estado es idéntico al empleado en la especificación de la modelo y cada variable de estado es inicializada a un valor único.
InitialConditions <- c(population.susceptible.to.COVID = 349 ,
population.infected.with.COVID = 1)
Ahora es necesario especificar el vector de tiempo que será usado para simular el modelo. Esta especificación se lleva a cabo como se muestra en la siguiente figura. Nota que para especificar este vector de tiempo empleamos la función seq(). Esta función crea una secuencia numérica y requiere tres parámetros: valor inicial, valor final e intervalo de crecimiento. En nuestro modelo dinámico estos tres parámetros representan el tiempo inicial de la simulación, el tiempo final de la simulación y la resolución temporal de la simulación. Nota que para cada parámetro hemos indicado la unidad de tiempo correspondiente.
times <- seq(0 , #initial time, days
120 , #end time, days
0.25 ) #time step, days
Aún no discutimos con detalle las propiedades de los diferentes métodos de integración que podemos emplear para simular nuestro modelo. Por lo pronto, para este ejercicio, elegiremos el método Runge-Kutta de Orden 4, en clases subsecuentes estudiaremos las propiedades de otros métodos de integración. La figura siguiente muestra la forma de especificar este método de integración.
intg.method<-c("rk4")
El último paso en el proceso de especificación del modelo es elegir las variables que serán “impresas” por la simulación. Este es un paso muy importante ya que nos permite elegir las variables que deseamos analizar. La figura siguiente muestra la forma de especificar las variables a imprimir por el modelo. Nota que esto es especificado en la última línea de código de la función contiene nuestro modelo dinámico. Nota también que en este caso hemos elegido imprimir sólo las variables de estado y que ambas están precedidas por el signo diferencial “d” y son concatenadas empleando la función c().
covid.epidemic <- function(t, state, parameters) {
with(as.list(c(state,parameters)), {
#Endogenous auxiliary variables
Probability.of.Contact.with.Infected<-population.infected.with.COVID/Total.Population #dimensionless
Susceptible.Contacts<-population.susceptible.to.COVID*Contact.Frequency #[people/time]
Contacts.bt.Infected.and.Uninfected.People<-Susceptible.Contacts*Probability.of.Contact.with.Infected #[people/time]
#Flow variables
Infection.Rate<-Infectivity*Contacts.bt.Infected.and.Uninfected.People #[people/time]
#State (stock) variables
dpopulation.susceptible.to.COVID<-(-1)*Infection.Rate #Stock units: People/time
dpopulation.infected.with.COVID<-Infection.Rate #Stock units: People/time
list(c(dpopulation.susceptible.to.COVID,
dpopulation.infected.with.COVID))
})
}
Esto concluye la especificación del modelo de simulación. El siguiente paso es ejecutar este código y llevar a cabo la simulación. Corre los chunks que contienen la librería deSolve, los vectores que guardamos como parameters, InitialConditions, times e intg.method, y también corre el chunk de la función covid.epidemic.
Una vez realizado esto, en la consola de R ya están cargados tanto el modelo como todos los parámetros necesarios para llevar a cabo la simulación, pero aún no hemos generado datos de la simulación. Para hacer esto, crearemos una base de datos “out” que contiene los resultados de la simulación empleando la función “ode”. Nota que la función “ode” emplea como parámetros de entrada condiciones iniciales de las variables de estado del modelo, el vector de tiempo, la función covid.epidemic que describe nuestro modelo, las variables exógenas (i.e. parámetros) y el método de integración. Todos estos elementos los hemos definido ya en los pasos anteriores.
out <- ode(y = InitialConditions,
times = times,
func = covid.epidemic,
parms = parameters,
method =intg.method )
Si has hecho esto correctamente verás un nuevo objeto llamado “out” listado en el panel superior derecho.
El paso final es analizar gráficamente los resultados para esto emplea la función “plot”
plot(out,
col=c("blue"))
3.1. Incluye tu modelo en un sólo chunk de código en el que se utilice la función plot para ver el comportamiento de las variables de estado. Toma en cuenta que el modelo que envíes será revisado en términos de las sintaxis del código, pero fundamentalmente en términos de su funcionalidad. Un modelo que no funcione al ser ejecutado será penalizado notablemente (2 puntos, productos: chunk con el modelo).
# Cargar librería
library("deSolve")
# Condiciones iniciales
InitialConditions <- c(population.susceptible.to.COVID = 349 ,
population.infected.with.COVID = 1)
# Horizonte temporal
times <- seq(0 , #initial time, days
120 , #end time, days
0.25 ) #time step, days
# Parámetros
parameters <- c(Infectivity = 0.1, # [1] dimmensionless
Contact.Frequency = 2, # people/day
Total.Population = 350 ) #people)
# Método de integración
intg.method<-c("rk4")
#Modelo
covid.epidemic <- function(t, state, parameters) {
with(as.list(c(state,parameters)), {
#Endogenous auxiliary variables
Probability.of.Contact.with.Infected<-population.infected.with.COVID/Total.Population #dimensionless
Susceptible.Contacts<-population.susceptible.to.COVID*Contact.Frequency #[people/time]
Contacts.bt.Infected.and.Uninfected.People<-Susceptible.Contacts*Probability.of.Contact.with.Infected #[people/time]
#Flow variables
Infection.Rate<-Infectivity*Contacts.bt.Infected.and.Uninfected.People #[people/time]
#State (stock) variables
#The population susceptible to COVID is equal to the
#population susceptible prior to the onset of the disease
#less all of those that have contracted it
dpopulation.susceptible.to.COVID<-(-1)*Infection.Rate #Stock units: People/time
dpopulation.infected.with.COVID<-Infection.Rate #Stock units: People/time
list(c(dpopulation.susceptible.to.COVID,
dpopulation.infected.with.COVID))
})
}
out <- ode(y = InitialConditions,
times = times,
func = covid.epidemic,
parms = parameters,
method =intg.method )
plot(out,
xlab = "Time (days)", ylab = "Population",
col=c("blue"))
3.2. ¿Qué sucede cuando inicializas la variable de estado “Population Infected with COVID” en cero? Explica brevemente que origina el comportamiento que observas, emplea la estructura del modelo para cimentar tu argumentación (2 puntos, productos: grafico de simulación y breve descripción).
InitialConditions_zero <- c(
population.susceptible.to.COVID = 350,
population.infected.with.COVID = 0
)
out_zero <- ode(y = InitialConditions_zero,
times = times,
func = covid.epidemic,
parms = parameters,
method = intg.method)
plot(out_zero,
xlab = "Time (days)", ylab = "Population",
col = "blue")
Descripción: Cuando la población infectada al inicio es cero, el modelo no genera ningún cambio a lo largo del tiempo: todas las personas permanecen susceptibles y no hay ningún contagio. Esto pasa porque la tasa de infección depende de la probabilidad de tener contacto con una persona infectada, y si no hay nadie infectado, esa probabilidad es cero. Por eso, aunque haya personas susceptibles y haya contactos, no se transmite el virus. El modelo refleja que, si no hay al menos una persona infectada al comienzo, no puede iniciarse la epidemia, lo cual tiene sentido porque siempre se necesita un caso inicial para que empiece el contagio.
3.3. ¿Cómo cambia la dinámica de comportamiento del modelo si inicializas esta variable de estado a un valor positivo diferente de cero? (2 puntos, productos: gráfico de simulación y breve descripción).
InitialConditions_10 <- c(
population.susceptible.to.COVID = 340,
population.infected.with.COVID = 10
)
out_10 <- ode(y = InitialConditions_10,
times = times,
func = covid.epidemic,
parms = parameters,
method = intg.method)
plot(out_10,
col = c("blue"),
xlab = "Time (days)", ylab = "Population")
Descripción:Cuando se inicia con 10 personas infectadas en lugar de solo 1, el contagio comienza más rápido. Esto se debe a que, desde el principio, la probabilidad de contacto con personas infectadas es mayor. Como resultado, la curva de infectados sube más temprano y la población susceptible disminuye más rápido. En esta simulación, se observa que los contagios aumentan de forma acelerada entre los días 10 y 35 aproximadamente, y para el día 40 prácticamente toda la población ya ha sido infectada. Esto es coherente con la estructura del modelo, que muestra que al haber más personas capaces de contagiar, la tasa de infección se incrementa desde los primeros días y la epidemia se acelera.
3.4. ¿Cómo cambia la dinámica del sistema si aumenta el valor del parámetro “Contact Frequency”? ¿El valor de este parámetro modifica el valor final de la variable de estado “Population Infected with COVID”? Explica porque sí o porque no haciendo referencia a la estructura del modelo y a los resultados de la simulación (4 puntos, productos: gráfico con resultados de simulación y descripción de resultados).
# Aumento de la frecuencia de contacto de 2 a 5 contactos por día
parameters_high_contact <- c(Infectivity = 0.1,
Contact.Frequency = 5,
Total.Population = 350)
InitialConditions <- c(population.susceptible.to.COVID = 349,
population.infected.with.COVID = 1)
out_contact <- ode(y = InitialConditions,
times = times,
func = covid.epidemic,
parms = parameters_high_contact,
method = intg.method)
plot(out_contact,
col = c("blue"),
xlab = "Time (days)", ylab = "Population")
Descripción: Cuando se aumenta el parámetro Contact
Frequency de 2 a 5, el contagio ocurre mucho más rápido. Esto se debe a
que, al haber más contactos por persona por día, crecen las
oportunidades de transmisión del virus. En la simulación, se observa que
el número de infectados se eleva rápidamente desde los primeros días, y
la población susceptible cae abruptamente. Aproximadamente para el día
20, ya casi toda la población ha sido contagiada.
Aunque la velocidad del brote cambia, el valor final de la variable Population Infected with COVID no se modifica, ya que el modelo no considera recuperación ni muerte. Es decir, el 100% de la población termina infectada sin importar cuántos contactos diarios haya; lo que sí cambia es la rapidez con que ocurre. Esto refleja que el parámetro Contact Frequency afecta la dinámica temporal, pero no el resultado final del sistema.
3.5. ¿Cómo cambia el comportamiento del modelo si la variable de flujo “Infection Rate” cambia? Sigue los siguientes lineamientos para dar tu respuesta: Responde a esta pregunta describiendo brevemente los cambios que identificas al cambiar el valor de esta variable. Emplea un par de gráficos de comportamiento del modelo para dar soporte a tu respuesta (6 puntos, productos: gráfico con resultados de simulación y descripción de resultados).
# Escenario 1: Infectivity baja
parameters_low <- c(Infectivity = 0.05, Contact.Frequency = 2, Total.Population = 350)
out_low <- ode(y = InitialConditions,
times = times,
func = covid.epidemic,
parms = parameters_low,
method = intg.method)
plot(out_low,
col = "blue",
xlab = "Time (days)", ylab = "Population")
# Escenario 2: Infectivity alta
parameters_high <- c(Infectivity = 0.3, Contact.Frequency = 2, Total.Population = 350)
out_high <- ode(y = InitialConditions,
times = times,
func = covid.epidemic,
parms = parameters_high,
method = intg.method)
plot(out_high,
col = "blue",
xlab = "Time (days)", ylab = "Population")
Descripción: Cuando se cambia el parámetro Infectivity, se modifica directamente la tasa de infección, ya que esta variable representa la probabilidad de que un contacto entre una persona infectada y una susceptible termine en contagio. En el primer escenario, con infectividad baja (0.05), la epidemia avanza lentamente y la curva de infectados crece de forma gradual. En cambio, cuando la infectividad es alta (0.3), la propagación ocurre de forma mucho más rápida, y en pocos días ya casi toda la población ha sido contagiada.
Aunque el número final de personas infectadas es el mismo en ambos casos (toda la población), el ritmo con el que se llega a ese punto cambia notablemente. Esto confirma que Infectivity no altera el resultado final del modelo, pero sí tiene un efecto muy fuerte sobre la dinámica temporal del contagio. El modelo asume que no hay recuperación, por lo tanto, una vez iniciado el brote, toda persona susceptible terminará infectada, sin importar qué tan contagioso sea el virus, solo que ocurrirá más rápido o más lento según el valor de este parámetro.
3.6. El modelo que has desarrollado siguiendo el tutorial anterior es demasiado simple. Brevemente critica la formulación y estructura del modelo y lista las suposiciones del modelo que consideras son irrealistas. Uno o dos párrafos son más que suficientes para responder este punto (2 puntos, productos: respuesta textual).
El modelo desarrollado es una representación muy simplificada de la dinámica real de una epidemia. Uno de sus principales límites es que no contempla la recuperación ni la muerte de las personas infectadas. Al asumir que todos los individuos infectados permanecen en ese estado indefinidamente, el modelo genera un escenario en el que inevitablemente toda la población termina contagiada. Esta suposición puede ser útil para estudiar el inicio de una epidemia o su potencial de propagación, pero no es realista para enfermedades como COVID-19, donde la mayoría de las personas se recuperan o, en algunos casos, fallecen.
Además, el modelo asume que todas las personas tienen el mismo comportamiento (frecuencia de contacto, probabilidad de infección) y que la población es completamente homogénea y cerrada, sin nacimientos, muertes externas ni movilidad. Estas simplificaciones permiten entender mejor la estructura básica del contagio, pero limitan su utilidad para hacer predicciones aplicadas o diseñar políticas públicas. En ese sentido, el modelo sirve como una base didáctica, pero requiere ampliaciones importantes para representar con mayor fidelidad la realidad epidemiológica.
En el punto anterior identificaste algunas suposiciones irrealistas. Las siguientes preguntas tienen como objetivo que explores que sucede cuando se expanda el modelo para atender sus limitaciones.
Hasta el momento hemos asumido que la población se mantiene infectada con el virus COVID de manera indefinida. En epidemiologia esto se conoce como el modelo SI (i.e. Susceptible-Infectious). El modelo SI es apropiado para representar enfermedades crónicas para las que no existe una cura. Sin embargo, en el caso de muchas enfermedades infecciosas, incluyendo COVID, SARS, viruela o influenza, las personas infectadas pueden recuperarse o en los casos más lamentables morir.
El siguiente diagrama stock-flow expande la estructura del modelo base para describir el proceso de recuperación de la población infectada con COVID. Esta expansión del modelo en epidemiología es conocida como el modelo SIR (i.e. la “R” indica “Recovery”). Sigue las instrucciones siguientes para expandir el modelo del tutorial.
El diagrama stock-flow muestra que debes agregar tres variables nuevas: una nueva variable de estado “Population Recovered from COVID”, una nueva variable de flujo “Recovery Rate” (por simplicidad no distinguiremos entre los pacientes que se recuperan y aquellos que mueren) y un nuevo parámetro “Average Duraction of Infection”.
El parámetro “Average Duraction of Infection” indica el tiempo promedio (i.e. en días) que una persona permanece infectada con el virus COVID. Los epidemiólogos estiman que la fase de infección del COVID tiene una duración promedio de 7 a 21 días. Emplea tu criterio para elegir el valor de este parámetro.
Existen muchas formas de modelar la variable de flujo “Recovery Rate” pero la especificación empleada con mayor frecuencia es la siguiente: Recovery Rate=Population Infected with COVID/Average Duration of Infectivity
Para implementar exitosamente esta estructura en el modelo es necesario que especifiques que esta nueva variable de flujo afecta también a la variable de estado existente “Population Infected with COVID” de la siguiente manera (i.e. sintaxis en R):
dpopulation.infected.with.COVID<-Infection.Rate - Recovery.Rate
También es necesario agregar nueva variable de estado “Population Recovered from COVID”, esto lo puedes lograr empleando la siguiente especificación:
dpopulation.recovered.from.COVID<- Recovery.Rate
Recuerda que al agregar una nueva variable de estado es necesario que indiques en el vector de condiciones iniciales el valor inicial de esta variable y también indicar en la última línea de código de la función “covid.epidemic” que esta nueva variable de estado será impresa por la simulación:
list(c(dpopulation.susceptible.to.COVID, dpopulation.infected.with.COVID, dpopulation.recovered.from.COVID))
Emplea esta nueva versión del modelo para responder a las siguientes preguntas:
3.7. ¿De qué manera cambia el comportamiento de la epidemia una vez que agregas estas nuevas variables al modelo? (10 puntos, productos: nueva versión del modelo, gráficos con comportamiento de las tres variables de estado).
# Carga la librería deSolve
library("deSolve")
# Condiciones iniciales
InitialConditions <- c(
population.susceptible.to.COVID = 349,
population.infected.with.COVID = 25,
population.recovered.from.COVID = 0
)
# Tiempo de simulación
times <- seq(0, 120, 0.25)
# Función del sistema (modelo SIR)
covid.epidemic <- function(t, state, parameters) {
with(as.list(c(state, parameters)), {
# Variables auxiliares endógenas
Probability.of.Contact.with.Infected <- population.infected.with.COVID / Total.Population
Susceptible.Contacts <- population.susceptible.to.COVID * Contact.Frequency
Contacts.bt.Infected.and.Uninfected.People <- Susceptible.Contacts * Probability.of.Contact.with.Infected
# Variables de flujo
Infection.Rate <- Infectivity * Contacts.bt.Infected.and.Uninfected.People
Recovery.Rate <- population.infected.with.COVID / Average.Duration.of.Infection
# Variables de estado (stocks)
dpopulation.susceptible.to.COVID <- -Infection.Rate
dpopulation.infected.with.COVID <- Infection.Rate - Recovery.Rate
dpopulation.recovered.from.COVID <- Recovery.Rate
list(c(
dpopulation.susceptible.to.COVID,
dpopulation.infected.with.COVID,
dpopulation.recovered.from.COVID
))
})
}
# Parámetros
parameters <- c(
Infectivity = 0.02,
Contact.Frequency = 10,
Total.Population = 350,
Average.Duration.of.Infection = 14 # puedes ajustar a 7, 14 o 21 días
)
# Método de integración
intg.method <- "rk4"
# Simulación
out <- ode(
y = InitialConditions,
times = times,
func = covid.epidemic,
parms = parameters,
method = intg.method
)
# Gráficas
plot(out, col = c("blue"))
3.8. ¿Describe gráficamente y con un breve texto el efecto en el sistema de cambios (i.e. incremento y decremento) de las siguientes variables: “contact frequency” y “infectivity”? Enfatiza en las diferencias que percibes con respecto del comportamiento del modelo base. Usa una concisa y breve descripción textual y gráfica (2 puntos, productos: descripción de comportamiento, gráficos describiendo el comportamiento del modelo).
En este escenario, se analiza un brote epidémico con baja infectividad y una frecuencia de contacto moderada. El resultado muestra un crecimiento más pausado en el número de personas infectadas, que alcanza un pico relativamente bajo y bien distribuido en el tiempo. La epidemia se propaga de forma gradual, lo que permite que una mayor proporción de la población susceptible permanezca sin contagiarse durante un periodo prolongado. De igual manera, la transición hacia el estado de recuperación ocurre de forma más lenta y sostenida.
Esta dinámica no impide que eventualmente una parte significativa de la población se infecte, pero sí permite que el sistema de salud tenga más capacidad de respuesta. En otras palabras, reducir el número de contactos o la probabilidad de transmisión no altera demasiado la magnitud final de los contagios, pero sí modifica la velocidad y el impacto temporal del brote, evitando picos abruptos que puedan saturar los servicios médicos.
# Carga la librería deSolve
library("deSolve")
# Condiciones iniciales
InitialConditions <- c(
population.susceptible.to.COVID = 349,
population.infected.with.COVID = 25,
population.recovered.from.COVID = 0
)
# Tiempo de simulación
times <- seq(0, 120, 0.25)
# Función del sistema (modelo SIR)
covid.epidemic <- function(t, state, parameters) {
with(as.list(c(state, parameters)), {
# Variables auxiliares endógenas
Probability.of.Contact.with.Infected <- population.infected.with.COVID / Total.Population
Susceptible.Contacts <- population.susceptible.to.COVID * Contact.Frequency
Contacts.bt.Infected.and.Uninfected.People <- Susceptible.Contacts * Probability.of.Contact.with.Infected
# Variables de flujo
Infection.Rate <- Infectivity * Contacts.bt.Infected.and.Uninfected.People
Recovery.Rate <- population.infected.with.COVID / Average.Duration.of.Infection
# Variables de estado (stocks)
dpopulation.susceptible.to.COVID <- -Infection.Rate
dpopulation.infected.with.COVID <- Infection.Rate - Recovery.Rate
dpopulation.recovered.from.COVID <- Recovery.Rate
list(c(
dpopulation.susceptible.to.COVID,
dpopulation.infected.with.COVID,
dpopulation.recovered.from.COVID
))
})
}
# Parámetros
parameters <- c(
Infectivity = 0.02,
Contact.Frequency = 5,
Total.Population = 350,
Average.Duration.of.Infection = 14 # puedes ajustar a 7, 14 o 21 días
)
# Método de integración
intg.method <- "rk4"
# Simulación
out <- ode(
y = InitialConditions,
times = times,
func = covid.epidemic,
parms = parameters,
method = intg.method
)
# Gráfica del resultado
plot(out, col = c("blue"))
En este segundo caso, se simula una situación de alta transmisibilidad y máxima interacción social, lo que genera una propagación extremadamente rápida del virus. El número de personas infectadas crece con gran velocidad, alcanzando un pico muy alto apenas iniciada la simulación. Este crecimiento acelerado provoca que casi toda la población susceptible se infecte en pocos días, y que el total de personas recuperadas se estabilice rápidamente en niveles cercanos al 100% de la población.
Este tipo de comportamiento representa un brote de gran intensidad y corta duración, pero con consecuencias potencialmente devastadoras, ya que un número muy alto de contagios simultáneos podría desbordar cualquier sistema de atención sanitaria. La comparación con el modelo base deja en evidencia que la combinación de alta infectividad y muchas interacciones favorece una epidemia más agresiva y difícil de controlar, y subraya la importancia de implementar medidas que reduzcan tanto el riesgo de contagio como la frecuencia de contacto en la población.
# Carga la librería deSolve
library("deSolve")
# Condiciones iniciales
InitialConditions <- c(
population.susceptible.to.COVID = 349,
population.infected.with.COVID = 25,
population.recovered.from.COVID = 0
)
# Tiempo de simulación
times <- seq(0, 120, 0.25)
# Función del sistema (modelo SIR)
covid.epidemic <- function(t, state, parameters) {
with(as.list(c(state, parameters)), {
# Variables auxiliares endógenas
Probability.of.Contact.with.Infected <- population.infected.with.COVID / Total.Population
Susceptible.Contacts <- population.susceptible.to.COVID * Contact.Frequency
Contacts.bt.Infected.and.Uninfected.People <- Susceptible.Contacts * Probability.of.Contact.with.Infected
# Variables de flujo
Infection.Rate <- Infectivity * Contacts.bt.Infected.and.Uninfected.People
Recovery.Rate <- population.infected.with.COVID / Average.Duration.of.Infection
# Variables de estado (stocks)
dpopulation.susceptible.to.COVID <- -Infection.Rate
dpopulation.infected.with.COVID <- Infection.Rate - Recovery.Rate
dpopulation.recovered.from.COVID <- Recovery.Rate
list(c(
dpopulation.susceptible.to.COVID,
dpopulation.infected.with.COVID,
dpopulation.recovered.from.COVID
))
})
}
# Parámetros
parameters <- c(
Infectivity = 0.5,
Contact.Frequency = 10,
Total.Population = 350,
Average.Duration.of.Infection = 14 # puedes ajustar a 7, 14 o 21 días
)
# Método de integración
intg.method <- "rk4"
# Simulación
out <- ode(
y = InitialConditions,
times = times,
func = covid.epidemic,
parms = parameters,
method = intg.method
)
# Gráfica del resultado
plot(out, col = c("blue"))
Descripción del caso:
Arms races are escalation processes between two (or more) nations or parties in a conflict that ‘watch each other and [both] respond to [uncertain] arming activities of their opponent with [relatively greater] arming activities of their own’ (Bossel 2007c, p36). The amount of weapons held by one party may actually deter the other party from attacking and vice versa, resulting in a situation of escalating armed peace. This exercise is based on the escalation model described in (Bossel 2007c, Z507).
Suppose there are two gangs, gang A and gang B. Initially, the arms stock of gang A amounts to 100% of the weapons needed to destroy gang B, and the arms stock of gang B amounts to 100% of the weapons needed to destroy gang A. The arms stock of gang A only in/decreases via the arming of gang A and the arms stock of gang B only in/decreases via the arming of gang B. Suppose that the arming of both gangs depends on an autonomous arming rate due to their intrinsic interest in arms and arming –the autonomous arming rate A and autonomous arming rate B respectively– and on an arming rate relative to the expected first order arming of the adversary, that is, the arming of gang B from the point of view of gang A without consideration of the arming of gang A and vice versa. This relative arming rate of gang A –in terms of the weapons needed to destroy gang B– then equals the product of the overassessment factor of gang B arming by gang A, the arms obsolescence rate of gang A, and this arms stock of gang B minus the arms obsolescence rate of gang A times the arms stock of gang A. The same applies to gang B: the relative arming rate of gang B –in terms of the weapons needed to destroy gang A– equals the product of the overassessment factor of gang A arming by gang B, the arms obsolescence rate of gang B and the arms stock of gang A minus the arms obsolescence rate of gang B times the arms stock of gang B. Assume that the autonomous arming rate of gang A and the autonomous arming rate of gang B are both equal to 5% of the weapons needed to destroy the other gang per month and that both arms obsolescence rates equal 10% of the weapons needed to destroy the other gang per month.
Preguntas del caso:
4.1. Desarrolla el diagrama causal del caso (10 puntos, producto: diagrama causal)
4.2. Construye un modelo de dinámica de sistemas de este caso de estudio, suponiendo que la banda A sobreestima el armamento de la banda B en un 10%, es decir, overassessment factor of gang A arming by gang B es 110%, y que la banda B estima correctamente el armamento de la banda A, es decir, overassessment factor of gang A arming by gang B es 100%. Simula el modelo durante un periodo de 100 meses. (15 puntos, producto: modelo en R mostrando el ‘plot’ del comportamiento de las variables de estado)
# Cargar librería
library("deSolve")
# Condiciones iniciales
InitialConditions <- c(armsstockofgangA = 100/100 ,
armsstockofgangB = 100/100)
# Horizonte temporal (meses)
times <- seq(0 , # mes inicial
100 , # mes final
1 ) # cada mes
# Parámetros
parameters <- c(
autonomousarmingrateA = 5/100,
autonomousarmingrateB = 5/100,
overassessmentfactorofgangBarmingbygangA = 100/100,
overassessmentfactorofgangAarmingbygangB = 110/100,
armsobsolescencerateofgangA = 10/100,
armsobsolescencerateofgangB = 10/100
)
# Modelo
arms <- function(t, state, parameters) {
with(as.list(c(state, parameters)), {
# Variables auxiliares endógenas
relativearmingrateofgangA <- (overassessmentfactorofgangBarmingbygangA * armsobsolescencerateofgangA * armsstockofgangB) - (armsobsolescencerateofgangA * armsstockofgangA)
relativearmingrateofgangB <- (overassessmentfactorofgangAarmingbygangB * armsobsolescencerateofgangB * armsstockofgangA) - (armsobsolescencerateofgangB * armsstockofgangB)
# Variables de flujo
armingofgangA <- autonomousarmingrateA + relativearmingrateofgangA
armingofgangB <- autonomousarmingrateB + relativearmingrateofgangB
# Variables de estado (tasas de cambio)
darmsstockofgangA <- armingofgangA
darmsstockofgangB <- armingofgangB
list(c(darmsstockofgangA, darmsstockofgangB))
})
}
# Método de integración
intg.method<-c("rk4")
# Simulación
out <- ode(y = InitialConditions,
times = times,
func = arms,
parms = parameters,
method = intg.method)
# Gráfico con etiquetas
plot(out, col = c("blue"), lwd = 2,
xlab = "Meses", ylab = "Stock de armas")
4.3. Describe textualmente tu hipótesis dinámica de este caso. ¿Qué comportamientos identficas? (2 puntos, producto: descripción de la hipótesis dinámica)
Si ambas bandas comienzan con niveles similares de armamento y se arman a la misma tasa autónoma, pero la banda B sobreestima el armamento de la banda A en un 10%, entonces el sistema evolucionará hacia una escalada armamentista progresiva, en la que ambas bandas incrementan constantemente su arsenal, aunque ninguna ataque a la otra.
Esta dinámica ocurre porque la sobreestimación de la banda B genera una percepción de amenaza mayor a la real, lo que la lleva a armarse más de lo necesario. La banda A, al observar este aumento real en el armamento de B, también incrementa el suyo como respuesta. Así se activa un bucle reforzador, donde el crecimiento del armamento de una banda alimenta el de la otra. En la simulación, este comportamiento se refleja en un crecimiento sostenido del stock de armas de ambas bandas, con una ligera ventaja acumulativa para la banda B, quien inició con una percepción exagerada de riesgo.
4.4. Ahora supongamos que la banda A subestima el armamento de la banda B en un 50%, es decir, que overassessment factor of gang B arming by gang A es del 100%-50% o del 50%, y que la banda B evalúa correctamente el armamento de la banda A, es decir, que overassessment factor of gang A arming by gang B es del 100%. Cambia el o los parámetros correspondientes y vuelve a simular el modelo durante un período de 100 meses. ¿Qué comportamiento muestra la simulación?, ¿por qué? (3 puntos, producto: descripción textual y gráfica del nuevo comportamiento del sistema)
# subestimación de A
parameters_4_4 <- c(
autonomousarmingrateA = 5/100,
autonomousarmingrateB = 5/100,
overassessmentfactorofgangBarmingbygangA = 0.5, # subestima 50%
overassessmentfactorofgangAarmingbygangB = 1.0, # evaluación correcta
armsobsolescencerateofgangA = 10/100,
armsobsolescencerateofgangB = 10/100
)
# Simulación
out_4_4 <- ode(y = InitialConditions,
times = times,
func = arms,
parms = parameters_4_4,
method = intg.method)
# Gráfico
plot(out_4_4, col = c("blue"), lwd = 2,
xlab = "Meses", ylab = "Stock de armas")
Descripción: En este nuevo escenario, la banda A subestima en un 50% el nivel de armamento de la banda B, por lo que percibe una amenaza menor de la real. Esto provoca que reduzca su ritmo de armamento, ya que interpreta que no necesita incrementar tanto su arsenal. En contraste, la banda B evalúa correctamente el nivel de armamento de la banda A y responde con un aumento constante y proporcional de su stock.
Como resultado, se rompe el equilibrio observado en el escenario anterior. La banda B acumula armas de forma más rápida y consistente, mientras que la banda A mantiene un ritmo más bajo de crecimiento. En la simulación, el stock de armas de la banda B crece sostenidamente, mientras que el de la banda A se mantiene relativamente estable o con una pendiente muy baja.
Este comportamiento refleja una dinámica de ventaja para la banda B por la subestimación por parte de A y a largo plazo, esta diferencia podría generar una situación de desequilibrio.