FAILURE MAP
← Case archive

FA-65676 / Ecological population dynamics / Open access

Stochastic growth rate and quasi-extinction: geometric mean · case 01

The geometric mean growth rate is reported on the log scale.

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

ROOT CAUSE

The mean log growth rate is not exponentiated.

VERIFIED REPAIR

Restore the geometric mean rule: `geo = math.exp(sum(logs) / len(logs))`.

Unsuccessful approach: Exponentiating before averaging divides the product by the count.

Case contract

Geometric mean growth exp(mean ln lambda) determines trend (declining <1, stable ==1, growing >1); arithmetic mean reported alongside; trajectory multiplies N by each lambda; quasi-extinction time is the first 1-based year with N < threshold or None; return [geo, arith, trajectory, hit, trend]; None for empty, non-positive lambdas 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(lambdas, n0, threshold):
    if not lambdas or min(lambdas) <= 0 or n0 <= 0:
        return None
    logs = [math.log(x) for x in lambdas]
    geo = sum(logs) / len(logs)
    arith = sum(lambdas) / len(lambdas)
    n = float(n0)
    traj = []
    hit = None
    for t, lam in enumerate(lambdas, start=1):
        n *= lam
        traj.append(round(n, 4))
        if hit is None and n < threshold:
            hit = t
    trend = 'declining' if geo < 1 else ('stable' if geo == 1 else 'growing')
    return [round(geo, 6), round(arith, 6), traj, hit, trend]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: boom and bust',
   ([1.5, 0.5, 1.5, 0.5], 100, 20),
   [0.866025, 1.0, [150.0, 75.0, 112.5, 56.25], None, 'declining']),
  ('regression: exact halving to threshold',
   ([0.5, 1.0, 2.0], 100, 50),
   [1.0, 1.166667, [50.0, 50.0, 100.0], None, 'stable']),
  ('regression: balanced doubling halving',
   ([2.0, 0.5], 100, 10),
   [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('regression: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('regression: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('regression: dip and recovery',
   ([0.4, 0.8, 3.0, 2.0], 100, 50),
   [1.177132, 1.55, [40.0, 32.0, 96.0, 192.0], 1, 'growing']),
  ('control: invalid zero lambda', ([1.0, 0.0], 10, 1), None)],
 [('regression: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('regression: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('regression: dip and recovery',
   ([0.4, 0.8, 3.0, 2.0], 100, 50),
   [1.177132, 1.55, [40.0, 32.0, 96.0, 192.0], 1, 'growing']),
  ('control: invalid zero lambda', ([1.0, 0.0], 10, 1), None),
  ('regression: first year crash',
   ([0.1, 1.5, 1.5], 100, 20),
   [0.60822, 1.033333, [10.0, 15.0, 22.5], 1, 'declining']),
  ('regression: high variance decline',
   ([3.0, 0.3, 3.0, 0.3], 100, 5),
   [0.948683, 1.65, [300.0, 90.0, 270.0, 81.0], None, 'declining']),
  ('regression: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, 'declining'])],
 [('regression: boom and bust',
   ([1.5, 0.5, 1.5, 0.5], 100, 20),
   [0.866025, 1.0, [150.0, 75.0, 112.5, 56.25], None, 'declining']),
  ('regression: exact halving to threshold',
   ([0.5, 1.0, 2.0], 100, 50),
   [1.0, 1.166667, [50.0, 50.0, 100.0], None, 'stable']),
  ('control: invalid zero lambda', ([1.0, 0.0], 10, 1), None),
  ('regression: first year crash',
   ([0.1, 1.5, 1.5], 100, 20),
   [0.60822, 1.033333, [10.0, 15.0, 22.5], 1, 'declining']),
  ('regression: high variance decline',
   ([3.0, 0.3, 3.0, 0.3], 100, 5),
   [0.948683, 1.65, [300.0, 90.0, 270.0, 81.0], None, 'declining']),
  ('regression: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, 'declining']),
  ('regression: slow decline',
   ([0.95, 1.02, 0.9, 1.05, 0.93], 80, 60),
   [0.968384, 0.97, [76.0, 77.52, 69.768, 73.2564, 68.1285], None, 'declining'])],
 [('regression: boom and bust',
   ([1.5, 0.5, 1.5, 0.5], 100, 20),
   [0.866025, 1.0, [150.0, 75.0, 112.5, 56.25], None, 'declining']),
  ('regression: exact halving to threshold',
   ([0.5, 1.0, 2.0], 100, 50),
   [1.0, 1.166667, [50.0, 50.0, 100.0], None, 'stable']),
  ('regression: balanced doubling halving',
   ([2.0, 0.5], 100, 10),
   [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('regression: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('control: invalid zero lambda', ([1.0, 0.0], 10, 1), None),
  ('regression: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, 'declining']),
  ('regression: slow decline',
   ([0.95, 1.02, 0.9, 1.05, 0.93], 80, 60),
   [0.968384, 0.97, [76.0, 77.52, 69.768, 73.2564, 68.1285], None, 'declining'])],
 [('regression: exact halving to threshold',
   ([0.5, 1.0, 2.0], 100, 50),
   [1.0, 1.166667, [50.0, 50.0, 100.0], None, 'stable']),
  ('regression: balanced doubling halving',
   ([2.0, 0.5], 100, 10),
   [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('regression: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('regression: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('regression: dip and recovery',
   ([0.4, 0.8, 3.0, 2.0], 100, 50),
   [1.177132, 1.55, [40.0, 32.0, 96.0, 192.0], 1, 'growing']),
  ('control: invalid zero lambda', ([1.0, 0.0], 10, 1), None),
  ('regression: first year crash',
   ([0.1, 1.5, 1.5], 100, 20),
   [0.60822, 1.033333, [10.0, 15.0, 22.5], 1, 'declining'])]]
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: boom and bust[-0.143841, 1.0, [150.0, 75.0, 112.5, 56.25], None, 'declining'][0.866025, 1.0, [150.0, 75.0, 112.5, 56.25], None, 'declining']Failed
regression: exact halving to threshold[0.0, 1.166667, [50.0, 50.0, 100.0], None, 'declining'][1.0, 1.166667, [50.0, 50.0, 100.0], None, 'stable']Failed
regression: balanced doubling halving[0.0, 1.25, [200.0, 100.0], None, 'declining'][1.0, 1.25, [200.0, 100.0], None, 'stable']Failed
regression: steady growth[0.108807, 1.116667, [55.0, 66.0, 69.3], None, 'declining'][1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']Failed
regression: constant[0.0, 1.0, [30.0, 30.0, 30.0], None, 'declining'][1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']Failed
regression: dip and recovery[0.163081, 1.55, [40.0, 32.0, 96.0, 192.0], 1, 'declining'][1.177132, 1.55, [40.0, 32.0, 96.0, 192.0], 1, 'growing']Failed
control: invalid zero lambdaNoneNonePassed

SHA-256 / a614faef1c559a827288afcc76b9d447a667c36e4840a29170c553da62c68239

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(lambdas, n0, threshold):
    if not lambdas or min(lambdas) <= 0 or n0 <= 0:
        return None
    logs = [math.log(x) for x in lambdas]
    geo = math.exp(sum(logs)) / len(logs)
    arith = sum(lambdas) / len(lambdas)
    n = float(n0)
    traj = []
    hit = None
    for t, lam in enumerate(lambdas, start=1):
        n *= lam
        traj.append(round(n, 4))
        if hit is None and n < threshold:
            hit = t
    trend = 'declining' if geo < 1 else ('stable' if geo == 1 else 'growing')
    return [round(geo, 6), round(arith, 6), traj, hit, trend]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: boom and bust',
   ([1.5, 0.5, 1.5, 0.5], 100, 20),
   [0.866025, 1.0, [150.0, 75.0, 112.5, 56.25], None, 'declining']),
  ('regression: exact halving to threshold',
   ([0.5, 1.0, 2.0], 100, 50),
   [1.0, 1.166667, [50.0, 50.0, 100.0], None, 'stable']),
  ('regression: balanced doubling halving',
   ([2.0, 0.5], 100, 10),
   [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('regression: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('regression: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('regression: dip and recovery',
   ([0.4, 0.8, 3.0, 2.0], 100, 50),
   [1.177132, 1.55, [40.0, 32.0, 96.0, 192.0], 1, 'growing']),
  ('control: invalid zero lambda', ([1.0, 0.0], 10, 1), None)],
 [('regression: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('regression: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('regression: dip and recovery',
   ([0.4, 0.8, 3.0, 2.0], 100, 50),
   [1.177132, 1.55, [40.0, 32.0, 96.0, 192.0], 1, 'growing']),
  ('control: invalid zero lambda', ([1.0, 0.0], 10, 1), None),
  ('regression: first year crash',
   ([0.1, 1.5, 1.5], 100, 20),
   [0.60822, 1.033333, [10.0, 15.0, 22.5], 1, 'declining']),
  ('regression: high variance decline',
   ([3.0, 0.3, 3.0, 0.3], 100, 5),
   [0.948683, 1.65, [300.0, 90.0, 270.0, 81.0], None, 'declining']),
  ('regression: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, 'declining'])],
 [('regression: boom and bust',
   ([1.5, 0.5, 1.5, 0.5], 100, 20),
   [0.866025, 1.0, [150.0, 75.0, 112.5, 56.25], None, 'declining']),
  ('regression: exact halving to threshold',
   ([0.5, 1.0, 2.0], 100, 50),
   [1.0, 1.166667, [50.0, 50.0, 100.0], None, 'stable']),
  ('control: invalid zero lambda', ([1.0, 0.0], 10, 1), None),
  ('regression: first year crash',
   ([0.1, 1.5, 1.5], 100, 20),
   [0.60822, 1.033333, [10.0, 15.0, 22.5], 1, 'declining']),
  ('regression: high variance decline',
   ([3.0, 0.3, 3.0, 0.3], 100, 5),
   [0.948683, 1.65, [300.0, 90.0, 270.0, 81.0], None, 'declining']),
  ('regression: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, 'declining']),
  ('regression: slow decline',
   ([0.95, 1.02, 0.9, 1.05, 0.93], 80, 60),
   [0.968384, 0.97, [76.0, 77.52, 69.768, 73.2564, 68.1285], None, 'declining'])],
 [('regression: boom and bust',
   ([1.5, 0.5, 1.5, 0.5], 100, 20),
   [0.866025, 1.0, [150.0, 75.0, 112.5, 56.25], None, 'declining']),
  ('regression: exact halving to threshold',
   ([0.5, 1.0, 2.0], 100, 50),
   [1.0, 1.166667, [50.0, 50.0, 100.0], None, 'stable']),
  ('regression: balanced doubling halving',
   ([2.0, 0.5], 100, 10),
   [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('regression: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('control: invalid zero lambda', ([1.0, 0.0], 10, 1), None),
  ('regression: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, 'declining']),
  ('regression: slow decline',
   ([0.95, 1.02, 0.9, 1.05, 0.93], 80, 60),
   [0.968384, 0.97, [76.0, 77.52, 69.768, 73.2564, 68.1285], None, 'declining'])],
 [('regression: exact halving to threshold',
   ([0.5, 1.0, 2.0], 100, 50),
   [1.0, 1.166667, [50.0, 50.0, 100.0], None, 'stable']),
  ('regression: balanced doubling halving',
   ([2.0, 0.5], 100, 10),
   [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('regression: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('regression: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('regression: dip and recovery',
   ([0.4, 0.8, 3.0, 2.0], 100, 50),
   [1.177132, 1.55, [40.0, 32.0, 96.0, 192.0], 1, 'growing']),
  ('control: invalid zero lambda', ([1.0, 0.0], 10, 1), None),
  ('regression: first year crash',
   ([0.1, 1.5, 1.5], 100, 20),
   [0.60822, 1.033333, [10.0, 15.0, 22.5], 1, 'declining'])]]
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: boom and bust[0.140625, 1.0, [150.0, 75.0, 112.5, 56.25], None, 'declining'][0.866025, 1.0, [150.0, 75.0, 112.5, 56.25], None, 'declining']Failed
regression: exact halving to threshold[0.333333, 1.166667, [50.0, 50.0, 100.0], None, 'declining'][1.0, 1.166667, [50.0, 50.0, 100.0], None, 'stable']Failed
regression: balanced doubling halving[0.5, 1.25, [200.0, 100.0], None, 'declining'][1.0, 1.25, [200.0, 100.0], None, 'stable']Failed
regression: steady growth[0.462, 1.116667, [55.0, 66.0, 69.3], None, 'declining'][1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']Failed
regression: constant[0.333333, 1.0, [30.0, 30.0, 30.0], None, 'declining'][1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']Failed
regression: dip and recovery[0.48, 1.55, [40.0, 32.0, 96.0, 192.0], 1, 'declining'][1.177132, 1.55, [40.0, 32.0, 96.0, 192.0], 1, 'growing']Failed
control: invalid zero lambdaNoneNonePassed

SHA-256 / 48fec58dbf6fd8303763d11a5dad09b605843167cf8cfca60451619140315c18

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(lambdas, n0, threshold):
    if not lambdas or min(lambdas) <= 0 or n0 <= 0:
        return None
    logs = [math.log(x) for x in lambdas]
    geo = math.exp(sum(logs) / len(logs))
    arith = sum(lambdas) / len(lambdas)
    n = float(n0)
    traj = []
    hit = None
    for t, lam in enumerate(lambdas, start=1):
        n *= lam
        traj.append(round(n, 4))
        if hit is None and n < threshold:
            hit = t
    trend = 'declining' if geo < 1 else ('stable' if geo == 1 else 'growing')
    return [round(geo, 6), round(arith, 6), traj, hit, trend]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: boom and bust',
   ([1.5, 0.5, 1.5, 0.5], 100, 20),
   [0.866025, 1.0, [150.0, 75.0, 112.5, 56.25], None, 'declining']),
  ('regression: exact halving to threshold',
   ([0.5, 1.0, 2.0], 100, 50),
   [1.0, 1.166667, [50.0, 50.0, 100.0], None, 'stable']),
  ('regression: balanced doubling halving',
   ([2.0, 0.5], 100, 10),
   [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('regression: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('regression: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('regression: dip and recovery',
   ([0.4, 0.8, 3.0, 2.0], 100, 50),
   [1.177132, 1.55, [40.0, 32.0, 96.0, 192.0], 1, 'growing']),
  ('control: invalid zero lambda', ([1.0, 0.0], 10, 1), None)],
 [('regression: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('regression: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('regression: dip and recovery',
   ([0.4, 0.8, 3.0, 2.0], 100, 50),
   [1.177132, 1.55, [40.0, 32.0, 96.0, 192.0], 1, 'growing']),
  ('control: invalid zero lambda', ([1.0, 0.0], 10, 1), None),
  ('regression: first year crash',
   ([0.1, 1.5, 1.5], 100, 20),
   [0.60822, 1.033333, [10.0, 15.0, 22.5], 1, 'declining']),
  ('regression: high variance decline',
   ([3.0, 0.3, 3.0, 0.3], 100, 5),
   [0.948683, 1.65, [300.0, 90.0, 270.0, 81.0], None, 'declining']),
  ('regression: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, 'declining'])],
 [('regression: boom and bust',
   ([1.5, 0.5, 1.5, 0.5], 100, 20),
   [0.866025, 1.0, [150.0, 75.0, 112.5, 56.25], None, 'declining']),
  ('regression: exact halving to threshold',
   ([0.5, 1.0, 2.0], 100, 50),
   [1.0, 1.166667, [50.0, 50.0, 100.0], None, 'stable']),
  ('control: invalid zero lambda', ([1.0, 0.0], 10, 1), None),
  ('regression: first year crash',
   ([0.1, 1.5, 1.5], 100, 20),
   [0.60822, 1.033333, [10.0, 15.0, 22.5], 1, 'declining']),
  ('regression: high variance decline',
   ([3.0, 0.3, 3.0, 0.3], 100, 5),
   [0.948683, 1.65, [300.0, 90.0, 270.0, 81.0], None, 'declining']),
  ('regression: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, 'declining']),
  ('regression: slow decline',
   ([0.95, 1.02, 0.9, 1.05, 0.93], 80, 60),
   [0.968384, 0.97, [76.0, 77.52, 69.768, 73.2564, 68.1285], None, 'declining'])],
 [('regression: boom and bust',
   ([1.5, 0.5, 1.5, 0.5], 100, 20),
   [0.866025, 1.0, [150.0, 75.0, 112.5, 56.25], None, 'declining']),
  ('regression: exact halving to threshold',
   ([0.5, 1.0, 2.0], 100, 50),
   [1.0, 1.166667, [50.0, 50.0, 100.0], None, 'stable']),
  ('regression: balanced doubling halving',
   ([2.0, 0.5], 100, 10),
   [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('regression: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('control: invalid zero lambda', ([1.0, 0.0], 10, 1), None),
  ('regression: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, 'declining']),
  ('regression: slow decline',
   ([0.95, 1.02, 0.9, 1.05, 0.93], 80, 60),
   [0.968384, 0.97, [76.0, 77.52, 69.768, 73.2564, 68.1285], None, 'declining'])],
 [('regression: exact halving to threshold',
   ([0.5, 1.0, 2.0], 100, 50),
   [1.0, 1.166667, [50.0, 50.0, 100.0], None, 'stable']),
  ('regression: balanced doubling halving',
   ([2.0, 0.5], 100, 10),
   [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('regression: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('regression: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('regression: dip and recovery',
   ([0.4, 0.8, 3.0, 2.0], 100, 50),
   [1.177132, 1.55, [40.0, 32.0, 96.0, 192.0], 1, 'growing']),
  ('control: invalid zero lambda', ([1.0, 0.0], 10, 1), None),
  ('regression: first year crash',
   ([0.1, 1.5, 1.5], 100, 20),
   [0.60822, 1.033333, [10.0, 15.0, 22.5], 1, 'declining'])]]
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: boom and bust[0.866025, 1.0, [150.0, 75.0, 112.5, 56.25], None, 'declining'][0.866025, 1.0, [150.0, 75.0, 112.5, 56.25], None, 'declining']Passed
regression: exact halving to threshold[1.0, 1.166667, [50.0, 50.0, 100.0], None, 'stable'][1.0, 1.166667, [50.0, 50.0, 100.0], None, 'stable']Passed
regression: balanced doubling halving[1.0, 1.25, [200.0, 100.0], None, 'stable'][1.0, 1.25, [200.0, 100.0], None, 'stable']Passed
regression: steady growth[1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing'][1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']Passed
regression: constant[1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable'][1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']Passed
regression: dip and recovery[1.177132, 1.55, [40.0, 32.0, 96.0, 192.0], 1, 'growing'][1.177132, 1.55, [40.0, 32.0, 96.0, 192.0], 1, 'growing']Passed
control: invalid zero lambdaNoneNonePassed

SHA-256 / 45b32b256c690acabeb9f4ee2fb8794da3d750d851df49f3ea62df6ee4a9b0ee

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

Case digest / e9d30886e399454c94788c79b94ffb798782248344e4709c93145db5bc0e111a