broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(k1, k2, a12, a21):
    if min(k1, k2) <= 0 or min(a12, a21) < 0:
        return None
    c1 = k1 * a21 - k2
    c2 = k2 * a12 - k1
    if c1 == 0 and c2 == 0:
        return ['neutral', None]
    if c1 > 0 and c2 < 0:
        return ['species1', [float(k1), 0.0]]
    if c1 < 0 and c2 > 0:
        return ['species2', [0.0, float(k2)]]
    den = 1 - a12 * a21
    n1 = (k1 - a12 * k2) / den
    n2 = (k2 - a21 * k1) / den
    kind = 'coexist' if c1 < 0 else 'founder'
    return [kind, [round(n1, 4), round(n2, 4)]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control: weak competition coexist', (100, 80, 0.5, 0.4), ['coexist', [75.0, 50.0]]),
  ('control: strong asymmetric species1', (100, 60, 0.5, 1.2), ['species1', [100.0, 0.0]]),
  ('control: species2 wins', (50, 120, 1.5, 0.3), ['species2', [0.0, 120.0]]),
  ('control: founder control', (100, 100, 1.5, 1.6), ['founder', [35.7143, 42.8571]]),
  ('regression: neutral tie', (100, 50, 1.0, 0.5), ['neutral', None]),
  ('control: no competition', (70, 40, 0.0, 0.0), ['coexist', [70.0, 40.0]]),
  ('regression: near tie', (100, 99.5, 1.0, 1.0), ['species1', [100.0, 0.0]])],
 [('control: founder control', (100, 100, 1.5, 1.6), ['founder', [35.7143, 42.8571]]),
  ('regression: neutral tie', (100, 50, 1.0, 0.5), ['neutral', None]),
  ('control: no competition', (70, 40, 0.0, 0.0), ['coexist', [70.0, 40.0]]),
  ('control: coexist with one strong coefficient', (200, 60, 1.5, 0.2), ['coexist', [157.1429, 28.5714]]),
  ('control: invalid negative coefficient', (100, 100, -0.1, 0.5), None),
  ('control: invalid capacity', (0, 100, 0.5, 0.5), None),
  ('regression: near tie', (100, 99.5, 1.0, 1.0), ['species1', [100.0, 0.0]])],
 [('control: weak competition coexist', (100, 80, 0.5, 0.4), ['coexist', [75.0, 50.0]]),
  ('regression: neutral tie', (100, 50, 1.0, 0.5), ['neutral', None]),
  ('control: coexist with one strong coefficient', (200, 60, 1.5, 0.2), ['coexist', [157.1429, 28.5714]]),
  ('control: invalid negative coefficient', (100, 100, -0.1, 0.5), None),
  ('control: invalid capacity', (0, 100, 0.5, 0.5), None),
  ('regression: near tie', (100, 99.5, 1.0, 1.0), ['species1', [100.0, 0.0]]),
  ('control: founder asymmetric', (90, 150, 2.0, 2.5), ['founder', [52.5, 18.75]])],
 [('control: weak competition coexist', (100, 80, 0.5, 0.4), ['coexist', [75.0, 50.0]]),
  ('control: strong asymmetric species1', (100, 60, 0.5, 1.2), ['species1', [100.0, 0.0]]),
  ('control: species2 wins', (50, 120, 1.5, 0.3), ['species2', [0.0, 120.0]]),
  ('control: founder control', (100, 100, 1.5, 1.6), ['founder', [35.7143, 42.8571]]),
  ('regression: neutral tie', (100, 50, 1.0, 0.5), ['neutral', None]),
  ('regression: near tie', (100, 99.5, 1.0, 1.0), ['species1', [100.0, 0.0]]),
  ('control: founder asymmetric', (90, 150, 2.0, 2.5), ['founder', [52.5, 18.75]])],
 [('control: strong asymmetric species1', (100, 60, 0.5, 1.2), ['species1', [100.0, 0.0]]),
  ('control: species2 wins', (50, 120, 1.5, 0.3), ['species2', [0.0, 120.0]]),
  ('control: founder control', (100, 100, 1.5, 1.6), ['founder', [35.7143, 42.8571]]),
  ('regression: neutral tie', (100, 50, 1.0, 0.5), ['neutral', None]),
  ('control: no competition', (70, 40, 0.0, 0.0), ['coexist', [70.0, 40.0]]),
  ('control: coexist with one strong coefficient', (200, 60, 1.5, 0.2), ['coexist', [157.1429, 28.5714]]),
  ('regression: near tie', (100, 99.5, 1.0, 1.0), ['species1', [100.0, 0.0]])]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(k1, k2, a12, a21):
    if min(k1, k2) <= 0 or min(a12, a21) < 0:
        return None
    c1 = k1 * a21 - k2
    c2 = k2 * a12 - k1
    if abs(c1) < 1 or abs(c2) < 1:
        return ['neutral', None]
    if c1 > 0 and c2 < 0:
        return ['species1', [float(k1), 0.0]]
    if c1 < 0 and c2 > 0:
        return ['species2', [0.0, float(k2)]]
    den = 1 - a12 * a21
    n1 = (k1 - a12 * k2) / den
    n2 = (k2 - a21 * k1) / den
    kind = 'coexist' if c1 < 0 else 'founder'
    return [kind, [round(n1, 4), round(n2, 4)]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control: weak competition coexist', (100, 80, 0.5, 0.4), ['coexist', [75.0, 50.0]]),
  ('control: strong asymmetric species1', (100, 60, 0.5, 1.2), ['species1', [100.0, 0.0]]),
  ('control: species2 wins', (50, 120, 1.5, 0.3), ['species2', [0.0, 120.0]]),
  ('control: founder control', (100, 100, 1.5, 1.6), ['founder', [35.7143, 42.8571]]),
  ('regression: neutral tie', (100, 50, 1.0, 0.5), ['neutral', None]),
  ('control: no competition', (70, 40, 0.0, 0.0), ['coexist', [70.0, 40.0]]),
  ('regression: near tie', (100, 99.5, 1.0, 1.0), ['species1', [100.0, 0.0]])],
 [('control: founder control', (100, 100, 1.5, 1.6), ['founder', [35.7143, 42.8571]]),
  ('regression: neutral tie', (100, 50, 1.0, 0.5), ['neutral', None]),
  ('control: no competition', (70, 40, 0.0, 0.0), ['coexist', [70.0, 40.0]]),
  ('control: coexist with one strong coefficient', (200, 60, 1.5, 0.2), ['coexist', [157.1429, 28.5714]]),
  ('control: invalid negative coefficient', (100, 100, -0.1, 0.5), None),
  ('control: invalid capacity', (0, 100, 0.5, 0.5), None),
  ('regression: near tie', (100, 99.5, 1.0, 1.0), ['species1', [100.0, 0.0]])],
 [('control: weak competition coexist', (100, 80, 0.5, 0.4), ['coexist', [75.0, 50.0]]),
  ('regression: neutral tie', (100, 50, 1.0, 0.5), ['neutral', None]),
  ('control: coexist with one strong coefficient', (200, 60, 1.5, 0.2), ['coexist', [157.1429, 28.5714]]),
  ('control: invalid negative coefficient', (100, 100, -0.1, 0.5), None),
  ('control: invalid capacity', (0, 100, 0.5, 0.5), None),
  ('regression: near tie', (100, 99.5, 1.0, 1.0), ['species1', [100.0, 0.0]]),
  ('control: founder asymmetric', (90, 150, 2.0, 2.5), ['founder', [52.5, 18.75]])],
 [('control: weak competition coexist', (100, 80, 0.5, 0.4), ['coexist', [75.0, 50.0]]),
  ('control: strong asymmetric species1', (100, 60, 0.5, 1.2), ['species1', [100.0, 0.0]]),
  ('control: species2 wins', (50, 120, 1.5, 0.3), ['species2', [0.0, 120.0]]),
  ('control: founder control', (100, 100, 1.5, 1.6), ['founder', [35.7143, 42.8571]]),
  ('regression: neutral tie', (100, 50, 1.0, 0.5), ['neutral', None]),
  ('regression: near tie', (100, 99.5, 1.0, 1.0), ['species1', [100.0, 0.0]]),
  ('control: founder asymmetric', (90, 150, 2.0, 2.5), ['founder', [52.5, 18.75]])],
 [('control: strong asymmetric species1', (100, 60, 0.5, 1.2), ['species1', [100.0, 0.0]]),
  ('control: species2 wins', (50, 120, 1.5, 0.3), ['species2', [0.0, 120.0]]),
  ('control: founder control', (100, 100, 1.5, 1.6), ['founder', [35.7143, 42.8571]]),
  ('regression: neutral tie', (100, 50, 1.0, 0.5), ['neutral', None]),
  ('control: no competition', (70, 40, 0.0, 0.0), ['coexist', [70.0, 40.0]]),
  ('control: coexist with one strong coefficient', (200, 60, 1.5, 0.2), ['coexist', [157.1429, 28.5714]]),
  ('regression: near tie', (100, 99.5, 1.0, 1.0), ['species1', [100.0, 0.0]])]]
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)

prompt:
A knife-edge isocline tie is reported as founder control or coexistence.

c1=K1*a21-K2, c2=K2*a12-K1; any zero -> neutral; c1>0,c2<0 species1 wins at [K1,0]; c1<0,c2>0 species2 at [0,K2]; otherwise interior N1=(K1-a12K2)/(1-a12a21), N2=(K2-a21K1)/(1-a12a21), coexist if both negative, founder if both positive; None for non-positive K or negative coefficients (zero allowed).

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(k1, k2, a12, a21):
    if min(k1, k2) <= 0 or min(a12, a21) <= 0:
        return None
    c1 = k1 * a21 - k2
    c2 = k2 * a12 - k1
    if c1 == 0 or c2 == 0:
        return ['neutral', None]
    if c1 > 0 and c2 < 0:
        return ['species1', [float(k1), 0.0]]
    if c1 < 0 and c2 > 0:
        return ['species2', [0.0, float(k2)]]
    den = 1 - a12 * a21
    n1 = (k1 - a12 * k2) / den
    n2 = (k2 - a21 * k1) / den
    kind = 'coexist' if c1 < 0 else 'founder'
    return [kind, [round(n1, 4), round(n2, 4)]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control: weak competition coexist', (100, 80, 0.5, 0.4), ['coexist', [75.0, 50.0]]),
  ('regression: strong asymmetric species1', (100, 60, 0.5, 1.2), ['species1', [100.0, 0.0]]),
  ('regression: species2 wins', (50, 120, 1.5, 0.3), ['species2', [0.0, 120.0]]),
  ('regression: founder control', (100, 100, 1.5, 1.6), ['founder', [35.7143, 42.8571]]),
  ('control: neutral tie', (100, 50, 1.0, 0.5), ['neutral', None]),
  ('regression: no competition', (70, 40, 0.0, 0.0), ['coexist', [70.0, 40.0]]),
  ('control: invalid negative coefficient', (100, 100, -0.1, 0.5), None)],
 [('regression: founder control', (100, 100, 1.5, 1.6), ['founder', [35.7143, 42.8571]]),
  ('control: neutral tie', (100, 50, 1.0, 0.5), ['neutral', None]),
  ('regression: no competition', (70, 40, 0.0, 0.0), ['coexist', [70.0, 40.0]]),
  ('regression: coexist with one strong coefficient', (200, 60, 1.5, 0.2), ['coexist', [157.1429, 28.5714]]),
  ('control: invalid negative coefficient', (100, 100, -0.1, 0.5), None),
  ('control: invalid capacity', (0, 100, 0.5, 0.5), None),
  ('control: near tie', (100, 99.5, 1.0, 1.0), ['species1', [100.0, 0.0]])],
 [('control: weak competition coexist', (100, 80, 0.5, 0.4), ['coexist', [75.0, 50.0]]),
  ('regression: no competition', (70, 40, 0.0, 0.0), ['coexist', [70.0, 40.0]]),
  ('regression: coexist with one strong coefficient', (200, 60, 1.5, 0.2), ['coexist', [157.1429, 28.5714]]),
  ('control: invalid negative coefficient', (100, 100, -0.1, 0.5), None),
  ('control: invalid capacity', (0, 100, 0.5, 0.5), None),
  ('control: near tie', (100, 99.5, 1.0, 1.0), ['species1', [100.0, 0.0]]),
  ('regression: founder asymmetric', (90, 150, 2.0, 2.5), ['founder', [52.5, 18.75]])],
 [('control: weak competition coexist', (100, 80, 0.5, 0.4), ['coexist', [75.0, 50.0]]),
  ('regression: strong asymmetric species1', (100, 60, 0.5, 1.2), ['species1', [100.0, 0.0]]),
  ('regression: species2 wins', (50, 120, 1.5, 0.3), ['species2', [0.0, 120.0]]),
  ('control: neutral tie', (100, 50, 1.0, 0.5), ['neutral', None]),
  ('regression: no competition', (70, 40, 0.0, 0.0), ['coexist', [70.0, 40.0]]),
  ('control: near tie', (100, 99.5, 1.0, 1.0), ['species1', [100.0, 0.0]]),
  ('regression: founder asymmetric', (90, 150, 2.0, 2.5), ['founder', [52.5, 18.75]])],
 [('regression: strong asymmetric species1', (100, 60, 0.5, 1.2), ['species1', [100.0, 0.0]]),
  ('regression: species2 wins', (50, 120, 1.5, 0.3), ['species2', [0.0, 120.0]]),
  ('regression: founder control', (100, 100, 1.5, 1.6), ['founder', [35.7143, 42.8571]]),
  ('control: neutral tie', (100, 50, 1.0, 0.5), ['neutral', None]),
  ('regression: no competition', (70, 40, 0.0, 0.0), ['coexist', [70.0, 40.0]]),
  ('control: invalid negative coefficient', (100, 100, -0.1, 0.5), None),
  ('control: invalid capacity', (0, 100, 0.5, 0.5), 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)

meaning: Fixture-count band, not measured model difficulty

deps: stdlib

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(k1, k2, a12, a21):
    if min(k1, k2) <= 0 or min(a12, a21) < 0 or max(a12, a21) > 1:
        return None
    c1 = k1 * a21 - k2
    c2 = k2 * a12 - k1
    if c1 == 0 or c2 == 0:
        return ['neutral', None]
    if c1 > 0 and c2 < 0:
        return ['species1', [float(k1), 0.0]]
    if c1 < 0 and c2 > 0:
        return ['species2', [0.0, float(k2)]]
    den = 1 - a12 * a21
    n1 = (k1 - a12 * k2) / den
    n2 = (k2 - a21 * k1) / den
    kind = 'coexist' if c1 < 0 else 'founder'
    return [kind, [round(n1, 4), round(n2, 4)]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control: weak competition coexist', (100, 80, 0.5, 0.4), ['coexist', [75.0, 50.0]]),
  ('regression: strong asymmetric species1', (100, 60, 0.5, 1.2), ['species1', [100.0, 0.0]]),
  ('regression: species2 wins', (50, 120, 1.5, 0.3), ['species2', [0.0, 120.0]]),
  ('regression: founder control', (100, 100, 1.5, 1.6), ['founder', [35.7143, 42.8571]]),
  ('control: neutral tie', (100, 50, 1.0, 0.5), ['neutral', None]),
  ('regression: no competition', (70, 40, 0.0, 0.0), ['coexist', [70.0, 40.0]]),
  ('control: invalid negative coefficient', (100, 100, -0.1, 0.5), None)],
 [('regression: founder control', (100, 100, 1.5, 1.6), ['founder', [35.7143, 42.8571]]),
  ('control: neutral tie', (100, 50, 1.0, 0.5), ['neutral', None]),
  ('regression: no competition', (70, 40, 0.0, 0.0), ['coexist', [70.0, 40.0]]),
  ('regression: coexist with one strong coefficient', (200, 60, 1.5, 0.2), ['coexist', [157.1429, 28.5714]]),
  ('control: invalid negative coefficient', (100, 100, -0.1, 0.5), None),
  ('control: invalid capacity', (0, 100, 0.5, 0.5), None),
  ('control: near tie', (100, 99.5, 1.0, 1.0), ['species1', [100.0, 0.0]])],
 [('control: weak competition coexist', (100, 80, 0.5, 0.4), ['coexist', [75.0, 50.0]]),
  ('regression: no competition', (70, 40, 0.0, 0.0), ['coexist', [70.0, 40.0]]),
  ('regression: coexist with one strong coefficient', (200, 60, 1.5, 0.2), ['coexist', [157.1429, 28.5714]]),
  ('control: invalid negative coefficient', (100, 100, -0.1, 0.5), None),
  ('control: invalid capacity', (0, 100, 0.5, 0.5), None),
  ('control: near tie', (100, 99.5, 1.0, 1.0), ['species1', [100.0, 0.0]]),
  ('regression: founder asymmetric', (90, 150, 2.0, 2.5), ['founder', [52.5, 18.75]])],
 [('control: weak competition coexist', (100, 80, 0.5, 0.4), ['coexist', [75.0, 50.0]]),
  ('regression: strong asymmetric species1', (100, 60, 0.5, 1.2), ['species1', [100.0, 0.0]]),
  ('regression: species2 wins', (50, 120, 1.5, 0.3), ['species2', [0.0, 120.0]]),
  ('control: neutral tie', (100, 50, 1.0, 0.5), ['neutral', None]),
  ('regression: no competition', (70, 40, 0.0, 0.0), ['coexist', [70.0, 40.0]]),
  ('control: near tie', (100, 99.5, 1.0, 1.0), ['species1', [100.0, 0.0]]),
  ('regression: founder asymmetric', (90, 150, 2.0, 2.5), ['founder', [52.5, 18.75]])],
 [('regression: strong asymmetric species1', (100, 60, 0.5, 1.2), ['species1', [100.0, 0.0]]),
  ('regression: species2 wins', (50, 120, 1.5, 0.3), ['species2', [0.0, 120.0]]),
  ('regression: founder control', (100, 100, 1.5, 1.6), ['founder', [35.7143, 42.8571]]),
  ('control: neutral tie', (100, 50, 1.0, 0.5), ['neutral', None]),
  ('regression: no competition', (70, 40, 0.0, 0.0), ['coexist', [70.0, 40.0]]),
  ('control: invalid negative coefficient', (100, 100, -0.1, 0.5), None),
  ('control: invalid capacity', (0, 100, 0.5, 0.5), 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)

prompt:
Species that do not compete at all are rejected as invalid input.

c1=K1*a21-K2, c2=K2*a12-K1; any zero -> neutral; c1>0,c2<0 species1 wins at [K1,0]; c1<0,c2>0 species2 at [0,K2]; otherwise interior N1=(K1-a12K2)/(1-a12a21), N2=(K2-a21K1)/(1-a12a21), coexist if both negative, founder if both positive; None for non-positive K or negative coefficients (zero allowed).

split: open-access


broken_source:
"""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 / 2
    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)

source:
"""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 / q
    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)

prompt:
MSY is double the surplus production possible at half capacity.

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.

split: open-access


broken_source:
"""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)

source:
"""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)

prompt:
Effort reference points ignore gear catchability.

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.

split: open-access


source:
"""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 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']),
  ('control: 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']),
  ('control: 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: collapse effort', (0.2, 3000, 300, 0.001), [150.0, 1500.0, 100.0, 0.0, 0.0, 'overfished']),
  ('control: no fishing', (0.6, 800, 0, 0.002), [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable']),
  ('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']),
  ('control: 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']),
  ('control: 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)

prompt:
Excessive effort yields negative biomass and negative catch.

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.

split: open-access


broken_source:
"""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 = 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']),
  ('control: 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']),
  ('control: 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']),
  ('control: no fishing', (0.6, 800, 0, 0.002), [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable']),
  ('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']),
  ('control: 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']),
  ('control: 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)

source:
"""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 * k
    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']),
  ('control: 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']),
  ('control: 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']),
  ('control: no fishing', (0.6, 800, 0, 0.002), [120.0, 400.0, 150.0, 800.0, 0.0, 'sustainable']),
  ('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']),
  ('control: 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']),
  ('control: 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)

prompt:
Yields are inflated by a factor 1/q.

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.

split: open-access


prompt:
Fishing exactly at E_msy is labelled overfished.

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.

split: open-access


prompt:
Destroyed patches are still colonised.

Occupancy p: p += c*p*(1-D-p) - e*p each year, clamped to [0, 1-D]; equilibrium max(0, 1-D-e/c); return [equilibrium rounded 6, trajectory rounded 6]; None for c<=0, e<0 or D outside [0,1).

split: open-access


prompt:
Equilibrium occupancy ignores habitat destruction.

Occupancy p: p += c*p*(1-D-p) - e*p each year, clamped to [0, 1-D]; equilibrium max(0, 1-D-e/c); return [equilibrium rounded 6, trajectory rounded 6]; None for c<=0, e<0 or D outside [0,1).

split: open-access


prompt:
Equilibrium occupancy falls as colonisation improves.

Occupancy p: p += c*p*(1-D-p) - e*p each year, clamped to [0, 1-D]; equilibrium max(0, 1-D-e/c); return [equilibrium rounded 6, trajectory rounded 6]; None for c<=0, e<0 or D outside [0,1).

split: open-access


prompt:
Occupancy exceeds the fraction of habitat that still exists.

Occupancy p: p += c*p*(1-D-p) - e*p each year, clamped to [0, 1-D]; equilibrium max(0, 1-D-e/c); return [equilibrium rounded 6, trajectory rounded 6]; None for c<=0, e<0 or D outside [0,1).

split: open-access


prompt:
Extinctions happen in empty patches.

Occupancy p: p += c*p*(1-D-p) - e*p each year, clamped to [0, 1-D]; equilibrium max(0, 1-D-e/c); return [equilibrium rounded 6, trajectory rounded 6]; None for c<=0, e<0 or D outside [0,1).

split: open-access


prompt:
Survivors ignore natural mortality and catches are overstated.

Z_a = F_a + M; catch_a = F_a/Z_a*N_a*(1-exp(-Z_a)) (0 when Z=0); survivors N_a*exp(-Z_a) age one year; the last class is a plus group; next year starts with recruits at age 0; return [catch rounded 3, next vector rounded 3, total catch rounded 3]; at least two age classes.

split: open-access


prompt:
Catch ignores fish that die naturally before they can be caught.

Z_a = F_a + M; catch_a = F_a/Z_a*N_a*(1-exp(-Z_a)) (0 when Z=0); survivors N_a*exp(-Z_a) age one year; the last class is a plus group; next year starts with recruits at age 0; return [catch rounded 3, next vector rounded 3, total catch rounded 3]; at least two age classes.

split: open-access


prompt:
Old fish disappear from the stock after one year in the oldest class.

Z_a = F_a + M; catch_a = F_a/Z_a*N_a*(1-exp(-Z_a)) (0 when Z=0); survivors N_a*exp(-Z_a) age one year; the last class is a plus group; next year starts with recruits at age 0; return [catch rounded 3, next vector rounded 3, total catch rounded 3]; at least two age classes.

split: open-access


prompt:
High mortality produces negative numbers at age.

Z_a = F_a + M; catch_a = F_a/Z_a*N_a*(1-exp(-Z_a)) (0 when Z=0); survivors N_a*exp(-Z_a) age one year; the last class is a plus group; next year starts with recruits at age 0; return [catch rounded 3, next vector rounded 3, total catch rounded 3]; at least two age classes.

split: open-access


prompt:
Parasitoid emergence is computed from next generation's hosts.

Escape fraction exp(-a*P); H' = lam*H*escape and P' = c*H*(1-escape) computed from the same generation; equilibrium [lam*ln(lam)/((lam-1)*a*c), ln(lam)/a] rounded 4 when lam>1, a>0, c>0 else None; return [equilibrium, trajectory of [H,P] rounded 4].

split: open-access


prompt:
Hosts escape too often at moderate parasitoid densities.

Escape fraction exp(-a*P); H' = lam*H*escape and P' = c*H*(1-escape) computed from the same generation; equilibrium [lam*ln(lam)/((lam-1)*a*c), ln(lam)/a] rounded 4 when lam>1, a>0, c>0 else None; return [equilibrium, trajectory of [H,P] rounded 4].

split: open-access


prompt:
Parasitoids emerge from hosts that escaped attack.

Escape fraction exp(-a*P); H' = lam*H*escape and P' = c*H*(1-escape) computed from the same generation; equilibrium [lam*ln(lam)/((lam-1)*a*c), ln(lam)/a] rounded 4 when lam>1, a>0, c>0 else None; return [equilibrium, trajectory of [H,P] rounded 4].

split: open-access


prompt:
The host equilibrium is understated by a factor lam.

Escape fraction exp(-a*P); H' = lam*H*escape and P' = c*H*(1-escape) computed from the same generation; equilibrium [lam*ln(lam)/((lam-1)*a*c), ln(lam)/a] rounded 4 when lam>1, a>0, c>0 else None; return [equilibrium, trajectory of [H,P] rounded 4].

split: open-access


prompt:
Parasitoid equilibrium grows linearly with host fecundity.

Escape fraction exp(-a*P); H' = lam*H*escape and P' = c*H*(1-escape) computed from the same generation; equilibrium [lam*ln(lam)/((lam-1)*a*c), ln(lam)/a] rounded 4 when lam>1, a>0, c>0 else None; return [equilibrium, trajectory of [H,P] rounded 4].

split: open-access


prompt:
Heat waves add degree-days above the developmental ceiling.

Daily max is capped at upper; daily min is raised to base and capped at upper; DD = max(0, mean - base); emergence day is the first 1-based day with cumulative DD >= target; return [cumulative rounded 2, day or None]; None when upper <= base.

split: open-access


prompt:
Cold nights subtract development accumulated during the day.

Daily max is capped at upper; daily min is raised to base and capped at upper; DD = max(0, mean - base); emergence day is the first 1-based day with cumulative DD >= target; return [cumulative rounded 2, day or None]; None when upper <= base.

split: open-access


prompt:
Cool days reduce the cumulative total.

Daily max is capped at upper; daily min is raised to base and capped at upper; DD = max(0, mean - base); emergence day is the first 1-based day with cumulative DD >= target; return [cumulative rounded 2, day or None]; None when upper <= base.

split: open-access


prompt:
Emergence is predicted one day late when the target is hit exactly.

Daily max is capped at upper; daily min is raised to base and capped at upper; DD = max(0, mean - base); emergence day is the first 1-based day with cumulative DD >= target; return [cumulative rounded 2, day or None]; None when upper <= base.

split: open-access


prompt:
Emergence days are reported zero-based.

Daily max is capped at upper; daily min is raised to base and capped at upper; DD = max(0, mean - base); emergence day is the first 1-based day with cumulative DD >= target; return [cumulative rounded 2, day or None]; None when upper <= base.

split: open-access


broken_source:
"""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 arith < 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']),
  ('control: 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: balanced doubling halving', ([2.0, 0.5], 100, 10), [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('control: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('control: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('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'])],
 [('control: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('control: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('control: 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']),
  ('control: 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']),
  ('control: 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']),
  ('control: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, 'declining']),
  ('control: 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']),
  ('control: 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: balanced doubling halving', ([2.0, 0.5], 100, 10), [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('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']),
  ('control: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, 'declining']),
  ('control: 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'])],
 [('control: 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: balanced doubling halving', ([2.0, 0.5], 100, 10), [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('control: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('control: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('control: 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']),
  ('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'])]]
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)

source:
"""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 + arith) / 2 < 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']),
  ('control: 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: balanced doubling halving', ([2.0, 0.5], 100, 10), [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('control: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('control: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('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'])],
 [('control: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('control: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('control: 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']),
  ('control: 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']),
  ('control: 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']),
  ('control: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, 'declining']),
  ('control: 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']),
  ('control: 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: balanced doubling halving', ([2.0, 0.5], 100, 10), [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('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']),
  ('control: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, 'declining']),
  ('control: 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'])],
 [('control: 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: balanced doubling halving', ([2.0, 0.5], 100, 10), [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('control: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('control: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('control: 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']),
  ('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'])]]
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)

prompt:
Boom-and-bust populations with declining long-run size are labelled stable or growing.

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.

split: open-access


broken_source:
"""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)

source:
"""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)

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

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.

split: open-access


broken_source:
"""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 = [[('control: 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: balanced doubling halving', ([2.0, 0.5], 100, 10), [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('control: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('control: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('control: 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']),
  ('regression: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, '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: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('control: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('control: 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),
  ('control: first year crash',
   ([0.1, 1.5, 1.5], 100, 20),
   [0.60822, 1.033333, [10.0, 15.0, 22.5], 1, 'declining']),
  ('regression: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, 'declining'])],
 [('control: 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),
  ('control: first year crash',
   ([0.1, 1.5, 1.5], 100, 20),
   [0.60822, 1.033333, [10.0, 15.0, 22.5], 1, 'declining']),
  ('control: 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']),
  ('control: 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'])],
 [('control: 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: balanced doubling halving', ([2.0, 0.5], 100, 10), [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('control: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('control: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('regression: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, 'declining']),
  ('control: 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']),
  ('control: balanced doubling halving', ([2.0, 0.5], 100, 10), [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('control: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('control: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('control: 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: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 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)

source:
"""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 round(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 = [[('control: 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: balanced doubling halving', ([2.0, 0.5], 100, 10), [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('control: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('control: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('control: 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']),
  ('regression: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, '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: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('control: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('control: 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),
  ('control: first year crash',
   ([0.1, 1.5, 1.5], 100, 20),
   [0.60822, 1.033333, [10.0, 15.0, 22.5], 1, 'declining']),
  ('regression: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, 'declining'])],
 [('control: 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),
  ('control: first year crash',
   ([0.1, 1.5, 1.5], 100, 20),
   [0.60822, 1.033333, [10.0, 15.0, 22.5], 1, 'declining']),
  ('control: 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']),
  ('control: 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'])],
 [('control: 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: balanced doubling halving', ([2.0, 0.5], 100, 10), [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('control: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('control: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('regression: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 1, 'declining']),
  ('control: 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']),
  ('control: balanced doubling halving', ([2.0, 0.5], 100, 10), [1.0, 1.25, [200.0, 100.0], None, 'stable']),
  ('control: steady growth',
   ([1.1, 1.2, 1.05], 50, 10),
   [1.114947, 1.116667, [55.0, 66.0, 69.3], None, 'growing']),
  ('control: constant', ([1.0, 1.0, 1.0], 30, 5), [1.0, 1.0, [30.0, 30.0, 30.0], None, 'stable']),
  ('control: 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: fractional dip', ([0.496, 1.2], 100, 50), [0.771492, 0.848, [49.6, 59.52], 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)

prompt:
Populations exactly at the threshold are counted as quasi-extinct.

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.

split: open-access