Capstone Simulation
A complete predator–prey + parameter-sweep mini-project tying it all together
This capstone is a complete scientific computing project compressed into a single page. We will:
- Build a multi-file simulation of a Lotka–Volterra predator–prey ecosystem
- Solve the ODE with
solve_ivpand detect extinction events - Run a parameter sweep over predation rates
- Visualize with small multiples and a phase portrait
- Quantify uncertainty by repeating with multiple seeds
By the end you will have used every skill from the course in a single, coherent workflow.
The model
A classic Lotka–Volterra system with logistic prey growth:
- = prey population (e.g. rabbits)
- = predator population (e.g. foxes)
- = prey intrinsic growth rate
- = prey carrying capacity
- = attack rate (how often predators catch prey)
- = conversion efficiency
- = predator mortality
Pipeline overview
The simulation module
What this little project demonstrates:
- Modeling. Translating a biological story into a system of ODEs with parameters that have physical meaning.
- Stable numerical integration. Using
solve_ivpwithdense_outputandmax_stepto get smooth, controllable output. - Event detection. Catching the extinction moment exactly.
- Reproducible stochasticity. A per-run
default_rng(seed)so every replicate is exactly repeatable. - Parameter sweeps. A clean loop over a grid of attack rates and seeds.
- Aggregation. Grouping replicates and computing summary statistics.
- Visualization. Small multiples that let your eye compare parameter regimes at a glance.
A phase portrait
The classical way to look at a predator–prey system is in phase space — predator on one axis, prey on the other. Closed orbits mean sustained oscillations; spirals mean damped or growing oscillations; runaway escape means extinction.
Different starting populations spiral into the same equilibrium — a behavior driven entirely by the prey's logistic carrying capacity. Without that term the orbits would be perfect closed loops (the classic Lotka–Volterra cycle).
Quantifying sensitivity
A useful question: how sensitive is extinction probability to the attack rate ? A small Monte Carlo over many seeds gives us an answer with confidence bars.
The survival probability falls as predation intensifies, and binomial standard errors quantify how confident we are in each estimate. This is the output of a real computational science project: not just a number, but a number with an uncertainty.
What you just used
A non-exhaustive list of techniques from this course that appear in the capstone:
| Technique | Where |
|---|---|
| Vectorized NumPy | the entire RHS |
| Adaptive ODE integration | solve_ivp with RK45 |
| Event detection | extinction at |
| Reproducible randomness | default_rng(seed) per run |
| Multi-file project layout | simulate / aggregate / plot |
| Parameter sweep | nested loops over a and seed |
| Small-multiples visualization | plot.small_multiples |
| Monte Carlo uncertainty | survival probability ± SE |
| Phase-portrait analysis | predator–prey trajectories |
Scientific computing is rarely a single algorithm. It is a pipeline of choices, each grounded in numerical understanding, glued together by reproducible code.
Check your understanding
The capstone uses solve_ivp(..., events=extinct, dense_output=True, max_step=0.5). Why max_step=0.5 rather than letting the solver pick freely?
To slow down the simulation for visualization
An adaptive solver may take huge steps over slow dynamics and miss short-lived events; capping the step size forces the solver to evaluate the event function frequently enough to detect a fast extinction transient
It changes the order of the integrator
It enables GPU acceleration
Why does the capstone summary report both mean_peak_prey and p_extinction per parameter setting, rather than just the population trajectory of one representative run?
For aesthetic reasons
A single trajectory hides stochastic variability. Aggregated quantities (means and probabilities) over many seeds report a property of the parameter setting, not of one lucky draw — and they come with quantifiable uncertainty
It is required by the language
The CPU is faster that way