codexpast-exam-of-the-mathematics-course-of-the-university-of-cambridge2005iiipaper-65-predator-prey.py
past-exam-of-the-mathematics-course-of-the-university-of-cambridge/2005/iii/paper-65-predator-prey.py
"""Original phase portraits; Python 3.14, NumPy 2.3.5, Matplotlib 3.10.7.
Writes only paper-65-predator-prey.png to the caller's working directory.
Caller-supplied MPLCONFIGDIR is left unchanged.
"""
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
def main():
fig, axes = plt.subplots(1, 4, figsize=(12, 3.3), constrained_layout=True)
cases = [(1.2, .4, 'Extinction'), (.6, .6, 'Predator extinction'), (.4, .3, 'Coexistence')]
for ax, (a, b, title) in zip(axes[:3], cases):
xs = np.linspace(0, 1.05, 110); ys = np.linspace(0, 1.6, 110)
x, y = np.meshgrid(xs, ys)
u = x*((1-a-x)/a-y); v=y*(x/b-1)
ax.streamplot(xs, ys, u, v, density=.85, linewidth=.6, arrowsize=.8, color='#416c96')
ax.plot(xs, np.maximum((1-a-xs)/a, 0), ':', color='#be7832', lw=1)
ax.axvline(b, color='#be7832', ls=':', lw=1)
points=[(0,0,'O')]
if a<1: points.append((1-a,0,'E'))
if a+b<1: points.append((b,(1-a-b)/a,'P'))
for px,py,label in points:
ax.plot(px,py,'ko',ms=4,clip_on=False);ax.annotate(label,(px,py),xytext=(5,5),textcoords='offset points')
ax.set(xlim=(0,1.05),ylim=(0,1.6),xlabel='prey x',ylabel='predator y',title=f'{title}\na={a:g}, b={b:g}')
ax=axes[3];aa=np.linspace(.001,1.5,700);bb=np.linspace(.001,1,600);a,b=np.meshgrid(aa,bb)
regions=np.where(a>1,0,np.where(a+b>1,1,2));colors=['#cbd9e9','#ffe0b0','#b6e0c4']
ax.pcolormesh(aa,bb,regions,cmap=ListedColormap(colors),vmin=0,vmax=2,shading='nearest',rasterized=True)
ax.plot([1,1],[0,1],'k-',lw=1);ax.plot([0,1],[1,0],'k-',lw=1)
ax.text(1.18,.5,'O sink',ha='center');ax.text(.75,.72,'E sink',ha='center');ax.text(.28,.23,'P sink',ha='center')
ax.set(xlim=(0,1.5),ylim=(0,1),xlabel='a',ylabel='b',title='ODE parameter regions')
fig.savefig('paper-65-predator-prey.png',dpi=150,facecolor='white',transparent=False)
plt.close(fig)
if __name__=='__main__':main()