FAILURE MAP
← Case archive

FA-65656 / Ecological population dynamics / Open access

Insect degree-day accumulation with horizontal cutoff: negative day floor · case 01

Cool days reduce the cumulative total.

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

ROOT CAUSE

Daily degree-days are not floored at zero.

VERIFIED REPAIR

Restore the negative day floor rule: `dd = max(0.0, (hi_c + lo_c) / 2 - base)`.

Unsuccessful approach: Taking the absolute value credits cold days with development.

Case contract

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.

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(tmins, tmaxs, base, upper, target):
    if upper <= base:
        return None
    total = 0.0
    cum = []
    day_hit = None
    for d, (lo, hi) in enumerate(zip(tmins, tmaxs), start=1):
        hi_c = min(hi, upper)
        lo_c = min(max(lo, base), upper)
        dd = (hi_c + lo_c) / 2 - base
        total += dd
        cum.append(round(total, 2))
        if day_hit is None and total >= target:
            day_hit = d
    return [cum, day_hit]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control: spring warming codling moth',
   ([4, 6, 8, 10, 12, 14], [15, 18, 20, 24, 26, 30], 10, 31, 20),
   [[2.5, 6.5, 11.5, 18.5, 27.5, 39.5], 5]),
  ('control: hot spell above cutoff', ([20, 22, 25], [34, 38, 40], 10, 30, 30), [[15.0, 31.0, 48.5], 2]),
  ('regression: cold days below base', ([-2, 0, 3], [5, 8, 9], 10, 30, 1), [[0.0, 0.0, 0.0], None]),
  ('control: exact target', ([10, 10, 10], [20, 20, 20], 10, 30, 10), [[5.0, 10.0, 15.0], 2]),
  ('control: never emerges', ([5, 6], [12, 13], 10, 30, 50), [[1.0, 2.5], None]),
  ('control: invalid thresholds', ([5], [15], 20, 20, 5), None),
  ('regression: frost then warm',
   ([-5, 2, 11, 14], [6, 16, 25, 29], 10, 30, 15),
   [[0.0, 3.0, 11.0, 22.5], 4])],
 [('regression: cold days below base', ([-2, 0, 3], [5, 8, 9], 10, 30, 1), [[0.0, 0.0, 0.0], None]),
  ('control: exact target', ([10, 10, 10], [20, 20, 20], 10, 30, 10), [[5.0, 10.0, 15.0], 2]),
  ('control: never emerges', ([5, 6], [12, 13], 10, 30, 50), [[1.0, 2.5], None]),
  ('control: invalid thresholds', ([5], [15], 20, 20, 5), None),
  ('control: warm nights', ([18, 19, 21, 22], [28, 29, 33, 35], 12, 32, 40), [[11.0, 23.0, 37.5, 52.5], 4]),
  ('control: no days', ([], [], 10, 30, 5), [[], None]),
  ('regression: frost then warm',
   ([-5, 2, 11, 14], [6, 16, 25, 29], 10, 30, 15),
   [[0.0, 3.0, 11.0, 22.5], 4])],
 [('control: spring warming codling moth',
   ([4, 6, 8, 10, 12, 14], [15, 18, 20, 24, 26, 30], 10, 31, 20),
   [[2.5, 6.5, 11.5, 18.5, 27.5, 39.5], 5]),
  ('control: hot spell above cutoff', ([20, 22, 25], [34, 38, 40], 10, 30, 30), [[15.0, 31.0, 48.5], 2]),
  ('regression: cold days below base', ([-2, 0, 3], [5, 8, 9], 10, 30, 1), [[0.0, 0.0, 0.0], None]),
  ('control: warm nights', ([18, 19, 21, 22], [28, 29, 33, 35], 12, 32, 40), [[11.0, 23.0, 37.5, 52.5], 4]),
  ('control: no days', ([], [], 10, 30, 5), [[], None]),
  ('control: near-miss rounding', ([10, 10], [29.2, 10], 10, 30, 10), [[9.6, 9.6], None]),
  ('regression: frost then warm',
   ([-5, 2, 11, 14], [6, 16, 25, 29], 10, 30, 15),
   [[0.0, 3.0, 11.0, 22.5], 4])],
 [('control: spring warming codling moth',
   ([4, 6, 8, 10, 12, 14], [15, 18, 20, 24, 26, 30], 10, 31, 20),
   [[2.5, 6.5, 11.5, 18.5, 27.5, 39.5], 5]),
  ('control: hot spell above cutoff', ([20, 22, 25], [34, 38, 40], 10, 30, 30), [[15.0, 31.0, 48.5], 2]),
  ('regression: cold days below base', ([-2, 0, 3], [5, 8, 9], 10, 30, 1), [[0.0, 0.0, 0.0], None]),
  ('control: exact target', ([10, 10, 10], [20, 20, 20], 10, 30, 10), [[5.0, 10.0, 15.0], 2]),
  ('control: never emerges', ([5, 6], [12, 13], 10, 30, 50), [[1.0, 2.5], None]),
  ('control: invalid thresholds', ([5], [15], 20, 20, 5), None),
  ('regression: frost then warm',
   ([-5, 2, 11, 14], [6, 16, 25, 29], 10, 30, 15),
   [[0.0, 3.0, 11.0, 22.5], 4])],
 [('regression: cold days below base', ([-2, 0, 3], [5, 8, 9], 10, 30, 1), [[0.0, 0.0, 0.0], None]),
  ('control: exact target', ([10, 10, 10], [20, 20, 20], 10, 30, 10), [[5.0, 10.0, 15.0], 2]),
  ('control: never emerges', ([5, 6], [12, 13], 10, 30, 50), [[1.0, 2.5], None]),
  ('control: invalid thresholds', ([5], [15], 20, 20, 5), None),
  ('control: warm nights', ([18, 19, 21, 22], [28, 29, 33, 35], 12, 32, 40), [[11.0, 23.0, 37.5, 52.5], 4]),
  ('control: no days', ([], [], 10, 30, 5), [[], None]),
  ('regression: frost then warm',
   ([-5, 2, 11, 14], [6, 16, 25, 29], 10, 30, 15),
   [[0.0, 3.0, 11.0, 22.5], 4])]]
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
control: spring warming codling moth[[2.5, 6.5, 11.5, 18.5, 27.5, 39.5], 5][[2.5, 6.5, 11.5, 18.5, 27.5, 39.5], 5]Passed
control: hot spell above cutoff[[15.0, 31.0, 48.5], 2][[15.0, 31.0, 48.5], 2]Passed
regression: cold days below base[[-2.5, -3.5, -4.0], None][[0.0, 0.0, 0.0], None]Failed
control: exact target[[5.0, 10.0, 15.0], 2][[5.0, 10.0, 15.0], 2]Passed
control: never emerges[[1.0, 2.5], None][[1.0, 2.5], None]Passed
control: invalid thresholdsNoneNonePassed
regression: frost then warm[[-2.0, 1.0, 9.0, 20.5], 4][[0.0, 3.0, 11.0, 22.5], 4]Failed

SHA-256 / 809b9fb4dc36c81b9896db4db33e49e0d382b7ef66e61d6626b346d949ded85f

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(tmins, tmaxs, base, upper, target):
    if upper <= base:
        return None
    total = 0.0
    cum = []
    day_hit = None
    for d, (lo, hi) in enumerate(zip(tmins, tmaxs), start=1):
        hi_c = min(hi, upper)
        lo_c = min(max(lo, base), upper)
        dd = abs((hi_c + lo_c) / 2 - base)
        total += dd
        cum.append(round(total, 2))
        if day_hit is None and total >= target:
            day_hit = d
    return [cum, day_hit]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control: spring warming codling moth',
   ([4, 6, 8, 10, 12, 14], [15, 18, 20, 24, 26, 30], 10, 31, 20),
   [[2.5, 6.5, 11.5, 18.5, 27.5, 39.5], 5]),
  ('control: hot spell above cutoff', ([20, 22, 25], [34, 38, 40], 10, 30, 30), [[15.0, 31.0, 48.5], 2]),
  ('regression: cold days below base', ([-2, 0, 3], [5, 8, 9], 10, 30, 1), [[0.0, 0.0, 0.0], None]),
  ('control: exact target', ([10, 10, 10], [20, 20, 20], 10, 30, 10), [[5.0, 10.0, 15.0], 2]),
  ('control: never emerges', ([5, 6], [12, 13], 10, 30, 50), [[1.0, 2.5], None]),
  ('control: invalid thresholds', ([5], [15], 20, 20, 5), None),
  ('regression: frost then warm',
   ([-5, 2, 11, 14], [6, 16, 25, 29], 10, 30, 15),
   [[0.0, 3.0, 11.0, 22.5], 4])],
 [('regression: cold days below base', ([-2, 0, 3], [5, 8, 9], 10, 30, 1), [[0.0, 0.0, 0.0], None]),
  ('control: exact target', ([10, 10, 10], [20, 20, 20], 10, 30, 10), [[5.0, 10.0, 15.0], 2]),
  ('control: never emerges', ([5, 6], [12, 13], 10, 30, 50), [[1.0, 2.5], None]),
  ('control: invalid thresholds', ([5], [15], 20, 20, 5), None),
  ('control: warm nights', ([18, 19, 21, 22], [28, 29, 33, 35], 12, 32, 40), [[11.0, 23.0, 37.5, 52.5], 4]),
  ('control: no days', ([], [], 10, 30, 5), [[], None]),
  ('regression: frost then warm',
   ([-5, 2, 11, 14], [6, 16, 25, 29], 10, 30, 15),
   [[0.0, 3.0, 11.0, 22.5], 4])],
 [('control: spring warming codling moth',
   ([4, 6, 8, 10, 12, 14], [15, 18, 20, 24, 26, 30], 10, 31, 20),
   [[2.5, 6.5, 11.5, 18.5, 27.5, 39.5], 5]),
  ('control: hot spell above cutoff', ([20, 22, 25], [34, 38, 40], 10, 30, 30), [[15.0, 31.0, 48.5], 2]),
  ('regression: cold days below base', ([-2, 0, 3], [5, 8, 9], 10, 30, 1), [[0.0, 0.0, 0.0], None]),
  ('control: warm nights', ([18, 19, 21, 22], [28, 29, 33, 35], 12, 32, 40), [[11.0, 23.0, 37.5, 52.5], 4]),
  ('control: no days', ([], [], 10, 30, 5), [[], None]),
  ('control: near-miss rounding', ([10, 10], [29.2, 10], 10, 30, 10), [[9.6, 9.6], None]),
  ('regression: frost then warm',
   ([-5, 2, 11, 14], [6, 16, 25, 29], 10, 30, 15),
   [[0.0, 3.0, 11.0, 22.5], 4])],
 [('control: spring warming codling moth',
   ([4, 6, 8, 10, 12, 14], [15, 18, 20, 24, 26, 30], 10, 31, 20),
   [[2.5, 6.5, 11.5, 18.5, 27.5, 39.5], 5]),
  ('control: hot spell above cutoff', ([20, 22, 25], [34, 38, 40], 10, 30, 30), [[15.0, 31.0, 48.5], 2]),
  ('regression: cold days below base', ([-2, 0, 3], [5, 8, 9], 10, 30, 1), [[0.0, 0.0, 0.0], None]),
  ('control: exact target', ([10, 10, 10], [20, 20, 20], 10, 30, 10), [[5.0, 10.0, 15.0], 2]),
  ('control: never emerges', ([5, 6], [12, 13], 10, 30, 50), [[1.0, 2.5], None]),
  ('control: invalid thresholds', ([5], [15], 20, 20, 5), None),
  ('regression: frost then warm',
   ([-5, 2, 11, 14], [6, 16, 25, 29], 10, 30, 15),
   [[0.0, 3.0, 11.0, 22.5], 4])],
 [('regression: cold days below base', ([-2, 0, 3], [5, 8, 9], 10, 30, 1), [[0.0, 0.0, 0.0], None]),
  ('control: exact target', ([10, 10, 10], [20, 20, 20], 10, 30, 10), [[5.0, 10.0, 15.0], 2]),
  ('control: never emerges', ([5, 6], [12, 13], 10, 30, 50), [[1.0, 2.5], None]),
  ('control: invalid thresholds', ([5], [15], 20, 20, 5), None),
  ('control: warm nights', ([18, 19, 21, 22], [28, 29, 33, 35], 12, 32, 40), [[11.0, 23.0, 37.5, 52.5], 4]),
  ('control: no days', ([], [], 10, 30, 5), [[], None]),
  ('regression: frost then warm',
   ([-5, 2, 11, 14], [6, 16, 25, 29], 10, 30, 15),
   [[0.0, 3.0, 11.0, 22.5], 4])]]
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
control: spring warming codling moth[[2.5, 6.5, 11.5, 18.5, 27.5, 39.5], 5][[2.5, 6.5, 11.5, 18.5, 27.5, 39.5], 5]Passed
control: hot spell above cutoff[[15.0, 31.0, 48.5], 2][[15.0, 31.0, 48.5], 2]Passed
regression: cold days below base[[2.5, 3.5, 4.0], 1][[0.0, 0.0, 0.0], None]Failed
control: exact target[[5.0, 10.0, 15.0], 2][[5.0, 10.0, 15.0], 2]Passed
control: never emerges[[1.0, 2.5], None][[1.0, 2.5], None]Passed
control: invalid thresholdsNoneNonePassed
regression: frost then warm[[2.0, 5.0, 13.0, 24.5], 4][[0.0, 3.0, 11.0, 22.5], 4]Failed

SHA-256 / 64f6e867a7ff7bf50fcc38bbe42d7f2d97257b1dd34e1986c1d5d7ba35e5417d

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(tmins, tmaxs, base, upper, target):
    if upper <= base:
        return None
    total = 0.0
    cum = []
    day_hit = None
    for d, (lo, hi) in enumerate(zip(tmins, tmaxs), start=1):
        hi_c = min(hi, upper)
        lo_c = min(max(lo, base), upper)
        dd = max(0.0, (hi_c + lo_c) / 2 - base)
        total += dd
        cum.append(round(total, 2))
        if day_hit is None and total >= target:
            day_hit = d
    return [cum, day_hit]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control: spring warming codling moth',
   ([4, 6, 8, 10, 12, 14], [15, 18, 20, 24, 26, 30], 10, 31, 20),
   [[2.5, 6.5, 11.5, 18.5, 27.5, 39.5], 5]),
  ('control: hot spell above cutoff', ([20, 22, 25], [34, 38, 40], 10, 30, 30), [[15.0, 31.0, 48.5], 2]),
  ('regression: cold days below base', ([-2, 0, 3], [5, 8, 9], 10, 30, 1), [[0.0, 0.0, 0.0], None]),
  ('control: exact target', ([10, 10, 10], [20, 20, 20], 10, 30, 10), [[5.0, 10.0, 15.0], 2]),
  ('control: never emerges', ([5, 6], [12, 13], 10, 30, 50), [[1.0, 2.5], None]),
  ('control: invalid thresholds', ([5], [15], 20, 20, 5), None),
  ('regression: frost then warm',
   ([-5, 2, 11, 14], [6, 16, 25, 29], 10, 30, 15),
   [[0.0, 3.0, 11.0, 22.5], 4])],
 [('regression: cold days below base', ([-2, 0, 3], [5, 8, 9], 10, 30, 1), [[0.0, 0.0, 0.0], None]),
  ('control: exact target', ([10, 10, 10], [20, 20, 20], 10, 30, 10), [[5.0, 10.0, 15.0], 2]),
  ('control: never emerges', ([5, 6], [12, 13], 10, 30, 50), [[1.0, 2.5], None]),
  ('control: invalid thresholds', ([5], [15], 20, 20, 5), None),
  ('control: warm nights', ([18, 19, 21, 22], [28, 29, 33, 35], 12, 32, 40), [[11.0, 23.0, 37.5, 52.5], 4]),
  ('control: no days', ([], [], 10, 30, 5), [[], None]),
  ('regression: frost then warm',
   ([-5, 2, 11, 14], [6, 16, 25, 29], 10, 30, 15),
   [[0.0, 3.0, 11.0, 22.5], 4])],
 [('control: spring warming codling moth',
   ([4, 6, 8, 10, 12, 14], [15, 18, 20, 24, 26, 30], 10, 31, 20),
   [[2.5, 6.5, 11.5, 18.5, 27.5, 39.5], 5]),
  ('control: hot spell above cutoff', ([20, 22, 25], [34, 38, 40], 10, 30, 30), [[15.0, 31.0, 48.5], 2]),
  ('regression: cold days below base', ([-2, 0, 3], [5, 8, 9], 10, 30, 1), [[0.0, 0.0, 0.0], None]),
  ('control: warm nights', ([18, 19, 21, 22], [28, 29, 33, 35], 12, 32, 40), [[11.0, 23.0, 37.5, 52.5], 4]),
  ('control: no days', ([], [], 10, 30, 5), [[], None]),
  ('control: near-miss rounding', ([10, 10], [29.2, 10], 10, 30, 10), [[9.6, 9.6], None]),
  ('regression: frost then warm',
   ([-5, 2, 11, 14], [6, 16, 25, 29], 10, 30, 15),
   [[0.0, 3.0, 11.0, 22.5], 4])],
 [('control: spring warming codling moth',
   ([4, 6, 8, 10, 12, 14], [15, 18, 20, 24, 26, 30], 10, 31, 20),
   [[2.5, 6.5, 11.5, 18.5, 27.5, 39.5], 5]),
  ('control: hot spell above cutoff', ([20, 22, 25], [34, 38, 40], 10, 30, 30), [[15.0, 31.0, 48.5], 2]),
  ('regression: cold days below base', ([-2, 0, 3], [5, 8, 9], 10, 30, 1), [[0.0, 0.0, 0.0], None]),
  ('control: exact target', ([10, 10, 10], [20, 20, 20], 10, 30, 10), [[5.0, 10.0, 15.0], 2]),
  ('control: never emerges', ([5, 6], [12, 13], 10, 30, 50), [[1.0, 2.5], None]),
  ('control: invalid thresholds', ([5], [15], 20, 20, 5), None),
  ('regression: frost then warm',
   ([-5, 2, 11, 14], [6, 16, 25, 29], 10, 30, 15),
   [[0.0, 3.0, 11.0, 22.5], 4])],
 [('regression: cold days below base', ([-2, 0, 3], [5, 8, 9], 10, 30, 1), [[0.0, 0.0, 0.0], None]),
  ('control: exact target', ([10, 10, 10], [20, 20, 20], 10, 30, 10), [[5.0, 10.0, 15.0], 2]),
  ('control: never emerges', ([5, 6], [12, 13], 10, 30, 50), [[1.0, 2.5], None]),
  ('control: invalid thresholds', ([5], [15], 20, 20, 5), None),
  ('control: warm nights', ([18, 19, 21, 22], [28, 29, 33, 35], 12, 32, 40), [[11.0, 23.0, 37.5, 52.5], 4]),
  ('control: no days', ([], [], 10, 30, 5), [[], None]),
  ('regression: frost then warm',
   ([-5, 2, 11, 14], [6, 16, 25, 29], 10, 30, 15),
   [[0.0, 3.0, 11.0, 22.5], 4])]]
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
control: spring warming codling moth[[2.5, 6.5, 11.5, 18.5, 27.5, 39.5], 5][[2.5, 6.5, 11.5, 18.5, 27.5, 39.5], 5]Passed
control: hot spell above cutoff[[15.0, 31.0, 48.5], 2][[15.0, 31.0, 48.5], 2]Passed
regression: cold days below base[[0.0, 0.0, 0.0], None][[0.0, 0.0, 0.0], None]Passed
control: exact target[[5.0, 10.0, 15.0], 2][[5.0, 10.0, 15.0], 2]Passed
control: never emerges[[1.0, 2.5], None][[1.0, 2.5], None]Passed
control: invalid thresholdsNoneNonePassed
regression: frost then warm[[0.0, 3.0, 11.0, 22.5], 4][[0.0, 3.0, 11.0, 22.5], 4]Passed

SHA-256 / 64c34fd40d997361830160ec54927acd0095c34ccad86a9d7c33a5f83171ffdc

Verification & scope

Deterministic bounded teaching model with a stipulated contract; not a validated scientific or public-health modelling library. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:47:35.984798+00:00.

Case digest / 4945109f88574bd4dc0582e94f890d98cdecd4b7c8efb8c2d070d116217ccef0