Skip to content

CASES I: Population Models

CASE: Single-Species Population Growth


Simple Difference Equation (Unbounded):

Nt+1 = Nt ( 1 + r )


Simple Difference Equation (Unbounded, over time period):

Nt = N0 ( 1 + r )t


Differential Model (Differential Change):


Differential Model (Change over time period):

Nt = N0ert

Density-Dependent Population Growth (1 species)

Basic Model

Logistic Growth Model

  • dampening of growth rate, based on state wrt carrying capacity, K

Discrete


Continuous


Scaled Logistic Growth (Discrete)

# Preliminaries
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.integrate import solve_ivp

# Define logistic growth equation
def logistic_n(t, N0, r, K):
    dN_dt = r * N0 * (1 - N0 / K)
    return dN_dt

# Set initial conditions
N0 = [1000]

# Set parameter values
params = {'r': 0.5,
         'K': 10000}
t_span = (0, 100)
t_eval = np.arange(0, 100, 0.1)

# Run differential equation solver
Nt = solve_ivp(logistic_n, t_span, N0, args=tuple(params.values()), t_eval=t_eval)

#print(Nt)

# Plot the time series
sns.set()
plt.plot(Nt.t, Nt.y[0], color='blue')
plt.xlabel('Time (t)')
plt.ylabel('Population Size (N)')
plt.axhline(10000, color="red", linestyle="--", label="Carrying Capacity")
plt.legend()
plt.show()

Logistic Growth with Time Lag

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.integrate import odeint

# Define logistic growth with time delay
def logistic_delay(N, t, r, K, tau, N_tau):
    dN_dt = r * N * (1 - N_tau / K)
    return dN_dt

# Define history function (for t < 0)
def N_history(t):
    return 500  # Initial condition before t=0

# Solve the DDE using Euler's method for approximation
def solve_logistic_delay(r, K, tau, N0, t_max, dt):
    t_values = np.arange(0, t_max, dt)
    N_values = np.zeros_like(t_values)
    
    # Set initial condition
    N_values[0] = N0

    # Numerical approximation (Euler-like method)
    for i in range(1, len(t_values)):
        t = t_values[i]
        t_lag = t - tau

        # Approximate the delayed value by looking at previous steps
        if t_lag < 0:
            N_tau = N_history(t_lag)
        else:
            N_tau = N_values[int((t_lag) / dt)]  # Nearest previous point

        # Compute the next value using logistic equation with delay
        dN_dt = logistic_delay(N_values[i - 1], t, r, K, tau, N_tau)
        N_values[i] = N_values[i - 1] + dN_dt * dt

    return t_values, N_values

# Define parameters
r = 0.5
K = 10000
tau = 2
N0 = 1000
t_max = 100
dt = 0.1

# Solve the DDE
t, N = solve_logistic_delay(r, K, tau, N0, t_max, dt)

# Plot results
sns.set()
plt.plot(t, N, label=f'Logistic Growth with Time Lag (τ={tau})', color='blue')
plt.axhline(K, label="Carrying Capacity (K)", linestyle="--", color="red")
plt.xlabel('Time (t)')
plt.ylabel('Population Size (N)')
plt.legend(loc="upper right")
plt.title("Delayed Logistic Growth")
plt.show()

Logistic growth with time lag is characterized by two factors: (1) time lag, tau; and (2) "response time"

Logistic Growth with no time delay-like

0 < r < 0.368

Damped Delayed Logistic Growth

0.368 < r < 0.1.570

Delayed Logistic Growth with Stable Limit Cycle

r > 0.1.570

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
#from scipy.integrate import odeint

# Define logistic growth with time delay
def logistic_delay(N, t, r, K, tau, N_tau):
    dN_dt = r * N * (1 - N_tau / K)
    return dN_dt

# Define history function (for t < 0)
def N_history(t):
    return 500  # Initial condition before t=0

# Solve the DDE using Euler's method for approximation
def solve_logistic_delay(r, K, tau, N0, t_max, dt):
    t_values = np.arange(0, t_max, dt)
    N_values = np.zeros_like(t_values)
    
    # Set initial condition
    N_values[0] = N0

    # Numerical approximation (Euler-like method)
    for i in range(1, len(t_values)):
        t = t_values[i]
        t_lag = t - tau

        # Approximate the delayed value by looking at previous steps
        if t_lag < 0:
            N_tau = N_history(t_lag)
        else:
            N_tau = N_values[int((t_lag) / dt)]  # Nearest previous point

        # Compute the next value using logistic equation with delay
        dN_dt = logistic_delay(N_values[i - 1], t, r, K, tau, N_tau)
        N_values[i] = N_values[i - 1] + dN_dt * dt

    return t_values, N_values

# Define parameters
r = 0.5
K = 10000
tau_values = [0.1, 2, 3.5, 5]
N0 = 1000
t_max = 100
dt = 0.1

# Plot results
sns.set()
for tau in tau_values:
    t, N = solve_logistic_delay(r, K, tau, N0, t_max, dt)
    plt.plot(t, N, label=f'r=0.5, Time Lag (τ={tau})')
plt.axhline(K, label="Carrying Capacity (K)", linestyle="--", color="red")
plt.xlabel('Time (t)')
plt.ylabel('Population Size (N)')
plt.legend(loc="upper right")
plt.title("Delayed Logistic Growth")
plt.show()
Hidden code
Hidden code
Discrete Logistic Growth

Technically, a logistic growth with time lag = 1.

# Preliminaries
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.integrate import solve_ivp

# Define model
def discrete_logistic_n(N_t, r, K):
    N_t1 = N_t + r * N_t * (1 - (N_t/K))
    return N_t1

# Define initial conditions
N0 = 50
t_max = 18
K = 100
r_list = [1.9, 2.4, 2.5, 2.8]

# Set model parameters
dt = 1
t_span = (0, t_max)
t_eval = np.arange(0, t_max, dt)
N_t1 = np.zeros_like(t_eval)
N_t1[0] = N0

# Solve equation and plot
sns.set()
fig, ax = plt.subplots(nrows=4, ncols=1, figsize=(6, 12), sharex=True)

for index, value in enumerate(r_list):
    for t1 in range(1, len(t_eval)):
        N_t = N_t1[t1-1]
        N_t1[t1] = discrete_logistic_n(N_t, value, K)
    ax[index].plot(t_eval, N_t1, label = f"r = {value}")
    ax[index].axhline(K, label = "K", color="red", linestyle="--")
    ax[index].set_xlabel("Time (t)")
    ax[index].set_ylabel("Population size (N)")
    ax[index].set_ylim(0, 140)
    ax[index].set_xlim(0, 18)
    ax[index].legend(loc="upper left")

plt.tight_layout()
plt.show()