Skip to content

Commit da50ea1

Browse files
jstacclaude
andcommitted
Use default color cycle for data series; minor prose/tense fixes
Per QuantEcon convention, let matplotlib pick data-series colors (C0/C1 standard pair) instead of hard-coding C0/C3; reserve explicit color for reference elements only (black 45-degree line/cobweb/markers/guides, grey milestone lines). Markers now follow their line via get_color(). Lingcod overfishing band switched from red to neutral grey. Also fold in the user's prose edits (overview rewording, G(x) definition, hide-input on plot_45, simplified update equation, tightened lingcod narrative) and fix a past/present tense slip in that narrative. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent ab22a82 commit da50ea1

1 file changed

Lines changed: 61 additions & 70 deletions

File tree

lectures/msy_fishery.md

Lines changed: 61 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ imposed quotas and restrictions based on MSY.
2424

2525
In some cases these management efforts were successful.
2626

27-
However, this hasn't always been the case.
27+
In other cases outcomes were disappointing.
2828

29-
For example, several major fisheries collapsed under MSY-based management,
29+
In fact, several major fisheries collapsed under MSY-based management,
3030
including the Peruvian anchovy in the 1970s and the Atlantic cod off
3131
Newfoundland in 1992.
3232

33-
In this lecture our main task is to explain how MSY is computed.
33+
In this lecture we provide an introduction to MSY-based management of fisheries.
34+
35+
Our main task is to explain how MSY is computed.
3436

3537
We begin with a relatively elementary treatment in discrete time.
3638

@@ -77,7 +79,8 @@ $$ (eq:logistic)
7779
7880
Here
7981
80-
* $x$ is the **stock biomass** --- the total weight of fish in tonnes,
82+
* $x$ is the **current biomass** --- the total weight of fish in tonnes,
83+
* $G(x)$ is **annual growth** in biomass --- the difference between current and next year's biomass,
8184
* $r > 0$ is called the **intrinsic growth rate**, and
8285
* $K > 0$ is called the **carrying capacity**.
8386
@@ -103,7 +106,7 @@ mystnb:
103106
x_grid = np.linspace(0, K, 400)
104107
105108
fig, ax = plt.subplots()
106-
ax.plot(x_grid, G(x_grid), lw=2, color='C0')
109+
ax.plot(x_grid, G(x_grid), lw=2)
107110
ax.set_xlabel('stock biomass $x$')
108111
ax.set_ylabel('annual growth $G(x)$')
109112
ax.set_xlim(0, K)
@@ -121,30 +124,34 @@ $$
121124
One way to see where the dynamics lead is via a 45-degree diagram, which plots
122125
next year's stock $x_{t+1}$ against this year's stock $x_t$.
123126
124-
Wherever the curve crosses the $45^\circ$ line we have $x_{t+1} = x_t$ --- a
125-
**steady state**, a stock that exactly reproduces itself.
127+
Wherever the curve crosses the $45^\circ$ line we have $x_{t+1} = x_t$.
128+
129+
The corresponding value of $x$ obeys $x = x + G(x)$.
130+
131+
Such an $x$ is called a **steady state**: a stock that exactly reproduces itself.
126132
127-
We can then trace the dynamics by "staircasing": from a starting stock go *up* to
133+
We can trace the dynamics of the model by "staircasing": from a starting stock go *up* to
128134
the curve (that gives next year's stock), *across* to the $45^\circ$ line (that
129135
becomes this year's stock), and repeat.
130136
131-
The next function draws such a diagram.
132-
133-
It takes the one-year update rule as a function argument `update_fn`, since at
134-
this point we have not yet introduced fishing.
137+
We start with some plotting code.
135138
136139
```{code-cell} ipython3
137-
def plot_45(ax, update_fn, x0, x_max, steady_state, ss_label, map_label, n_years=30):
138-
"Draw a 45-degree (cobweb) diagram for a one-year stock update rule."
140+
:tags: [hide-input]
141+
142+
def plot_45(
143+
ax, f, x0, x_max, steady_state, ss_label, map_label, n_years=30
144+
):
145+
"Draw a 45-degree (cobweb) diagram for a function f."
139146
grid = np.linspace(0, x_max, 400)
140-
ax.plot(grid, update_fn(grid), color='C0', lw=2, label=map_label)
147+
ax.plot(grid, f(grid), lw=2, label=map_label)
141148
ax.plot(grid, grid, color='0.6', lw=1, ls='--',
142149
label=r'$45^\circ$ line')
143150
# cobweb staircase starting from x0
144151
x = x0
145152
cx, cy = [x], [0.0]
146153
for _ in range(n_years):
147-
y = update_fn(x)
154+
y = f(x)
148155
cx += [x, y]
149156
cy += [y, y]
150157
x = y
@@ -189,7 +196,7 @@ stock grows away from it.)
189196
190197
### Adding fishing
191198
192-
Now let a fishing fleet remove a catch each year.
199+
Now let a fishing fleet remove some catch quantity $h_t$ each year.
193200
194201
Following {cite:t}`schaefer1954`, the catch is proportional to fishing **effort**
195202
$e$ (e.g. boat-days) and to the stock available to be caught:
@@ -203,10 +210,7 @@ Here $q > 0$ is the **catchability coefficient**.
203210
Subtracting the catch, next year's stock becomes
204211
205212
$$
206-
x_{t+1}
207-
\;=\; x_t
208-
\;+\; \underbrace{r\,x_t\!\left(1-\frac{x_t}{K}\right)}_{\text{growth}}
209-
\;-\; \underbrace{qe\,x_t}_{\text{catch}}.
213+
x_{t+1} = x_t + G(x_t) - qe\,x_t.
210214
$$ (eq:update)
211215
212216
@@ -259,10 +263,10 @@ grid = np.linspace(0, 1100, 400)
259263
260264
fig, ax = plt.subplots(figsize=(4.95, 4.95))
261265
ax.plot(grid, grid, color='0.6', lw=1, ls='--', label=r'$45^\circ$ line')
262-
for e, c in zip((10.0, 30.0), ('C0', 'C3')):
263-
ax.plot(grid, update(grid, e), lw=2, color=c, label=f'$e={e:.0f}$')
266+
for e in (10.0, 30.0):
267+
line, = ax.plot(grid, update(grid, e), lw=2, label=f'$e={e:.0f}$')
264268
xs = x_star(e)
265-
ax.plot([xs], [xs], 'o', color=c, ms=8, zorder=5)
269+
ax.plot([xs], [xs], 'o', color=line.get_color(), ms=8, zorder=5)
266270
267271
ax.set_xlabel('stock this year $x_t$')
268272
ax.set_ylabel('stock next year $x_{t+1}$')
@@ -330,8 +334,8 @@ mystnb:
330334
x = np.linspace(0, K, 400)
331335
332336
fig, ax = plt.subplots()
333-
ax.plot(x, G(x), lw=2, color='C0', label=r'growth $G(x)$')
334-
ax.plot(x, q * e_demo * x, lw=2, color='C3', label=r'harvest $q e x$')
337+
ax.plot(x, G(x), lw=2, label=r'growth $G(x)$')
338+
ax.plot(x, q * e_demo * x, lw=2, label=r'harvest $q e x$')
335339
336340
xs = x_star(e_demo)
337341
ys = sustainable_yield(e_demo)
@@ -363,15 +367,14 @@ mystnb:
363367
name: fig:steady-states
364368
---
365369
fig, ax = plt.subplots()
366-
ax.plot(x, G(x), lw=2, color='C0', label='growth $G(x)$')
370+
ax.plot(x, G(x), lw=2, label='growth $G(x)$')
367371
368372
efforts = [12.5, 25.0, 37.5]
369373
labels = [r'low $e$', r'moderate $e$', r'high $e$']
370-
colors = ['C2', 'C3', 'C1']
371374
372-
for e, lab, c in zip(efforts, labels, colors):
373-
ax.plot(x, q * e * x, lw=2, color=c, label=lab)
374-
ax.plot([x_star(e)], [q * e * x_star(e)], 'o', color=c, ms=7, zorder=5)
375+
for e, lab in zip(efforts, labels):
376+
line, = ax.plot(x, q * e * x, lw=2, label=lab)
377+
ax.plot([x_star(e)], [q * e * x_star(e)], 'o', color=line.get_color(), ms=7, zorder=5)
375378
376379
ax.set_xlabel('stock $x$')
377380
ax.set_ylabel('catch')
@@ -406,7 +409,7 @@ e_grid = np.linspace(0, r / q, 400)
406409
y_grid = sustainable_yield(e_grid)
407410
408411
fig, ax = plt.subplots()
409-
ax.plot(e_grid, y_grid, lw=2, color='C0', label=r'$y^*(e)=qeK\,(1-qe/r)$')
412+
ax.plot(e_grid, y_grid, lw=2, label=r'$y^*(e)=qeK\,(1-qe/r)$')
410413
ax.set_xlabel('fishing effort $e$')
411414
ax.set_ylabel('sustainable yield $y^*(e)$')
412415
ax.set_xlim(0, r / q)
@@ -564,10 +567,12 @@ Before turning to the risks, it is worth seeing the MSY framework succeed.
564567
A clean example is the lingcod (*Ophiodon elongatus*) fishery off the U.S.
565568
Pacific Coast.
566569
567-
Lingcod is managed using MSY-based reference points: a target biomass and a
568-
target fishing pressure that together define the maximum sustainable yield.
570+
Lingcod is managed using MSY-based analysis.
569571
570-
To follow the fishery we use two dimensionless ratios.
572+
This analysis leads to a target biomass and a target fishing pressure that
573+
together define the maximum sustainable yield.
574+
575+
To follow the fishery we use two ratios.
571576
572577
The first is $B / B_{MSY}$, the stock biomass relative to the biomass $B_{MSY}$
573578
that supports the MSY.
@@ -579,9 +584,6 @@ $F_{MSY}$ that achieves the MSY.
579584
580585
(In our model this is the MSY effort $e_{MSY}$.)
581586
582-
Each ratio is measured against its own MSY reference point, so the value $1$ is
583-
simultaneously the target and the limit.
584-
585587
The data come from the RAM Legacy Stock Assessment Database {cite:t}`ricard2012`.
586588
587589
```{code-cell} ipython3
@@ -603,71 +605,60 @@ ymax = max(lingcod['B_over_Bmsy'].max(), lingcod['F_over_Fmsy'].max()) * 1.06
603605
# shade the years when fishing pressure exceeded the MSY level
604606
over = lingcod['F_over_Fmsy'] > 1
605607
ax.fill_between(lingcod['year'], 0, ymax, where=over,
606-
color='C3', alpha=0.08)
608+
color='0.5', alpha=0.12)
607609
608-
ax.plot(lingcod['year'], lingcod['B_over_Bmsy'], color='C0', lw=2,
610+
ax.plot(lingcod['year'], lingcod['B_over_Bmsy'], lw=2,
609611
label=r'$B / B_{MSY}$ (biomass)')
610-
ax.plot(lingcod['year'], lingcod['F_over_Fmsy'], color='C3', lw=2,
612+
ax.plot(lingcod['year'], lingcod['F_over_Fmsy'], lw=2,
611613
label=r'$F / F_{MSY}$ (fishing pressure)')
612614
613615
ax.axvline(1999, color='grey', lw=0.8, ls=':')
614616
ax.axvline(2005, color='grey', lw=0.8, ls=':')
615-
ax.text(2000, ymax * 0.97, 'overfished (1999)', ha='left', va='top',
616-
fontsize=8.5, color='dimgrey')
617-
ax.text(2000, ymax * 0.88, 'rebuilt (2005)', ha='left', va='top',
618-
fontsize=8.5, color='dimgrey')
619617
620618
ax.set_xlabel('year')
621619
ax.set_ylabel('ratio to MSY reference point')
622620
ax.set_xlim(lingcod['year'].min(), lingcod['year'].max())
623621
ax.set_ylim(0, ymax)
624-
ax.legend(loc='upper center', frameon=False)
622+
ax.legend(loc='upper left', frameon=False)
625623
plt.tight_layout()
626624
plt.show()
627625
```
628626
629-
The story unfolds in three acts.
630627
631-
Through the 1960s the stock is lightly exploited: $F$ sits well below $F_{MSY}$
632-
and biomass drifts down slowly from a high level.
628+
Through the 1960s the stock was lightly exploited: $F$ sat well below $F_{MSY}$
629+
and biomass drifted down slowly from a high level.
633630
634-
From the early 1970s fishing pressure climbs above $F_{MSY}$ and stays there for
631+
From the early 1970s fishing pressure climbed above $F_{MSY}$ and stayed there for
635632
nearly three decades.
636633
637-
Biomass falls steadily, reaching a trough of about $0.27\,B_{MSY}$ in 1993 ---
634+
Biomass fell steadily, reaching a trough of about $0.27\,B_{MSY}$ in 1993 ---
638635
close to collapse.
639636
640-
In 1999 the stock was formally declared *overfished*, and a rebuilding plan cut
641-
catches sharply.
637+
In 1999 the stock was formally declared *overfished*, and a rebuilding plan
638+
based around MSY cut catches sharply.
642639
643640
Fishing pressure dropped well below $F_{MSY}$, and biomass climbed back through
644641
$B_{MSY}$ by 2004.
645642
646-
The stock was declared fully *rebuilt* in 2005, ahead of schedule, and then
643+
The stock was declared fully rebuilt in 2005, ahead of schedule, and then
647644
overshot its target.
648645
649-
This is exactly the negative feedback built into the model.
650-
651-
Push fishing above the MSY level and the stock falls; pull it below and the
652-
stock recovers toward $B_{MSY}$.
646+
As suggested by the model, fishing above the MSY level has led to falling stock, while
647+
keeping it below has led to recovery.
653648
654-
Used as a steering target, the MSY reference point did its job.
655649
656-
A few caveats keep the story honest --- and set up the next section.
650+
Of course, the real world is not as clean as the model and random factors
651+
also influenced outcomes.
657652
658-
First, attribution is never clean: a strong 1999 year-class also helped, so the
659-
cut in fishing was necessary but recruitment luck set the speed of recovery.
653+
For example, a strong 1999 year-class also helped, so the
654+
cut in fishing was important but recruitment luck set the speed of recovery.
660655
661-
Second, $B_{MSY}$ and $F_{MSY}$ are *estimated* quantities, revised at each
662-
assessment; the famous MSY failures are often failures of estimating the
663-
reference point rather than of the control rule itself.
656+
In addition, the recovery was aided by coast-wide measures aimed at the whole
657+
groundfish community.
664658
665-
Third, the recovery rode partly on coast-wide measures aimed at the whole
666-
groundfish community, a reminder that single-species MSY targets sit inside a
667-
multispecies system.
659+
The next section expands our model somewhat, with the aim of introducing more
660+
realistic dynamics.
668661
669-
The next section takes these caveats seriously, and asks what randomness does to
670-
MSY-based management.
671662
672663
## Randomness, risk and collapse
673664

0 commit comments

Comments
 (0)