Estoy tratando de simular un modelo estocástico de crecimiento exponencial determinista de la población, donde $dN/dt = rN$ donde $N$ es el tamaño de la población y $r$ es la tasa ($t$ tiempo). Estoy asumiendo que no hay capacidad de carga. Esta página (http://cnr.lwlss.net/DiscreteStochasticLogistic/) sugiere este algoritmo para simular el crecimiento en un intervalo $[0, t_{end}]$:
- empieza en $t = 0$ con tamaño de población inicial
- elige el siguiente tiempo para el evento de nacimiento, $\delta t \sim Exponencial(rN(1 - N/K))$ ($K$ es la capacidad de carga)
- incrementa el tamaño de la población, $N = N + 1$
- establece $t = t + \delta t$
- si $t > t_{end}$ entonces termina, de lo contrario ve al paso 2.
Dado que no tengo una capacidad de carga $K$, asumo que es infinita, entonces el próximo tiempo de nacimiento es $\delta t \sim Exponencial(rN)$. ¿Es eso correcto?
cuando ejecuto la simulación de esta manera, no proporciona en absoluto resultados similares a $N(t) = P_0 e^{rt}$ (donde $P_0$ es el tamaño inicial de la población). incluso promediando sobre muchas iteraciones parece dar curvas de crecimiento diferentes.
a continuación se muestra mi código y el resultado de la simulación. la curva roja es crecimiento exponencial determinista, las curvas negras son simulaciones usando distribución exponencial. claramente no coinciden.
import numpy as np
import matplotlib.pylab as plt
def sim(rate, start, end, init):
N = 200
tamañosfinales = []
resultados = []
for n in range(N):
tamaño = init
curr_t = 0
tiempos = [curr_t]
tamaños = [init]
nueva_tasa = rate
while curr_t <= end:
# simular próximo tiempo de nacimiento. el parámetro de escala
# es inversamente proporcional al tamaño de la población
nueva_tasa = 1/float(nueva_tasa * tamaño)
tiempo_div = np.random.exponential(scale=nueva_tasa)
# avanzar en el tiempo
curr_t += tiempo_div
if curr_t > end:
# si excedemos el intervalo de tiempo, terminamos
break
tiempos.append(curr_t)
# aumentar el tamaño de la población
tamaño += 1
tamaños.append(tamaño)
tamañosfinales.append([tiempos, tamaños])
return tamañosfinales
# ejecutar simulación y graficar resultados
init = 20
start = 0
end = 20
rate = 1
tamañosfinales = sim(rate, start, end, init)
plt.figure()
todoslostamaños = []
for f in tamañosfinales:
todoslostamaños.append(f[1][-1])
plt.plot(f[0], f[1], color="k", alpha=0.5)
tiempos = np.arange(0, end + 1)
plt.plot(tiempos, init*np.power(2, rate * tiempos), color="r")
plt.xlabel("tiempo")
plt.ylabel("tamaño de la población")
print "tamaño final promedio: ", np.mean(todoslostamaños)
plt.show()
respuesta a la excelente respuesta de whuber: no entiendo por qué tengo que especificar el tamaño de la población de antemano. mi simulación pretende preguntar: ¿en una cantidad determinada de tiempo, cuál será la variabilidad en el tamaño de la población asumiendo un crecimiento exponencial? (y no, ¿cuánto tiempo se necesita en promedio para hacer una población de tamaño $N$, que es lo que parece estar haciendo la simulación de whuber).
tampoco creo que sea correcto que "todavía no he hecho suficientes simulaciones para apreciar lo que te están diciendo". actualicé mi simulación para graficar 1000 corridas. como puedes ver, con mi condición de finalización basada en el tiempo, los resultados consistentemente subestiman el tamaño de la población de crecimiento exponencial determinista.
mi razonamiento era que si simulo $N$ corridas por una duración $t$, entonces a medida que $N \rightarrow \infty$, el tamaño promedio de la población que obtengo de mi simulación debería ser una estimación imparcial del tamaño de la población basada en el modelo de crecimiento exponencial determinista para $t$, es decir, $2^{rt}$. por ejemplo, si simulo 3 pasos de tiempo (comenzando con un solo individuo), esperaría que el tamaño de la población a veces sea mayor que 8 en la simulación y a veces menor que 8, y el promedio converja a 8. parece que esto debería ser cierto incluso si comienzo con una población muy pequeña, siempre y cuando simule suficientes corridas. ¿esto es incorrecto? ¿cuál es el error en este razonamiento? las simulaciones no respaldan esto a pesar de que esperaba que fuera cierto. parece que debe haber algún error en mi razonamiento y/o simulación.
actualización 2: corrección en la simulación donde el parámetro de escala de la distribución exponencial disminuye con el tamaño de la población (inversamente proporcional a él) y el tamaño de población inicial es 10. aún subestima enormemente el crecimiento exponencial.
0 votos
¿Podrías publicar algunas fotos de tu resultado, junto con la curva de crecimiento propuesta?
0 votos
@AlexR. publicó un gráfico y código para la simulación
1 votos
Si entiendo el código correctamente, tiene al menos dos grandes problemas. El primero es el cálculo de la tasa: parece que multiplicas la tasa original por la población inicial, luego por la población inicial + 1, etc. Con una población inicial de $1$ y un valor inicial de $r$, esto te dará una tasa de $n!r$ en el paso $n$ en lugar de $nr$. La única razón por la que no obtienes una explosión ridícula en las poblaciones es que parece que utilizas la tasa como una escala, que es el recíproco de la tasa. En efecto, tu tasa realmente está disminuyendo rápidamente a cero, por lo que la población se estabiliza.
0 votos
En cuanto al algoritmo, no hay diferencia alguna entre ejecutarlo durante un tiempo especificado o hasta una población específica, siempre y cuando se ejecute lo suficiente tiempo. Aún así, sería más eficiente ejecutarlo hasta una población mucho mayor de lo esperado y cortar los valores que ocurran después de tu tiempo objetivo, en lugar de ejecutarlo solo hasta ese momento, porque el algoritmo se vuelve tan sencillo que se paraleliza de manera excelente (como se muestra en el código
R
que publiqué).0 votos
@whuber: arreglé la simulación para que ahora pase el parámetro exponencial como el inverso de la escala (es decir, 1/(tamaño de la población * tasa)). todavía subestima el crecimiento exponencial. Entiendo la versión paralela/vectorizada del código y por qué es mejor, pero no estoy interesado en la eficiencia, solo en entender el algoritmo y por qué mi versión simple falla.
0 votos
Describí dos en mi primer comentario. Parecen haber muchos más, pero este no es un sitio de revisión de código. Está claro que el modelo funciona, así que ahora se trata de depurar tu código. Me gustaría señalar que tu nuevo gráfico rojo claramente no es el correcto para un valor inicial de $1$ y una tasa de $1$: debería trazar $y=\exp(x)$ desde $x=0$ hasta $x=4$ y por lo tanto no superaría a $\exp(4)\approx 55$. Realmente no tengo idea de lo que estás graficando porque obviamente este gráfico no comienza con una población de $100$, a pesar de que eso es lo que
init=100
parecería significar.0 votos
Lo siento, mi gráfico era para
init=20
noinit=100
. La línea roja se traza usando base 2, no logaritmo natural. Con un tamaño de población inicial de 20, esperas que $20\times 2^{4*1} = 320$ al final, que es lo que obtengo. Pero ahora entiendo qué salió mal. Gracias.