FA-65556 / Ecological population dynamics / Open access
Schaefer surplus-production harvest reference points: effort at MSY · case 01
Effort reference points ignore gear catchability.
ROOT CAUSE
E_msy omits the catchability coefficient.
VERIFIED REPAIR
Restore the effort at MSY rule: `emsy = r / (2 * q)`.
Unsuccessful approach: Using 4q halves the effort that achieves MSY.
Case contract
MSY = rK/4 at B=K/2 and E_msy = r/(2q); equilibrium biomass under effort E is K(1-qE/r) when qE<r else 0; yield = qEB; status 'overfished' when E>E_msy, 'at-msy' when equal, else 'sustainable'; return [MSY, Bmsy, Emsy, B, yield, status] rounded; None for invalid inputs.
Why this case matters
Population projections set harvest quotas, conservation status and pest-control timing; a wrong update order, boundary or rate conversion silently changes management advice.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(r, k, effort, q):
if r <= 0 or k <= 0 or q <= 0 or effort < 0:
return None
msy = r * k / 4
bmsy = k / 2
emsy = r / 2
b = k * (1 - q * effort / r) if q * effort < r else 0.0
y = q * effort * b
if effort > emsy:
status = 'overfished'
elif effort == emsy:
status = 'at-msy'
else:
status = 'sustainable'
return [round(msy, 4), round(bmsy, 4), round(emsy, 6), round(b, 4), round(y, 4), status]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: tuna fishery moderate effort',
(0.4, 10000, 100, 0.001),
[1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable']),
('regression: effort at msy', (0.5, 2000, 250, 0.001), [250.0, 1000.0, 250.0, 1000.0, 250.0, 'at-msy']),
('regression: overfished',
(0.3, 5000, 250, 0.001),
[375.0, 2500.0, 150.0, 833.3333, 208.3333, 'overfished']),
('regression: collapse effort', (0.2, 3000, 300, 0.001), [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished']),
('regression: no fishing', (0.6, 800, 0, 0.002), [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable']),
('regression: high catchability', (0.8, 1500, 50, 0.01), [300.0, 750.0, 40.0, 562.5, 281.25, 'overfished']),
('control: invalid q', (0.5, 2000, 100, 0.0), None)],
[('regression: tuna fishery moderate effort',
(0.4, 10000, 100, 0.001),
[1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable']),
('regression: collapse effort', (0.2, 3000, 300, 0.001), [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished']),
('regression: no fishing', (0.6, 800, 0, 0.002), [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable']),
('regression: high catchability', (0.8, 1500, 50, 0.01), [300.0, 750.0, 40.0, 562.5, 281.25, 'overfished']),
('regression: slightly over msy',
(0.5, 2000, 250.4, 0.001),
[250.0, 1000.0, 250.0, 998.4, 249.9994, 'overfished']),
('control: invalid q', (0.5, 2000, 100, 0.0), None),
('regression: light fishing',
(1.2, 400, 20, 0.005),
[120.0, 200.0, 120.0, 366.6667, 36.6667, 'sustainable'])],
[('regression: tuna fishery moderate effort',
(0.4, 10000, 100, 0.001),
[1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable']),
('regression: effort at msy', (0.5, 2000, 250, 0.001), [250.0, 1000.0, 250.0, 1000.0, 250.0, 'at-msy']),
('regression: overfished',
(0.3, 5000, 250, 0.001),
[375.0, 2500.0, 150.0, 833.3333, 208.3333, 'overfished']),
('regression: collapse effort', (0.2, 3000, 300, 0.001), [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished']),
('regression: slightly over msy',
(0.5, 2000, 250.4, 0.001),
[250.0, 1000.0, 250.0, 998.4, 249.9994, 'overfished']),
('control: invalid q', (0.5, 2000, 100, 0.0), None),
('regression: light fishing',
(1.2, 400, 20, 0.005),
[120.0, 200.0, 120.0, 366.6667, 36.6667, 'sustainable'])],
[('regression: tuna fishery moderate effort',
(0.4, 10000, 100, 0.001),
[1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable']),
('regression: effort at msy', (0.5, 2000, 250, 0.001), [250.0, 1000.0, 250.0, 1000.0, 250.0, 'at-msy']),
('regression: overfished',
(0.3, 5000, 250, 0.001),
[375.0, 2500.0, 150.0, 833.3333, 208.3333, 'overfished']),
('regression: collapse effort', (0.2, 3000, 300, 0.001), [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished']),
('regression: no fishing', (0.6, 800, 0, 0.002), [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable']),
('regression: high catchability', (0.8, 1500, 50, 0.01), [300.0, 750.0, 40.0, 562.5, 281.25, 'overfished']),
('control: invalid q', (0.5, 2000, 100, 0.0), None)],
[('regression: tuna fishery moderate effort',
(0.4, 10000, 100, 0.001),
[1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable']),
('regression: collapse effort', (0.2, 3000, 300, 0.001), [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished']),
('regression: no fishing', (0.6, 800, 0, 0.002), [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable']),
('regression: high catchability', (0.8, 1500, 50, 0.01), [300.0, 750.0, 40.0, 562.5, 281.25, 'overfished']),
('regression: slightly over msy',
(0.5, 2000, 250.4, 0.001),
[250.0, 1000.0, 250.0, 998.4, 249.9994, 'overfished']),
('control: invalid q', (0.5, 2000, 100, 0.0), None),
('regression: light fishing',
(1.2, 400, 20, 0.005),
[120.0, 200.0, 120.0, 366.6667, 36.6667, 'sustainable'])]]
for label, args, expected in fixtures[N - 1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: tuna fishery moderate effort | [1000.0, 5000.0, 0.2, 7500.0, 750.0, 'overfished'] | [1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable'] | Failed |
| regression: effort at msy | [250.0, 1000.0, 0.25, 1000.0, 250.0, 'overfished'] | [250.0, 1000.0, 250.0, 1000.0, 250.0, 'at-msy'] | Failed |
| regression: overfished | [375.0, 2500.0, 0.15, 833.3333, 208.3333, 'overfished'] | [375.0, 2500.0, 150.0, 833.3333, 208.3333, 'overfished'] | Failed |
| regression: collapse effort | [150.0, 1500.0, 0.1, 0.0, 0.0, 'overfished'] | [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished'] | Failed |
| regression: no fishing | [120.0, 400.0, 0.3, 800.0, 0.0, 'sustainable'] | [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable'] | Failed |
| regression: high catchability | [300.0, 750.0, 0.4, 562.5, 281.25, 'overfished'] | [300.0, 750.0, 40.0, 562.5, 281.25, 'overfished'] | Failed |
| control: invalid q | None | None | Passed |
SHA-256 / 9c0a1507380f44b99a713d1c23a6403ccd8c0864842e7efdf6e781cbda264a24
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(r, k, effort, q):
if r <= 0 or k <= 0 or q <= 0 or effort < 0:
return None
msy = r * k / 4
bmsy = k / 2
emsy = r / (4 * q)
b = k * (1 - q * effort / r) if q * effort < r else 0.0
y = q * effort * b
if effort > emsy:
status = 'overfished'
elif effort == emsy:
status = 'at-msy'
else:
status = 'sustainable'
return [round(msy, 4), round(bmsy, 4), round(emsy, 6), round(b, 4), round(y, 4), status]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: tuna fishery moderate effort',
(0.4, 10000, 100, 0.001),
[1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable']),
('regression: effort at msy', (0.5, 2000, 250, 0.001), [250.0, 1000.0, 250.0, 1000.0, 250.0, 'at-msy']),
('regression: overfished',
(0.3, 5000, 250, 0.001),
[375.0, 2500.0, 150.0, 833.3333, 208.3333, 'overfished']),
('regression: collapse effort', (0.2, 3000, 300, 0.001), [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished']),
('regression: no fishing', (0.6, 800, 0, 0.002), [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable']),
('regression: high catchability', (0.8, 1500, 50, 0.01), [300.0, 750.0, 40.0, 562.5, 281.25, 'overfished']),
('control: invalid q', (0.5, 2000, 100, 0.0), None)],
[('regression: tuna fishery moderate effort',
(0.4, 10000, 100, 0.001),
[1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable']),
('regression: collapse effort', (0.2, 3000, 300, 0.001), [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished']),
('regression: no fishing', (0.6, 800, 0, 0.002), [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable']),
('regression: high catchability', (0.8, 1500, 50, 0.01), [300.0, 750.0, 40.0, 562.5, 281.25, 'overfished']),
('regression: slightly over msy',
(0.5, 2000, 250.4, 0.001),
[250.0, 1000.0, 250.0, 998.4, 249.9994, 'overfished']),
('control: invalid q', (0.5, 2000, 100, 0.0), None),
('regression: light fishing',
(1.2, 400, 20, 0.005),
[120.0, 200.0, 120.0, 366.6667, 36.6667, 'sustainable'])],
[('regression: tuna fishery moderate effort',
(0.4, 10000, 100, 0.001),
[1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable']),
('regression: effort at msy', (0.5, 2000, 250, 0.001), [250.0, 1000.0, 250.0, 1000.0, 250.0, 'at-msy']),
('regression: overfished',
(0.3, 5000, 250, 0.001),
[375.0, 2500.0, 150.0, 833.3333, 208.3333, 'overfished']),
('regression: collapse effort', (0.2, 3000, 300, 0.001), [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished']),
('regression: slightly over msy',
(0.5, 2000, 250.4, 0.001),
[250.0, 1000.0, 250.0, 998.4, 249.9994, 'overfished']),
('control: invalid q', (0.5, 2000, 100, 0.0), None),
('regression: light fishing',
(1.2, 400, 20, 0.005),
[120.0, 200.0, 120.0, 366.6667, 36.6667, 'sustainable'])],
[('regression: tuna fishery moderate effort',
(0.4, 10000, 100, 0.001),
[1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable']),
('regression: effort at msy', (0.5, 2000, 250, 0.001), [250.0, 1000.0, 250.0, 1000.0, 250.0, 'at-msy']),
('regression: overfished',
(0.3, 5000, 250, 0.001),
[375.0, 2500.0, 150.0, 833.3333, 208.3333, 'overfished']),
('regression: collapse effort', (0.2, 3000, 300, 0.001), [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished']),
('regression: no fishing', (0.6, 800, 0, 0.002), [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable']),
('regression: high catchability', (0.8, 1500, 50, 0.01), [300.0, 750.0, 40.0, 562.5, 281.25, 'overfished']),
('control: invalid q', (0.5, 2000, 100, 0.0), None)],
[('regression: tuna fishery moderate effort',
(0.4, 10000, 100, 0.001),
[1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable']),
('regression: collapse effort', (0.2, 3000, 300, 0.001), [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished']),
('regression: no fishing', (0.6, 800, 0, 0.002), [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable']),
('regression: high catchability', (0.8, 1500, 50, 0.01), [300.0, 750.0, 40.0, 562.5, 281.25, 'overfished']),
('regression: slightly over msy',
(0.5, 2000, 250.4, 0.001),
[250.0, 1000.0, 250.0, 998.4, 249.9994, 'overfished']),
('control: invalid q', (0.5, 2000, 100, 0.0), None),
('regression: light fishing',
(1.2, 400, 20, 0.005),
[120.0, 200.0, 120.0, 366.6667, 36.6667, 'sustainable'])]]
for label, args, expected in fixtures[N - 1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: tuna fishery moderate effort | [1000.0, 5000.0, 100.0, 7500.0, 750.0, 'at-msy'] | [1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable'] | Failed |
| regression: effort at msy | [250.0, 1000.0, 125.0, 1000.0, 250.0, 'overfished'] | [250.0, 1000.0, 250.0, 1000.0, 250.0, 'at-msy'] | Failed |
| regression: overfished | [375.0, 2500.0, 75.0, 833.3333, 208.3333, 'overfished'] | [375.0, 2500.0, 150.0, 833.3333, 208.3333, 'overfished'] | Failed |
| regression: collapse effort | [150.0, 1500.0, 50.0, 0.0, 0.0, 'overfished'] | [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished'] | Failed |
| regression: no fishing | [120.0, 400.0, 75.0, 800.0, 0.0, 'sustainable'] | [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable'] | Failed |
| regression: high catchability | [300.0, 750.0, 20.0, 562.5, 281.25, 'overfished'] | [300.0, 750.0, 40.0, 562.5, 281.25, 'overfished'] | Failed |
| control: invalid q | None | None | Passed |
SHA-256 / e7ef0e31aafd195e74de76d92e5938781c49364f2b3a4c0350a741c889ece8b6
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(r, k, effort, q):
if r <= 0 or k <= 0 or q <= 0 or effort < 0:
return None
msy = r * k / 4
bmsy = k / 2
emsy = r / (2 * q)
b = k * (1 - q * effort / r) if q * effort < r else 0.0
y = q * effort * b
if effort > emsy:
status = 'overfished'
elif effort == emsy:
status = 'at-msy'
else:
status = 'sustainable'
return [round(msy, 4), round(bmsy, 4), round(emsy, 6), round(b, 4), round(y, 4), status]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: tuna fishery moderate effort',
(0.4, 10000, 100, 0.001),
[1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable']),
('regression: effort at msy', (0.5, 2000, 250, 0.001), [250.0, 1000.0, 250.0, 1000.0, 250.0, 'at-msy']),
('regression: overfished',
(0.3, 5000, 250, 0.001),
[375.0, 2500.0, 150.0, 833.3333, 208.3333, 'overfished']),
('regression: collapse effort', (0.2, 3000, 300, 0.001), [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished']),
('regression: no fishing', (0.6, 800, 0, 0.002), [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable']),
('regression: high catchability', (0.8, 1500, 50, 0.01), [300.0, 750.0, 40.0, 562.5, 281.25, 'overfished']),
('control: invalid q', (0.5, 2000, 100, 0.0), None)],
[('regression: tuna fishery moderate effort',
(0.4, 10000, 100, 0.001),
[1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable']),
('regression: collapse effort', (0.2, 3000, 300, 0.001), [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished']),
('regression: no fishing', (0.6, 800, 0, 0.002), [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable']),
('regression: high catchability', (0.8, 1500, 50, 0.01), [300.0, 750.0, 40.0, 562.5, 281.25, 'overfished']),
('regression: slightly over msy',
(0.5, 2000, 250.4, 0.001),
[250.0, 1000.0, 250.0, 998.4, 249.9994, 'overfished']),
('control: invalid q', (0.5, 2000, 100, 0.0), None),
('regression: light fishing',
(1.2, 400, 20, 0.005),
[120.0, 200.0, 120.0, 366.6667, 36.6667, 'sustainable'])],
[('regression: tuna fishery moderate effort',
(0.4, 10000, 100, 0.001),
[1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable']),
('regression: effort at msy', (0.5, 2000, 250, 0.001), [250.0, 1000.0, 250.0, 1000.0, 250.0, 'at-msy']),
('regression: overfished',
(0.3, 5000, 250, 0.001),
[375.0, 2500.0, 150.0, 833.3333, 208.3333, 'overfished']),
('regression: collapse effort', (0.2, 3000, 300, 0.001), [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished']),
('regression: slightly over msy',
(0.5, 2000, 250.4, 0.001),
[250.0, 1000.0, 250.0, 998.4, 249.9994, 'overfished']),
('control: invalid q', (0.5, 2000, 100, 0.0), None),
('regression: light fishing',
(1.2, 400, 20, 0.005),
[120.0, 200.0, 120.0, 366.6667, 36.6667, 'sustainable'])],
[('regression: tuna fishery moderate effort',
(0.4, 10000, 100, 0.001),
[1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable']),
('regression: effort at msy', (0.5, 2000, 250, 0.001), [250.0, 1000.0, 250.0, 1000.0, 250.0, 'at-msy']),
('regression: overfished',
(0.3, 5000, 250, 0.001),
[375.0, 2500.0, 150.0, 833.3333, 208.3333, 'overfished']),
('regression: collapse effort', (0.2, 3000, 300, 0.001), [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished']),
('regression: no fishing', (0.6, 800, 0, 0.002), [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable']),
('regression: high catchability', (0.8, 1500, 50, 0.01), [300.0, 750.0, 40.0, 562.5, 281.25, 'overfished']),
('control: invalid q', (0.5, 2000, 100, 0.0), None)],
[('regression: tuna fishery moderate effort',
(0.4, 10000, 100, 0.001),
[1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable']),
('regression: collapse effort', (0.2, 3000, 300, 0.001), [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished']),
('regression: no fishing', (0.6, 800, 0, 0.002), [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable']),
('regression: high catchability', (0.8, 1500, 50, 0.01), [300.0, 750.0, 40.0, 562.5, 281.25, 'overfished']),
('regression: slightly over msy',
(0.5, 2000, 250.4, 0.001),
[250.0, 1000.0, 250.0, 998.4, 249.9994, 'overfished']),
('control: invalid q', (0.5, 2000, 100, 0.0), None),
('regression: light fishing',
(1.2, 400, 20, 0.005),
[120.0, 200.0, 120.0, 366.6667, 36.6667, 'sustainable'])]]
for label, args, expected in fixtures[N - 1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: tuna fishery moderate effort | [1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable'] | [1000.0, 5000.0, 200.0, 7500.0, 750.0, 'sustainable'] | Passed |
| regression: effort at msy | [250.0, 1000.0, 250.0, 1000.0, 250.0, 'at-msy'] | [250.0, 1000.0, 250.0, 1000.0, 250.0, 'at-msy'] | Passed |
| regression: overfished | [375.0, 2500.0, 150.0, 833.3333, 208.3333, 'overfished'] | [375.0, 2500.0, 150.0, 833.3333, 208.3333, 'overfished'] | Passed |
| regression: collapse effort | [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished'] | [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished'] | Passed |
| regression: no fishing | [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable'] | [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable'] | Passed |
| regression: high catchability | [300.0, 750.0, 40.0, 562.5, 281.25, 'overfished'] | [300.0, 750.0, 40.0, 562.5, 281.25, 'overfished'] | Passed |
| control: invalid q | None | None | Passed |
SHA-256 / a9abc7f030033d312e8271aa81b1310223468722b245caf9b1ce71af0b04ef0c
Verification & scope
Deterministic bounded teaching model with a stipulated contract; not a validated scientific or public-health modelling library. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:47:35.185743+00:00.
Case digest / 53ab0cc42107dd146a6533321a97c76c2ed83270a6494443b870ed9a99b13b87