codexpast-exam-of-the-mathematics-course-of-the-university-of-cambridge2005iiipaper-38-competing-populations.py
past-exam-of-the-mathematics-course-of-the-university-of-cambridge/2005/iii/paper-38-competing-populations.py
"""Plot the symmetric competition model; write the PNG to the working directory."""
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
def main():
plt.rcParams.update({"font.size": 10, "axes.spines.top": False, "axes.spines.right": False})
fig, (time_ax, phase_ax) = plt.subplots(1, 2, figsize=(9, 4.2), layout="constrained")
times = np.linspace(0, 6, 401)
for rate, colour in [(0.5, "#2468ad"), (2.0, "#d06b23")]:
z = rate / (1 + (rate - 1) * np.exp(-rate * times))
time_ax.plot(times, z, color=colour, lw=2.2, label=rf"$\lambda={rate:g}$")
time_ax.axhline(rate, color=colour, lw=1, ls=":")
time_ax.set(xlabel="Time", ylabel=r"Equal populations $x=y=z$", title=r"Diagonal relaxation ($\mu=1$)", ylim=(0.35, 2.15))
time_ax.legend(frameon=False, loc="center right")
time_ax.grid(alpha=0.2)
grid = np.linspace(0.1, 1.9, 13)
x, y = np.meshgrid(grid, grid)
u, v = x * (1 - y), y * (1 - x)
norm = np.hypot(u, v)
good = norm > 1e-12
u = np.divide(u, norm, out=np.zeros_like(u), where=good)
v = np.divide(v, norm, out=np.zeros_like(v), where=good)
phase_ax.quiver(x, y, u, v, color="#91989f", angles="xy", scale_units="xy", scale=9, width=0.005)
phase_ax.plot([0, 2], [0, 2], color="#2468ad", lw=2, label="Invariant diagonal")
phase_ax.scatter([1], [1], s=45, c="#202830", zorder=4)
phase_ax.annotate("Coexistence saddle", (1, 1), xytext=(0.12, 1.7), arrowprops={"arrowstyle": "->", "color": "#202830"})
for start, end in [((1.05, 0.95), (1.48, 0.52)), ((0.95, 1.05), (0.52, 1.48))]:
phase_ax.annotate("", end, xytext=start, arrowprops={"arrowstyle": "->", "color": "#d06b23", "lw": 2})
phase_ax.set(xlabel=r"Population $x$", ylabel=r"Population $y$", title=r"Difference grows ($\lambda=\mu=1$)", xlim=(0, 2), ylim=(0, 2), aspect="equal")
phase_ax.legend(frameon=False, loc="lower left")
fig.savefig(Path.cwd() / "paper-38-competing-populations.png", dpi=120, facecolor="white")
plt.close(fig)
if __name__ == "__main__":
main()