The marginal value theorem

ecology tutorial
R
foraging
behaviour
optimisation
The marginal value theorem in R: the optimal time to leave a patch, the tangent that solves it, and why a richer environment means leaving each patch sooner.
Author

Tidy Ecology

Published

2026-07-29

A hummingbird works a patch of flowers, or a bee a clump of clover, and the nectar it collects piles up fast at first and then slows as the patch empties. At some point it should give up this patch and fly to the next, spending time in transit that yields nothing. When should it leave? The marginal value theorem answers this, and its answer is one of the cleaner results in behavioural ecology (Charnov 1976 Theoretical Population Biology 9(2):129-136).

The problem

Two ingredients. Inside a patch, cumulative intake follows a gain curve g(t) that rises with diminishing returns. Between patches there is a travel time that returns nothing. A forager that keeps doing this collects, over the long run, a rate of

\[R(t) = \frac{g(t)}{t + \text{travel}},\]

intake per patch divided by the total time per patch, foraging plus travel. The forager should pick the residence time t that makes this long-run rate as large as possible.

Gmax <- 30; k <- 0.18
g  <- function(t) Gmax * (1 - exp(-k * t))    # patch gain curve, diminishing returns
gp <- function(t) Gmax * k * exp(-k * t)      # marginal gain (its slope)

The rule, and its picture

Maximising the long-run rate gives a strikingly simple condition: leave the patch when the marginal intake rate, the slope of the gain curve at that instant, has fallen to the long-run rate you could get by leaving now and starting fresh elsewhere.

\[g'(t^{*}) = \frac{g(t^{*})}{t^{*} + \text{travel}}.\]

Solve it with uniroot.

tstar <- function(travel) uniroot(function(t) gp(t) - g(t)/(t + travel), c(1e-6, 200))$root
sapply(c(2, 6, 12), tstar)          # optimal residence at three travel times
[1] 4.131653 6.569395 8.608910

Geometrically this is a tangent. Draw the gain curve, mark the travel time as a point on the negative time axis at (-travel, 0), and draw the steepest line from that point that touches the curve. It touches at the optimal departure time, and its slope is the best achievable long-run rate. The construction makes the answer visible.

tt <- seq(0, 30, 0.1)
gc <- data.frame(t = tt, g = g(tt))
tan_df <- do.call(rbind, lapply(c(6, 12), function(tr) {
  ts <- tstar(tr); data.frame(x = c(-tr, ts), y = c(0, g(ts)), travel = paste("travel", tr))
}))
pt_df <- data.frame(t = sapply(c(6, 12), tstar), g = g(sapply(c(6, 12), tstar)),
                    travel = paste("travel", c(6, 12)))
ggplot() +
  geom_vline(xintercept = 0, colour = col_ref, linewidth = 0.3) +
  geom_line(data = gc, aes(t, g), colour = col_gain, linewidth = 1) +
  geom_line(data = tan_df, aes(x, y, group = travel, colour = travel), linewidth = 0.8) +
  geom_point(data = pt_df, aes(t, g, colour = travel), size = 2.6) +
  scale_colour_manual(values = c("travel 6" = col_tan, "travel 12" = "#d8a56b")) +
  labs(x = "Time (travel shown negative)", y = "Cumulative intake", colour = NULL,
       title = "Leave where the tangent from the travel time touches the curve")
A patch gain curve with two tangent lines drawn from two travel times on the negative axis; the tangent from the longer travel time touches the curve further to the right.
Figure 1: The marginal value theorem as a tangent. From the travel time on the negative axis, the line touching the gain curve marks the optimal departure. A longer travel time (lighter) shifts the tangent point to the right: stay longer.

The counterintuitive part

Read the table of solutions and one number moves the wrong way for most people’s intuition.

data.frame(travel = c(2, 6, 12),
           residence = round(sapply(c(2, 6, 12), tstar), 2),
           long_run_rate = round(sapply(c(2, 6, 12), function(tr) { ts <- tstar(tr); g(ts)/(ts+tr) }), 3))
  travel residence long_run_rate
1      2      4.13         2.567
2      6      6.57         1.655
3     12      8.61         1.147

When travel time is short, 2, the forager should leave each patch after only 4.1 time units; when travel is long, 12, it should stay 8.6. A richer environment, one where patches are close together and travel is cheap, means leaving each patch sooner, not later. It feels backwards: surely a good environment lets you relax? But the logic is opportunity cost. When the next patch is a short hop away, the rate you forgo by lingering in a depleting patch is high, so you should cut and run early. When the next patch is far, there is little to rush to, so you stay and squeeze more from the one you are in.

There is a second way to say the same thing. At the optimal departure the marginal capture rate equals the habitat-wide average rate: here the forager leaves when the patch has dropped to a marginal rate of 1.655 at travel 6, exactly the long-run rate 1.655 it earns overall. Quit a patch the moment it falls to the average of the whole habitat.

tr <- seq(1, 20, 0.5)
dd <- data.frame(travel = tr,
                 residence = sapply(tr, tstar),
                 rate = sapply(tr, function(x) { ts <- tstar(x); g(ts)/(ts+x) }))
ggplot(dd, aes(travel)) +
  geom_line(aes(y = residence), colour = col_gain, linewidth = 1) +
  geom_line(aes(y = rate * 4), colour = col_tan, linewidth = 1) +
  scale_y_continuous(name = "Optimal residence time",
                     sec.axis = sec_axis(~ . / 4, name = "Long-run intake rate")) +
  labs(x = "Travel time between patches",
       title = "Longer travel: stay longer, earn less") +
  theme(axis.title.y.left = element_text(colour = col_gain),
        axis.title.y.right = element_text(colour = col_tan))
Two curves against travel time: optimal residence time rising, and long-run intake rate falling.
Figure 2: Optimal residence time (green) rises with travel time while the long-run intake rate (ochre) falls. Cheaper travel means shorter patch visits and a higher overall rate.

What the theorem assumes

The marginal value theorem is a prediction about an idealised forager: one that knows the shape of the gain curve, knows the average quality of its habitat, and is paid purely in intake rate. Real animals do not solve calculus at the flower. They use rules of thumb, leave when the capture rate drops below a threshold, or after a fixed unrewarded interval, and these approximate the theorem well without needing its knowledge. Whether an animal maximises rate at all, rather than efficiency or safety, is a separate question the checking post takes up. The theorem is a benchmark for how a rate-maximiser should behave, and departures from it are how you find out what the animal is really doing. The next post keeps the forager still and asks a different question: of the prey it meets, which ones are worth eating?

References

  • Charnov EL 1976. Theoretical Population Biology 9(2):129-136 (10.1016/0040-5809(76)90040-X).
  • MacArthur RH, Pianka ER 1966. The American Naturalist 100(916):603-609 (10.1086/282454).
  • Pyke GH 1984. Annual Review of Ecology and Systematics 15(1):523-575 (10.1146/annurev.es.15.110184.002515).

Newsletter

Get new tutorials by email

New R and QGIS tutorials for ecologists, straight to your inbox. No spam; unsubscribe anytime.

By subscribing you agree to receive these emails and confirm your address once. See the privacy policy.