FAILURE MAP
← Case archive

FA-65371 / Ecological population dynamics / Open access

Ricker map trajectory and dynamic regime: exponent grouping · case 01

Populations above carrying capacity turn negative instead of being pulled down smoothly.

Verified by executionVariant 1 · 7 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The density term multiplies exp(r) instead of sitting inside the exponent.

VERIFIED REPAIR

Restore the exponent grouping rule: `math.exp(r * (1 - n / k))`.

Unsuccessful approach: Dividing (1-N) by K inside the exponent misplaces the crowding term.

Case contract

Regime by r: r<0 decline, r==0 neutral, 0<r<=1 monotone, 1<r<2 damped, 2<=r<2.526 cycle2, else complex; trajectory N[t+1]=N*exp(r*(1-N/K)) rounded 4; None for K<=0 or N0<0.

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, n0, years):
    if k <= 0 or n0 < 0:
        return None
    if r < 0:
        regime = 'decline'
    elif r == 0:
        regime = 'neutral'
    elif r <= 1:
        regime = 'monotone'
    elif r < 2:
        regime = 'damped'
    elif r < 2.526:
        regime = 'cycle2'
    else:
        regime = 'complex'
    n = float(n0)
    traj = []
    for _ in range(years):
        n = n * math.exp(r) * (1 - n / k)
        traj.append(round(n, 4))
    return [regime, traj]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: salmon stock damped',
   (1.5, 1000, 200, 6),
   ['damped', [664.0234, 1099.1389, 947.2604, 1025.2415, 987.1493, 1006.3622]]),
  ('regression: superstable r one',
   (1.0, 500, 100, 5),
   ['monotone', [222.5541, 387.6342, 485.3128, 499.78, 500.0]]),
  ('regression: two cycle',
   (2.2, 100, 30, 6),
   ['cycle2', [139.9377, 58.1234, 146.0361, 53.0407, 149.0324, 50.6759]]),
  ('regression: period doubling onset exactly 2',
   (2.0, 100, 40, 5),
   ['cycle2', [132.8047, 68.9089, 128.3303, 72.8208, 125.4096]]),
  ('regression: near two', (1.96, 100, 40, 4), ['damped', [129.6553, 72.5035, 124.2836, 77.2161]]),
  ('control: neutral empty patch', (0.0, 100, 0, 3), ['neutral', [0.0, 0.0, 0.0]]),
  ('control: invalid capacity', (1.0, 0, 10, 3), None)],
 [('regression: period doubling onset exactly 2',
   (2.0, 100, 40, 5),
   ['cycle2', [132.8047, 68.9089, 128.3303, 72.8208, 125.4096]]),
  ('regression: near two', (1.96, 100, 40, 4), ['damped', [129.6553, 72.5035, 124.2836, 77.2161]]),
  ('regression: chaotic', (3.0, 100, 10, 5), ['complex', [148.7973, 34.421, 246.1736, 3.0674, 56.1939]]),
  ('regression: neutral', (0.0, 100, 60, 3), ['neutral', [60.0, 60.0, 60.0]]),
  ('control: neutral empty patch', (0.0, 100, 0, 3), ['neutral', [0.0, 0.0, 0.0]]),
  ('regression: declining', (-0.3, 100, 80, 4), ['decline', [75.3412, 69.9688, 63.9407, 57.3848]]),
  ('control: invalid capacity', (1.0, 0, 10, 3), None)],
 [('regression: salmon stock damped',
   (1.5, 1000, 200, 6),
   ['damped', [664.0234, 1099.1389, 947.2604, 1025.2415, 987.1493, 1006.3622]]),
  ('regression: neutral', (0.0, 100, 60, 3), ['neutral', [60.0, 60.0, 60.0]]),
  ('control: neutral empty patch', (0.0, 100, 0, 3), ['neutral', [0.0, 0.0, 0.0]]),
  ('regression: declining', (-0.3, 100, 80, 4), ['decline', [75.3412, 69.9688, 63.9407, 57.3848]]),
  ('control: invalid capacity', (1.0, 0, 10, 3), None),
  ('regression: weak growth above K',
   (0.5, 200, 350, 5),
   ['monotone', [240.5512, 217.36, 208.1284, 203.9417, 201.9419]]),
  ('regression: weak growth below K',
   (0.7, 200, 20, 5),
   ['monotone', [37.5522, 66.3073, 105.8713, 147.1827, 177.0682]])],
 [('regression: salmon stock damped',
   (1.5, 1000, 200, 6),
   ['damped', [664.0234, 1099.1389, 947.2604, 1025.2415, 987.1493, 1006.3622]]),
  ('regression: superstable r one',
   (1.0, 500, 100, 5),
   ['monotone', [222.5541, 387.6342, 485.3128, 499.78, 500.0]]),
  ('regression: two cycle',
   (2.2, 100, 30, 6),
   ['cycle2', [139.9377, 58.1234, 146.0361, 53.0407, 149.0324, 50.6759]]),
  ('control: neutral empty patch', (0.0, 100, 0, 3), ['neutral', [0.0, 0.0, 0.0]]),
  ('control: invalid capacity', (1.0, 0, 10, 3), None),
  ('regression: weak growth above K',
   (0.5, 200, 350, 5),
   ['monotone', [240.5512, 217.36, 208.1284, 203.9417, 201.9419]]),
  ('regression: weak growth below K',
   (0.7, 200, 20, 5),
   ['monotone', [37.5522, 66.3073, 105.8713, 147.1827, 177.0682]])],
 [('regression: salmon stock damped',
   (1.5, 1000, 200, 6),
   ['damped', [664.0234, 1099.1389, 947.2604, 1025.2415, 987.1493, 1006.3622]]),
  ('regression: superstable r one',
   (1.0, 500, 100, 5),
   ['monotone', [222.5541, 387.6342, 485.3128, 499.78, 500.0]]),
  ('regression: two cycle',
   (2.2, 100, 30, 6),
   ['cycle2', [139.9377, 58.1234, 146.0361, 53.0407, 149.0324, 50.6759]]),
  ('regression: period doubling onset exactly 2',
   (2.0, 100, 40, 5),
   ['cycle2', [132.8047, 68.9089, 128.3303, 72.8208, 125.4096]]),
  ('regression: near two', (1.96, 100, 40, 4), ['damped', [129.6553, 72.5035, 124.2836, 77.2161]]),
  ('control: neutral empty patch', (0.0, 100, 0, 3), ['neutral', [0.0, 0.0, 0.0]]),
  ('control: invalid capacity', (1.0, 0, 10, 3), None)]]
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 fixtureActualExpectedOutcome
regression: salmon stock damped['damped', [717.0703, 909.2473, 369.8138, 1044.4646, -208.1372, -1126.9578]]['damped', [664.0234, 1099.1389, 947.2604, 1025.2415, 987.1493, 1006.3622]]Failed
regression: superstable r one['monotone', [217.4625, 334.0296, 301.3978, 325.4233, 308.8584]]['monotone', [222.5541, 387.6342, 485.3128, 499.78, 500.0]]Failed
regression: two cycle['cycle2', [189.5253, -1531.3015, -225446.152, -4589085079.6969, -1.9006409780069967e+18, -3.2602284814540045e+35]]['cycle2', [139.9377, 58.1234, 146.0361, 53.0407, 149.0324, 50.6759]]Failed
regression: period doubling onset exactly 2['cycle2', [177.3373, -1013.3942, -83371.2616, -514212127.2252, -1.953771085285938e+16]]['cycle2', [132.8047, 68.9089, 128.3303, 72.8208, 125.4096]]Failed
regression: near two['damped', [170.3838, -851.3706, -57502.3401, -235148834.2026]]['damped', [129.6553, 72.5035, 124.2836, 77.2161]]Failed
control: neutral empty patch['neutral', [0.0, 0.0, 0.0]]['neutral', [0.0, 0.0, 0.0]]Passed
control: invalid capacityNoneNonePassed

SHA-256 / 74ee5a4995d035e20f84eb873a2e227ee9106e450ad9a16939a52a3c2c58aebb

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, n0, years):
    if k <= 0 or n0 < 0:
        return None
    if r < 0:
        regime = 'decline'
    elif r == 0:
        regime = 'neutral'
    elif r <= 1:
        regime = 'monotone'
    elif r < 2:
        regime = 'damped'
    elif r < 2.526:
        regime = 'cycle2'
    else:
        regime = 'complex'
    n = float(n0)
    traj = []
    for _ in range(years):
        n = n * math.exp(r * (1 - n) / k)
        traj.append(round(n, 4))
    return [regime, traj]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: salmon stock damped',
   (1.5, 1000, 200, 6),
   ['damped', [664.0234, 1099.1389, 947.2604, 1025.2415, 987.1493, 1006.3622]]),
  ('regression: superstable r one',
   (1.0, 500, 100, 5),
   ['monotone', [222.5541, 387.6342, 485.3128, 499.78, 500.0]]),
  ('regression: two cycle',
   (2.2, 100, 30, 6),
   ['cycle2', [139.9377, 58.1234, 146.0361, 53.0407, 149.0324, 50.6759]]),
  ('regression: period doubling onset exactly 2',
   (2.0, 100, 40, 5),
   ['cycle2', [132.8047, 68.9089, 128.3303, 72.8208, 125.4096]]),
  ('regression: near two', (1.96, 100, 40, 4), ['damped', [129.6553, 72.5035, 124.2836, 77.2161]]),
  ('control: neutral empty patch', (0.0, 100, 0, 3), ['neutral', [0.0, 0.0, 0.0]]),
  ('control: invalid capacity', (1.0, 0, 10, 3), None)],
 [('regression: period doubling onset exactly 2',
   (2.0, 100, 40, 5),
   ['cycle2', [132.8047, 68.9089, 128.3303, 72.8208, 125.4096]]),
  ('regression: near two', (1.96, 100, 40, 4), ['damped', [129.6553, 72.5035, 124.2836, 77.2161]]),
  ('regression: chaotic', (3.0, 100, 10, 5), ['complex', [148.7973, 34.421, 246.1736, 3.0674, 56.1939]]),
  ('regression: neutral', (0.0, 100, 60, 3), ['neutral', [60.0, 60.0, 60.0]]),
  ('control: neutral empty patch', (0.0, 100, 0, 3), ['neutral', [0.0, 0.0, 0.0]]),
  ('regression: declining', (-0.3, 100, 80, 4), ['decline', [75.3412, 69.9688, 63.9407, 57.3848]]),
  ('control: invalid capacity', (1.0, 0, 10, 3), None)],
 [('regression: salmon stock damped',
   (1.5, 1000, 200, 6),
   ['damped', [664.0234, 1099.1389, 947.2604, 1025.2415, 987.1493, 1006.3622]]),
  ('regression: neutral', (0.0, 100, 60, 3), ['neutral', [60.0, 60.0, 60.0]]),
  ('control: neutral empty patch', (0.0, 100, 0, 3), ['neutral', [0.0, 0.0, 0.0]]),
  ('regression: declining', (-0.3, 100, 80, 4), ['decline', [75.3412, 69.9688, 63.9407, 57.3848]]),
  ('control: invalid capacity', (1.0, 0, 10, 3), None),
  ('regression: weak growth above K',
   (0.5, 200, 350, 5),
   ['monotone', [240.5512, 217.36, 208.1284, 203.9417, 201.9419]]),
  ('regression: weak growth below K',
   (0.7, 200, 20, 5),
   ['monotone', [37.5522, 66.3073, 105.8713, 147.1827, 177.0682]])],
 [('regression: salmon stock damped',
   (1.5, 1000, 200, 6),
   ['damped', [664.0234, 1099.1389, 947.2604, 1025.2415, 987.1493, 1006.3622]]),
  ('regression: superstable r one',
   (1.0, 500, 100, 5),
   ['monotone', [222.5541, 387.6342, 485.3128, 499.78, 500.0]]),
  ('regression: two cycle',
   (2.2, 100, 30, 6),
   ['cycle2', [139.9377, 58.1234, 146.0361, 53.0407, 149.0324, 50.6759]]),
  ('control: neutral empty patch', (0.0, 100, 0, 3), ['neutral', [0.0, 0.0, 0.0]]),
  ('control: invalid capacity', (1.0, 0, 10, 3), None),
  ('regression: weak growth above K',
   (0.5, 200, 350, 5),
   ['monotone', [240.5512, 217.36, 208.1284, 203.9417, 201.9419]]),
  ('regression: weak growth below K',
   (0.7, 200, 20, 5),
   ['monotone', [37.5522, 66.3073, 105.8713, 147.1827, 177.0682]])],
 [('regression: salmon stock damped',
   (1.5, 1000, 200, 6),
   ['damped', [664.0234, 1099.1389, 947.2604, 1025.2415, 987.1493, 1006.3622]]),
  ('regression: superstable r one',
   (1.0, 500, 100, 5),
   ['monotone', [222.5541, 387.6342, 485.3128, 499.78, 500.0]]),
  ('regression: two cycle',
   (2.2, 100, 30, 6),
   ['cycle2', [139.9377, 58.1234, 146.0361, 53.0407, 149.0324, 50.6759]]),
  ('regression: period doubling onset exactly 2',
   (2.0, 100, 40, 5),
   ['cycle2', [132.8047, 68.9089, 128.3303, 72.8208, 125.4096]]),
  ('regression: near two', (1.96, 100, 40, 4), ['damped', [129.6553, 72.5035, 124.2836, 77.2161]]),
  ('control: neutral empty patch', (0.0, 100, 0, 3), ['neutral', [0.0, 0.0, 0.0]]),
  ('control: invalid capacity', (1.0, 0, 10, 3), None)]]
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 fixtureActualExpectedOutcome
regression: salmon stock damped['damped', [148.3861, 118.9542, 99.6642, 85.9539, 75.6699, 67.6519]]['damped', [664.0234, 1099.1389, 947.2604, 1025.2415, 987.1493, 1006.3622]]Failed
regression: superstable r one['monotone', [82.037, 69.7625, 60.7989, 53.9455, 48.5252]]['monotone', [222.5541, 387.6342, 485.3128, 499.78, 500.0]]Failed
regression: two cycle['cycle2', [15.8504, 11.4328, 9.0881, 7.6067, 6.5777, 5.8181]]['cycle2', [139.9377, 58.1234, 146.0361, 53.0407, 149.0324, 50.6759]]Failed
regression: period doubling onset exactly 2['cycle2', [18.3362, 12.9637, 10.205, 8.4891, 7.3082]]['cycle2', [132.8047, 68.9089, 128.3303, 72.8208, 125.4096]]Failed
regression: near two['damped', [18.6245, 13.1845, 10.3836, 8.6392]]['damped', [129.6553, 72.5035, 124.2836, 77.2161]]Failed
control: neutral empty patch['neutral', [0.0, 0.0, 0.0]]['neutral', [0.0, 0.0, 0.0]]Passed
control: invalid capacityNoneNonePassed

SHA-256 / 4268ef614bc2522ee58d44f509d2b55d2c56ccf2b394661b75958bc00a26ad89

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, n0, years):
    if k <= 0 or n0 < 0:
        return None
    if r < 0:
        regime = 'decline'
    elif r == 0:
        regime = 'neutral'
    elif r <= 1:
        regime = 'monotone'
    elif r < 2:
        regime = 'damped'
    elif r < 2.526:
        regime = 'cycle2'
    else:
        regime = 'complex'
    n = float(n0)
    traj = []
    for _ in range(years):
        n = n * math.exp(r * (1 - n / k))
        traj.append(round(n, 4))
    return [regime, traj]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: salmon stock damped',
   (1.5, 1000, 200, 6),
   ['damped', [664.0234, 1099.1389, 947.2604, 1025.2415, 987.1493, 1006.3622]]),
  ('regression: superstable r one',
   (1.0, 500, 100, 5),
   ['monotone', [222.5541, 387.6342, 485.3128, 499.78, 500.0]]),
  ('regression: two cycle',
   (2.2, 100, 30, 6),
   ['cycle2', [139.9377, 58.1234, 146.0361, 53.0407, 149.0324, 50.6759]]),
  ('regression: period doubling onset exactly 2',
   (2.0, 100, 40, 5),
   ['cycle2', [132.8047, 68.9089, 128.3303, 72.8208, 125.4096]]),
  ('regression: near two', (1.96, 100, 40, 4), ['damped', [129.6553, 72.5035, 124.2836, 77.2161]]),
  ('control: neutral empty patch', (0.0, 100, 0, 3), ['neutral', [0.0, 0.0, 0.0]]),
  ('control: invalid capacity', (1.0, 0, 10, 3), None)],
 [('regression: period doubling onset exactly 2',
   (2.0, 100, 40, 5),
   ['cycle2', [132.8047, 68.9089, 128.3303, 72.8208, 125.4096]]),
  ('regression: near two', (1.96, 100, 40, 4), ['damped', [129.6553, 72.5035, 124.2836, 77.2161]]),
  ('regression: chaotic', (3.0, 100, 10, 5), ['complex', [148.7973, 34.421, 246.1736, 3.0674, 56.1939]]),
  ('regression: neutral', (0.0, 100, 60, 3), ['neutral', [60.0, 60.0, 60.0]]),
  ('control: neutral empty patch', (0.0, 100, 0, 3), ['neutral', [0.0, 0.0, 0.0]]),
  ('regression: declining', (-0.3, 100, 80, 4), ['decline', [75.3412, 69.9688, 63.9407, 57.3848]]),
  ('control: invalid capacity', (1.0, 0, 10, 3), None)],
 [('regression: salmon stock damped',
   (1.5, 1000, 200, 6),
   ['damped', [664.0234, 1099.1389, 947.2604, 1025.2415, 987.1493, 1006.3622]]),
  ('regression: neutral', (0.0, 100, 60, 3), ['neutral', [60.0, 60.0, 60.0]]),
  ('control: neutral empty patch', (0.0, 100, 0, 3), ['neutral', [0.0, 0.0, 0.0]]),
  ('regression: declining', (-0.3, 100, 80, 4), ['decline', [75.3412, 69.9688, 63.9407, 57.3848]]),
  ('control: invalid capacity', (1.0, 0, 10, 3), None),
  ('regression: weak growth above K',
   (0.5, 200, 350, 5),
   ['monotone', [240.5512, 217.36, 208.1284, 203.9417, 201.9419]]),
  ('regression: weak growth below K',
   (0.7, 200, 20, 5),
   ['monotone', [37.5522, 66.3073, 105.8713, 147.1827, 177.0682]])],
 [('regression: salmon stock damped',
   (1.5, 1000, 200, 6),
   ['damped', [664.0234, 1099.1389, 947.2604, 1025.2415, 987.1493, 1006.3622]]),
  ('regression: superstable r one',
   (1.0, 500, 100, 5),
   ['monotone', [222.5541, 387.6342, 485.3128, 499.78, 500.0]]),
  ('regression: two cycle',
   (2.2, 100, 30, 6),
   ['cycle2', [139.9377, 58.1234, 146.0361, 53.0407, 149.0324, 50.6759]]),
  ('control: neutral empty patch', (0.0, 100, 0, 3), ['neutral', [0.0, 0.0, 0.0]]),
  ('control: invalid capacity', (1.0, 0, 10, 3), None),
  ('regression: weak growth above K',
   (0.5, 200, 350, 5),
   ['monotone', [240.5512, 217.36, 208.1284, 203.9417, 201.9419]]),
  ('regression: weak growth below K',
   (0.7, 200, 20, 5),
   ['monotone', [37.5522, 66.3073, 105.8713, 147.1827, 177.0682]])],
 [('regression: salmon stock damped',
   (1.5, 1000, 200, 6),
   ['damped', [664.0234, 1099.1389, 947.2604, 1025.2415, 987.1493, 1006.3622]]),
  ('regression: superstable r one',
   (1.0, 500, 100, 5),
   ['monotone', [222.5541, 387.6342, 485.3128, 499.78, 500.0]]),
  ('regression: two cycle',
   (2.2, 100, 30, 6),
   ['cycle2', [139.9377, 58.1234, 146.0361, 53.0407, 149.0324, 50.6759]]),
  ('regression: period doubling onset exactly 2',
   (2.0, 100, 40, 5),
   ['cycle2', [132.8047, 68.9089, 128.3303, 72.8208, 125.4096]]),
  ('regression: near two', (1.96, 100, 40, 4), ['damped', [129.6553, 72.5035, 124.2836, 77.2161]]),
  ('control: neutral empty patch', (0.0, 100, 0, 3), ['neutral', [0.0, 0.0, 0.0]]),
  ('control: invalid capacity', (1.0, 0, 10, 3), None)]]
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 fixtureActualExpectedOutcome
regression: salmon stock damped['damped', [664.0234, 1099.1389, 947.2604, 1025.2415, 987.1493, 1006.3622]]['damped', [664.0234, 1099.1389, 947.2604, 1025.2415, 987.1493, 1006.3622]]Passed
regression: superstable r one['monotone', [222.5541, 387.6342, 485.3128, 499.78, 500.0]]['monotone', [222.5541, 387.6342, 485.3128, 499.78, 500.0]]Passed
regression: two cycle['cycle2', [139.9377, 58.1234, 146.0361, 53.0407, 149.0324, 50.6759]]['cycle2', [139.9377, 58.1234, 146.0361, 53.0407, 149.0324, 50.6759]]Passed
regression: period doubling onset exactly 2['cycle2', [132.8047, 68.9089, 128.3303, 72.8208, 125.4096]]['cycle2', [132.8047, 68.9089, 128.3303, 72.8208, 125.4096]]Passed
regression: near two['damped', [129.6553, 72.5035, 124.2836, 77.2161]]['damped', [129.6553, 72.5035, 124.2836, 77.2161]]Passed
control: neutral empty patch['neutral', [0.0, 0.0, 0.0]]['neutral', [0.0, 0.0, 0.0]]Passed
control: invalid capacityNoneNonePassed

SHA-256 / 011b53be07787226d3b6afee4e4f427b23214e4b5eb5c2e69535f3ffa45bd73a

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:33.330675+00:00.

Case digest / 5f45115eb9c8b36c7d104e0024048a794cfaeea50e2f0bb5153a6e6579488b55