Lab 2: Population Models — Answers
1) With dP/dt = r, integrating gives P(t) = rt + C. Using P(0) = 379 → C = 379. Using P(1) = 423 → r + 379 = 423
→ r = 44.
P(t) = 44t + 379
2) With dP/dt = rP, the solution is P(t) = P0·e^(rt). P(0) = 379 → P0 = 379. P(1) = 423 → 379e^r = 423 → r =
ln(423/379) ≈ 0.11.
P(t) = 379e^(0.11t)
3) Let u = 1/P, so du/dt = −(1/P²)(dP/dt) = −u²(dP/dt).
Substituting dP/dt = rP(1 − P/K) = r(1/u)(1 − 1/(Ku)):
du/dt = −u²·r(1/u)(1 − 1/(Ku)) = −ru(1 − 1/(Ku)) =
−ru + r/K
This is linear in u (first-order linear ODE). Solving with integrating factor e^(rt):
u(t) = 1/K + (1/P0 − 1/K)e^(−rt)
Taking the reciprocal and simplifying (multiply through by K·P0):
P(t) = K·P0 / [P0 + (K − P0)e^(−rt)]
4) Sample code:
import numpy as np
import matplotlib.pyplot as plt
t_data = np.arange(0, 21)
P_data = [379,423,472,523,610,738,995,1231,1457,1783,
2239,2805,3366,3852,4250,4317,4691,5149,5689,5737,6016]
def P_linear(t):
return 44*t + 379
def P_exponential(t):
return 379*np.exp(0.11*t)
t_smooth = np.linspace(0, 20, 300)
plt.scatter(t_data, P_data, label="Data", color="black")
plt.plot(t_smooth, P_linear(t_smooth), label="Linear")
plt.plot(t_smooth, P_exponential(t_smooth), label="Exponential")
plt.xlabel("Decades since 1790")
plt.ylabel("Population")
plt.legend()
plt.show()
5)
def compute_r(P0, P1, P2, h):
return (1/h) * np.log((P2*(P1-P0)) / (P0*(P2-P1)))
def compute_K(P0, P1, P2, h, r):
return (P0*P1*(1 - np.exp(-r*h))) / (P0 - P1*np.exp(-r*h))
6) Using the three equally spaced points at each h (t = 0, h, 2h):
• h = 1 (P0=379, P1=423, P2=472): r ≈ 0.112, K ≈ 22,700 — technically valid, but K is enormous because the first
three points are still deep in the early exponential-looking regime, giving almost no curvature to estimate K from.
The resulting curve underestimates the population badly later on.
• h = 5 (P0=379, P1=738, P2=2239): r ≈ 0.069, K comes out negative (≈ −570). This is the "completely
unreasonable" curve — with negative K the formula predicts negative populations and/or a vertical asymptote
(blow-up), so the curve looks nothing like real growth.
• h = 10 (P0=379, P1=2239, P2=6016): r ≈ 0.206, K ≈ 7,990 — a sensible, S-shaped curve that tracks the data well,
including the leveling-off in the late 1900s.
Cause of the unreasonable curve: for h = 5, the denominator in the K formula, P0 − P1e^(−rh), comes out negative
(P1e^(−rh) slightly exceeds P0), which flips the sign of K. This happens because the three chosen points don't yet
show the population "bending over," so the algebra used to back out K is extremely sensitive to noise/spacing and
can produce a nonphysical (negative) carrying capacity.
Best fit of the two reasonable curves: h = 10 fits the data noticeably better than h = 1, because it uses points spread
across the entire dataset — including the years where the population visibly levels off — giving a much more
accurate estimate of the true carrying capacity.
7) r is the intrinsic (per-capita) growth rate — the rate at which the population would grow if it were small and
unconstrained by resources.
K is the carrying capacity — the equilibrium population size the model predicts the population will approach as t →
∞ (dP/dt → 0 when P = K).
Setting P = K/2:
dP/dt = rP(1 − P/K) = r(K/2)(1 − 1/2) =
rK/4
Since dP/dt = rP(1−P/K) is a downward-opening parabola in P, its maximum occurs exactly at P = K/2, with
maximum value rK/4. This means the population is growing fastest when it's at half the carrying capacity. On the
logistic curve, this is the inflection point — the curve is concave up (accelerating growth) before P = K/2 and
concave down (decelerating growth, leveling toward K) after it — which is what produces the characteristic Sshape.