Learning Objectives
By the end of this section you will be able to:
- Derive the Lotka–Volterra competition model by adding inter-specific terms to two coupled logistic equations and explain why every coefficient appears where it does.
- Sketch the two nullclines and directly from their intercepts.
- List the four equilibria and the coexistence point, and find each by inspection.
- Compute the Jacobian at any equilibrium and classify it from the signs of the eigenvalues.
- Predict which of four regimes will play out (1 wins, 2 wins, coexistence, bistability) from the two comparisons and .
- Implement the model with an RK4 integrator in plain Python and again as a batched
nn.Modulein PyTorch.
The Question Behind the Math
"Two species share one bowl of food. Can they share — or does one drive the other out?"
Predator–prey models in the previous section described one species eating another. The dynamic was inherently asymmetric. Here we tackle the more common situation in ecology: two species who do not eat each other but who both want the same things — nutrients, sunlight, shelter, nesting sites. Their interaction is symmetric in flavour but its long-time outcome can be wildly different, and the difference is entirely captured by two numbers we will call competition coefficients.
The question that organises everything below is: given the growth rates, the carrying capacities, and the strengths of competition, who survives? The answer turns out to be a clean four-way classification you can read off a single picture — and the picture is two intersecting straight lines in the plane.
From Logistic Growth to Competition
For a single species the logistic equation says
Read this in two steps. The factor is the unrestrained exponential growth rate. The factor in parentheses is a brake: when the population equals the carrying capacity , the bracket is zero and growth stops. Halfway to the brake is at 50%, and at the brake is — the population is overshooting and actually shrinking.
Now put a second species in the same bowl. The cleanest possible modification is: let species 2 count too, but in species-1 units. One individual of species 2 occupies as much of the niche as individuals of species 1. So replace in the brake by . Do the symmetric thing for species 2 — replace its by . That is the entire derivation.
The Competition Model
The full system is
Six parameters, two state variables. Every term has a direct ecological meaning:
| Symbol | Meaning | Units |
|---|---|---|
| r₁, r₂ | Intrinsic per-capita growth rate of each species when alone and rare | 1/time |
| K₁, K₂ | Carrying capacity if the other species is absent (the solo logistic asymptote) | individuals |
| α₁₂ | Per-capita effect of species 2 on species 1 (in units of species 1) | dimensionless |
| α₂₁ | Per-capita effect of species 1 on species 2 (in units of species 2) | dimensionless |
| N₁, N₂ | Population sizes at time t | individuals |
Notice that putting gives back two decoupled logistic equations — the species ignore each other and grow toward their own carrying capacities. The full model only differs from this trivial limit through the two cross-terms and . All of the rich behaviour below lives inside those two terms.
Nullclines: Where Each Species Stops Changing
The geometric backbone of any 2D ODE system is its nullclines: the curves on which one of the rates vanishes. Set :
A product is zero iff a factor is zero, so either (the vertical axis) or the bracket is zero. The bracket gives a straight line:
It crosses the -axis at (set ) and the -axis at (set ). Identically for species 2:
with intercepts and .
The geometric punchline
On its own nullcline, a species is momentarily frozen: its rate is exactly zero. Above it the bracket is negative and the species shrinks; below it the bracket is positive and the species grows. Combined, the two nullclines partition the positive quadrant into 3 or 4 regions, and the SIGN of in each region is enough to predict the long-time outcome.
The Four Equilibria
An equilibrium is a point where both rates are zero simultaneously — geometrically, an intersection of an -nullcline with an -nullcline.
- — both extinct. The axes and intersect at the origin. Both rates vanish there.
- — only species 1. The species-1 sloped nullcline meets the axis. Species 1 is at its solo carrying capacity.
- — only species 2. Symmetric.
- — coexistence. The two sloped nullclines meet (if they meet inside the positive quadrant) at
The coexistence formulas come from solving the two linear nullcline equations and — straight Cramer's rule. The denominator appearing in both expressions is exactly the determinant of the 2×2 coefficient matrix. When that determinant is zero the lines are parallel and coexistence either doesn't exist or fills a whole line — a degenerate case.
Stability via the Jacobian
Near any equilibrium we linearise. Write and similarly . The Jacobian is
At each equilibrium plug in and read off the eigenvalues from the trace and determinant. Their signs determine the type:
| Eigenvalues | Type | Long-time behaviour near the point |
|---|---|---|
| Both negative | Stable node | All nearby trajectories converge to the point |
| Both positive | Unstable node | All nearby trajectories run away |
| Opposite signs | Saddle | Most trajectories run away; one special direction comes in |
| Complex with Re<0 | Stable spiral | Trajectories spiral inward (rare in pure competition) |
The Four Regimes — Geometry Predicts the Future
Compare with , and with . These two comparisons encode which nullcline lies above which on each axis, and they yield exactly four cases.
| Case | Conditions | Stable equilibrium | Ecology |
|---|---|---|---|
| 1. Species 1 wins | K₁ > α₁₂ K₂ and K₂ < α₂₁ K₁ | (K₁, 0) | Competitive exclusion — species 2 driven extinct |
| 2. Species 2 wins | K₁ < α₁₂ K₂ and K₂ > α₂₁ K₁ | (0, K₂) | Symmetric — species 1 driven extinct |
| 3. Stable coexistence | K₁ > α₁₂ K₂ and K₂ > α₂₁ K₁ | (N₁*, N₂*) | Weak inter-specific competition. Both survive forever |
| 4. Founder control | K₁ < α₁₂ K₂ and K₂ < α₂₁ K₁ | (K₁, 0) or (0, K₂) | Strong competition both ways — initial conditions decide who wins |
The intuition behind the conditions: the inequality says that, even when species 2 is at its solo carrying capacity, the brake on species 1 is still less than 100%, so species 1 can invade. If both invasion criteria hold, both species can come back from rare, and the only place they can co-rest is .
Case 4 is the most counter-intuitive: both single-species equilibria are stable. Whichever species starts higher pushes the other below its invasion threshold and wins. The coexistence point still exists but is a saddle; its stable manifold is the boundary between the two basins of attraction.
Interactive Phase-Plane Explorer
Below is the phase plane with vector field, nullclines, and equilibria for any parameter setting you choose. Use the four presets to flip between the four regimes; drag the sliders to deform the picture; and click anywhere in the field to drop a new trajectory. Notice how the same geometric ingredients (two lines + four dots) tell the whole story.
Take three minutes to play. The single most useful experiment is to load Founder control, drop a trajectory at , then drop another at . The two trajectories live on opposite sides of an invisible line — the stable manifold of the saddle — and end up at different attractors.
Worked Example (Step-by-Step)
Take the canonical "stable coexistence" setting and grind through every step by hand.
Click to expand the full hand calculation
Step 1. Parameters
. Time is measured in whatever units make ; populations in head count.
Step 2. Which regime?
Check the two comparisons:
- vs : , so species 1 CAN invade when species 2 sits at .
- vs : , so species 2 can also invade when species 1 sits at .
Both invasion criteria hold ⇒ regime 3, stable coexistence.
Step 3. Locate the coexistence equilibrium
Apply the formula directly. The shared denominator is
Then
Step 4. Jacobian at
Plug into the Jacobian. With :
- .
- .
- .
- .
Step 5. Eigenvalues
Trace and determinant first:
- .
- .
Discriminant , so , and
Both eigenvalues are real and negative ⇒ stable node. Every trajectory that starts in the positive quadrant gets pulled into .
Step 6. Sanity check at the other equilibria
At the Jacobian is upper-triangular: and . One negative, one positive ⇒ saddle, as predicted by the regime table.
At the Jacobian is lower-triangular: and . Another saddle.
At both diagonal entries are ⇒ unstable node.
Step 7. Picture
Three saddles/unstable points plus one stable node fully constrain the flow. Trajectories from anywhere in the positive quadrant curve into . The geometry has just told us the future without us solving a single transcendental.
Time-Series Companion
The phase plane shows where the system goes. The time-series view shows how fast. Slide the initial populations and watch (cyan) and (rose) both bend toward the coexistence levels . The dashed horizontal lines mark the solo carrying capacities — note that both species equilibrate below their solo , because each is making room for the other.
Plain Python Implementation
The cleanest way to internalise the model is to integrate it yourself. Below is a complete plain-Python program that reproduces the coexistence run with classical RK4. Every name in the code maps one-to-one onto the equations above.
Run it and you should see all three trajectories — starting from very different corners — print the same final state . That is the computational confirmation of the geometric prediction.
Same Model in PyTorch
Once you have it in plain Python, it is one short hop to PyTorch: wrap the parameters as nn.Parameters and broadcast the right-hand side over a batch dimension. The payoff is parallel integration of many initial conditions on GPU and automatic differentiation through every coefficient — so you can fit the model to data with torch.optim.Adam instead of by hand.
The Competitive Exclusion Principle
Cases 1, 2 and 4 all end with at least one extinction. That is not an accident of the model — it is the mathematical face of a famous ecological idea due to G. F. Gause (1934): two species competing for exactly the same single resource cannot coexist indefinitely. In the limit and (the two species are functionally identical), the coexistence point either disappears or lies on a line of degenerate equilibria — exact coexistence is not robust to any perturbation.
Stable coexistence (regime 3) only exists when the two species specialise: each must compete more strongly with itself than with the other. Mathematically, that is and simultaneously. In ecology this is called niche partitioning, and it is why finches on different Galápagos islands evolved different beak shapes.
Common Pitfalls
- Index direction. is the effect OF species 2 ON species 1, not the other way round. The first index is the sufferer. Plug-and-chug errors here flip the whole prediction.
- Confusing carrying capacity with coexistence. is the carrying capacity of species 1 when alone; is its coexistence population. They are different and both can be below at the same time.
- Picking the wrong rk step size. With the characteristic time scale is ~1, so is fine. If you scale up by 100 you must scale down by the same factor or RK4 will diverge.
- Forgetting the positivity constraint. The model itself preserves exactly (each rate is proportional to ), but numerical drift can push trajectories slightly negative. Either clip or use an adaptive solver.
- Reading the saddle in case 4 as a coexistence equilibrium. The coordinates of are real and positive in case 4, but the equilibrium is unstable — almost every trajectory leaves it. Always classify before celebrating.
Summary
Two coupled logistic equations with cross-competition coefficients already produce a rich four-way ecology. The geometry is two straight nullclines whose relative positions are decided by two simple comparisons — and those two comparisons completely determine which of four futures the system will live: species 1 wins, species 2 wins, both coexist, or the winner is whoever happens to start ahead. The Jacobian gives a rigorous stability classification at every equilibrium, plain Python integrates the model in 20 lines, and PyTorch lets you scale it to batched and fitted versions without rewriting a single equation.
Next we will close out the chapter with the most famous nonlinear system of all — Lorenz's three-equation atmosphere model — where three coupled ODEs produce something that never settles to an equilibrium and yet is bounded forever: deterministic chaos.