FA-65116 / Epidemic compartment models / Open access
Windowed renewal-equation Rt estimate: serial-interval lag origin · case 01
Same-day cases are counted as their own infectors.
ROOT CAUSE
The lag loop starts at 0, so same-day incidence is weighted by the wrapped-around last weight.
VERIFIED REPAIR
Restore the serial-interval lag origin rule: `range(1, len(weights) + 1)`.
Unsuccessful approach: Starting at 1 but dropping the final lag loses the tail of the serial interval.
Case contract
weights[s-1] is the serial-interval weight at lag s>=1 (unnormalised); daily infection pressure Lambda_k = sum_s w_s*I[k-s]/sum of available weights (lags reaching before day 0 dropped); Rt = sum_{k=t-window+1..t} I_k / sum Lambda_k; None if the window reaches day 0, t is out of range or the denominator is zero; result rounded 6.
Why this case matters
Compartmental epidemic calculations drive outbreak forecasts, vaccine targets and hospital planning; a single wrong flow, rate conversion or boundary silently changes every downstream number.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(incidence, weights, t, window):
if window < 1 or t - window + 1 < 1 or t >= len(incidence):
return None
num = 0.0
den = 0.0
for k in range(t - window + 1, t + 1):
pressure = 0.0
mass = 0.0
for s in range(0, len(weights)):
if k - s < 0:
break
pressure += weights[s - 1] * incidence[k - s]
mass += weights[s - 1]
if mass > 0:
pressure /= mass
num += incidence[k]
den += pressure
if den <= 0:
return None
return round(num / den, 6)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: growing outbreak', ([1, 2, 4, 7, 12, 20, 33, 50, 80], [0.2, 0.5, 0.3], 8, 3), 2.515432),
('regression: declining outbreak', ([90, 80, 60, 45, 30, 20, 12, 8], [0.3, 0.4, 0.3], 7, 2), 0.383877),
('regression: unnormalised weights', ([5, 6, 8, 9, 11, 14, 16], [2, 3, 1], 6, 2), 1.417323),
('regression: early window truncation', ([3, 5, 9, 14, 20], [0.1, 0.2, 0.3, 0.4], 3, 2), 2.76),
('control: boundary window reaching day 0', ([4, 6, 9, 12], [0.5, 0.5], 2, 3), None),
('control: t out of range', ([4, 6, 9], [0.5, 0.5], 3, 1), None),
('control: flat incidence', ([10, 10, 10, 10, 10, 10], [0.5, 0.3, 0.2], 5, 3), 1.0)],
[('regression: early window truncation', ([3, 5, 9, 14, 20], [0.1, 0.2, 0.3, 0.4], 3, 2), 2.76),
('control: boundary window reaching day 0', ([4, 6, 9, 12], [0.5, 0.5], 2, 3), None),
('regression: window starting on day 1', ([4, 6, 9, 12], [0.5, 0.5], 2, 2), 1.666667),
('regression: single day window at day 1', ([3, 5, 8], [1.0], 1, 1), 1.666667),
('control: t out of range', ([4, 6, 9], [0.5, 0.5], 3, 1), None),
('regression: zero history', ([0, 0, 0, 5, 7], [0.6, 0.4], 3, 2), None),
('control: flat incidence', ([10, 10, 10, 10, 10, 10], [0.5, 0.3, 0.2], 5, 3), 1.0)],
[('control: boundary window reaching day 0', ([4, 6, 9, 12], [0.5, 0.5], 2, 3), None),
('regression: single day window at day 1', ([3, 5, 8], [1.0], 1, 1), 1.666667),
('control: t out of range', ([4, 6, 9], [0.5, 0.5], 3, 1), None),
('regression: zero history', ([0, 0, 0, 5, 7], [0.6, 0.4], 3, 2), None),
('regression: single day window', ([10, 12, 15, 17, 22, 25], [0.25, 0.5, 0.25], 5, 1), 1.408451),
('regression: long serial interval',
([2, 3, 5, 8, 11, 15, 19, 24, 30, 36], [0.1, 0.15, 0.2, 0.25, 0.3], 9, 4),
2.289916),
('control: flat incidence', ([10, 10, 10, 10, 10, 10], [0.5, 0.3, 0.2], 5, 3), 1.0)],
[('regression: growing outbreak', ([1, 2, 4, 7, 12, 20, 33, 50, 80], [0.2, 0.5, 0.3], 8, 3), 2.515432),
('regression: declining outbreak', ([90, 80, 60, 45, 30, 20, 12, 8], [0.3, 0.4, 0.3], 7, 2), 0.383877),
('control: boundary window reaching day 0', ([4, 6, 9, 12], [0.5, 0.5], 2, 3), None),
('control: t out of range', ([4, 6, 9], [0.5, 0.5], 3, 1), None),
('regression: single day window', ([10, 12, 15, 17, 22, 25], [0.25, 0.5, 0.25], 5, 1), 1.408451),
('regression: long serial interval',
([2, 3, 5, 8, 11, 15, 19, 24, 30, 36], [0.1, 0.15, 0.2, 0.25, 0.3], 9, 4),
2.289916),
('control: flat incidence', ([10, 10, 10, 10, 10, 10], [0.5, 0.3, 0.2], 5, 3), 1.0)],
[('regression: growing outbreak', ([1, 2, 4, 7, 12, 20, 33, 50, 80], [0.2, 0.5, 0.3], 8, 3), 2.515432),
('regression: declining outbreak', ([90, 80, 60, 45, 30, 20, 12, 8], [0.3, 0.4, 0.3], 7, 2), 0.383877),
('regression: unnormalised weights', ([5, 6, 8, 9, 11, 14, 16], [2, 3, 1], 6, 2), 1.417323),
('regression: early window truncation', ([3, 5, 9, 14, 20], [0.1, 0.2, 0.3, 0.4], 3, 2), 2.76),
('control: boundary window reaching day 0', ([4, 6, 9, 12], [0.5, 0.5], 2, 3), None),
('control: t out of range', ([4, 6, 9], [0.5, 0.5], 3, 1), None),
('control: flat incidence', ([10, 10, 10, 10, 10, 10], [0.5, 0.3, 0.2], 5, 3), 1.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)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: growing outbreak | 1.598039 | 2.515432 | Failed |
| regression: declining outbreak | 0.561798 | 0.383877 | Failed |
| regression: unnormalised weights | 1.285714 | 1.417323 | Failed |
| regression: early window truncation | 1.521739 | 2.76 | Failed |
| control: boundary window reaching day 0 | None | None | Passed |
| control: t out of range | None | None | Passed |
| control: flat incidence | 1.0 | 1.0 | Passed |
SHA-256 / 28beddcf0c0a538364922b01b5f1a05e8b7056337a5e4299c3b48614808c9ec9
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(incidence, weights, t, window):
if window < 1 or t - window + 1 < 1 or t >= len(incidence):
return None
num = 0.0
den = 0.0
for k in range(t - window + 1, t + 1):
pressure = 0.0
mass = 0.0
for s in range(1, len(weights)):
if k - s < 0:
break
pressure += weights[s - 1] * incidence[k - s]
mass += weights[s - 1]
if mass > 0:
pressure /= mass
num += incidence[k]
den += pressure
if den <= 0:
return None
return round(num / den, 6)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: growing outbreak', ([1, 2, 4, 7, 12, 20, 33, 50, 80], [0.2, 0.5, 0.3], 8, 3), 2.515432),
('regression: declining outbreak', ([90, 80, 60, 45, 30, 20, 12, 8], [0.3, 0.4, 0.3], 7, 2), 0.383877),
('regression: unnormalised weights', ([5, 6, 8, 9, 11, 14, 16], [2, 3, 1], 6, 2), 1.417323),
('regression: early window truncation', ([3, 5, 9, 14, 20], [0.1, 0.2, 0.3, 0.4], 3, 2), 2.76),
('control: boundary window reaching day 0', ([4, 6, 9, 12], [0.5, 0.5], 2, 3), None),
('control: t out of range', ([4, 6, 9], [0.5, 0.5], 3, 1), None),
('control: flat incidence', ([10, 10, 10, 10, 10, 10], [0.5, 0.3, 0.2], 5, 3), 1.0)],
[('regression: early window truncation', ([3, 5, 9, 14, 20], [0.1, 0.2, 0.3, 0.4], 3, 2), 2.76),
('control: boundary window reaching day 0', ([4, 6, 9, 12], [0.5, 0.5], 2, 3), None),
('regression: window starting on day 1', ([4, 6, 9, 12], [0.5, 0.5], 2, 2), 1.666667),
('regression: single day window at day 1', ([3, 5, 8], [1.0], 1, 1), 1.666667),
('control: t out of range', ([4, 6, 9], [0.5, 0.5], 3, 1), None),
('regression: zero history', ([0, 0, 0, 5, 7], [0.6, 0.4], 3, 2), None),
('control: flat incidence', ([10, 10, 10, 10, 10, 10], [0.5, 0.3, 0.2], 5, 3), 1.0)],
[('control: boundary window reaching day 0', ([4, 6, 9, 12], [0.5, 0.5], 2, 3), None),
('regression: single day window at day 1', ([3, 5, 8], [1.0], 1, 1), 1.666667),
('control: t out of range', ([4, 6, 9], [0.5, 0.5], 3, 1), None),
('regression: zero history', ([0, 0, 0, 5, 7], [0.6, 0.4], 3, 2), None),
('regression: single day window', ([10, 12, 15, 17, 22, 25], [0.25, 0.5, 0.25], 5, 1), 1.408451),
('regression: long serial interval',
([2, 3, 5, 8, 11, 15, 19, 24, 30, 36], [0.1, 0.15, 0.2, 0.25, 0.3], 9, 4),
2.289916),
('control: flat incidence', ([10, 10, 10, 10, 10, 10], [0.5, 0.3, 0.2], 5, 3), 1.0)],
[('regression: growing outbreak', ([1, 2, 4, 7, 12, 20, 33, 50, 80], [0.2, 0.5, 0.3], 8, 3), 2.515432),
('regression: declining outbreak', ([90, 80, 60, 45, 30, 20, 12, 8], [0.3, 0.4, 0.3], 7, 2), 0.383877),
('control: boundary window reaching day 0', ([4, 6, 9, 12], [0.5, 0.5], 2, 3), None),
('control: t out of range', ([4, 6, 9], [0.5, 0.5], 3, 1), None),
('regression: single day window', ([10, 12, 15, 17, 22, 25], [0.25, 0.5, 0.25], 5, 1), 1.408451),
('regression: long serial interval',
([2, 3, 5, 8, 11, 15, 19, 24, 30, 36], [0.1, 0.15, 0.2, 0.25, 0.3], 9, 4),
2.289916),
('control: flat incidence', ([10, 10, 10, 10, 10, 10], [0.5, 0.3, 0.2], 5, 3), 1.0)],
[('regression: growing outbreak', ([1, 2, 4, 7, 12, 20, 33, 50, 80], [0.2, 0.5, 0.3], 8, 3), 2.515432),
('regression: declining outbreak', ([90, 80, 60, 45, 30, 20, 12, 8], [0.3, 0.4, 0.3], 7, 2), 0.383877),
('regression: unnormalised weights', ([5, 6, 8, 9, 11, 14, 16], [2, 3, 1], 6, 2), 1.417323),
('regression: early window truncation', ([3, 5, 9, 14, 20], [0.1, 0.2, 0.3, 0.4], 3, 2), 2.76),
('control: boundary window reaching day 0', ([4, 6, 9, 12], [0.5, 0.5], 2, 3), None),
('control: t out of range', ([4, 6, 9], [0.5, 0.5], 3, 1), None),
('control: flat incidence', ([10, 10, 10, 10, 10, 10], [0.5, 0.3, 0.2], 5, 3), 1.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)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: growing outbreak | 2.148776 | 2.515432 | Failed |
| regression: declining outbreak | 0.472973 | 0.383877 | Failed |
| regression: unnormalised weights | 1.363636 | 1.417323 | Failed |
| regression: early window truncation | 2.76 | 2.76 | Passed |
| control: boundary window reaching day 0 | None | None | Passed |
| control: t out of range | None | None | Passed |
| control: flat incidence | 1.0 | 1.0 | Passed |
SHA-256 / dd4cb32ebcd50f160ce769e6c41cd687009d2b88004adb214952ade106fc8ada
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(incidence, weights, t, window):
if window < 1 or t - window + 1 < 1 or t >= len(incidence):
return None
num = 0.0
den = 0.0
for k in range(t - window + 1, t + 1):
pressure = 0.0
mass = 0.0
for s in range(1, len(weights) + 1):
if k - s < 0:
break
pressure += weights[s - 1] * incidence[k - s]
mass += weights[s - 1]
if mass > 0:
pressure /= mass
num += incidence[k]
den += pressure
if den <= 0:
return None
return round(num / den, 6)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: growing outbreak', ([1, 2, 4, 7, 12, 20, 33, 50, 80], [0.2, 0.5, 0.3], 8, 3), 2.515432),
('regression: declining outbreak', ([90, 80, 60, 45, 30, 20, 12, 8], [0.3, 0.4, 0.3], 7, 2), 0.383877),
('regression: unnormalised weights', ([5, 6, 8, 9, 11, 14, 16], [2, 3, 1], 6, 2), 1.417323),
('regression: early window truncation', ([3, 5, 9, 14, 20], [0.1, 0.2, 0.3, 0.4], 3, 2), 2.76),
('control: boundary window reaching day 0', ([4, 6, 9, 12], [0.5, 0.5], 2, 3), None),
('control: t out of range', ([4, 6, 9], [0.5, 0.5], 3, 1), None),
('control: flat incidence', ([10, 10, 10, 10, 10, 10], [0.5, 0.3, 0.2], 5, 3), 1.0)],
[('regression: early window truncation', ([3, 5, 9, 14, 20], [0.1, 0.2, 0.3, 0.4], 3, 2), 2.76),
('control: boundary window reaching day 0', ([4, 6, 9, 12], [0.5, 0.5], 2, 3), None),
('regression: window starting on day 1', ([4, 6, 9, 12], [0.5, 0.5], 2, 2), 1.666667),
('regression: single day window at day 1', ([3, 5, 8], [1.0], 1, 1), 1.666667),
('control: t out of range', ([4, 6, 9], [0.5, 0.5], 3, 1), None),
('regression: zero history', ([0, 0, 0, 5, 7], [0.6, 0.4], 3, 2), None),
('control: flat incidence', ([10, 10, 10, 10, 10, 10], [0.5, 0.3, 0.2], 5, 3), 1.0)],
[('control: boundary window reaching day 0', ([4, 6, 9, 12], [0.5, 0.5], 2, 3), None),
('regression: single day window at day 1', ([3, 5, 8], [1.0], 1, 1), 1.666667),
('control: t out of range', ([4, 6, 9], [0.5, 0.5], 3, 1), None),
('regression: zero history', ([0, 0, 0, 5, 7], [0.6, 0.4], 3, 2), None),
('regression: single day window', ([10, 12, 15, 17, 22, 25], [0.25, 0.5, 0.25], 5, 1), 1.408451),
('regression: long serial interval',
([2, 3, 5, 8, 11, 15, 19, 24, 30, 36], [0.1, 0.15, 0.2, 0.25, 0.3], 9, 4),
2.289916),
('control: flat incidence', ([10, 10, 10, 10, 10, 10], [0.5, 0.3, 0.2], 5, 3), 1.0)],
[('regression: growing outbreak', ([1, 2, 4, 7, 12, 20, 33, 50, 80], [0.2, 0.5, 0.3], 8, 3), 2.515432),
('regression: declining outbreak', ([90, 80, 60, 45, 30, 20, 12, 8], [0.3, 0.4, 0.3], 7, 2), 0.383877),
('control: boundary window reaching day 0', ([4, 6, 9, 12], [0.5, 0.5], 2, 3), None),
('control: t out of range', ([4, 6, 9], [0.5, 0.5], 3, 1), None),
('regression: single day window', ([10, 12, 15, 17, 22, 25], [0.25, 0.5, 0.25], 5, 1), 1.408451),
('regression: long serial interval',
([2, 3, 5, 8, 11, 15, 19, 24, 30, 36], [0.1, 0.15, 0.2, 0.25, 0.3], 9, 4),
2.289916),
('control: flat incidence', ([10, 10, 10, 10, 10, 10], [0.5, 0.3, 0.2], 5, 3), 1.0)],
[('regression: growing outbreak', ([1, 2, 4, 7, 12, 20, 33, 50, 80], [0.2, 0.5, 0.3], 8, 3), 2.515432),
('regression: declining outbreak', ([90, 80, 60, 45, 30, 20, 12, 8], [0.3, 0.4, 0.3], 7, 2), 0.383877),
('regression: unnormalised weights', ([5, 6, 8, 9, 11, 14, 16], [2, 3, 1], 6, 2), 1.417323),
('regression: early window truncation', ([3, 5, 9, 14, 20], [0.1, 0.2, 0.3, 0.4], 3, 2), 2.76),
('control: boundary window reaching day 0', ([4, 6, 9, 12], [0.5, 0.5], 2, 3), None),
('control: t out of range', ([4, 6, 9], [0.5, 0.5], 3, 1), None),
('control: flat incidence', ([10, 10, 10, 10, 10, 10], [0.5, 0.3, 0.2], 5, 3), 1.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)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: growing outbreak | 2.515432 | 2.515432 | Passed |
| regression: declining outbreak | 0.383877 | 0.383877 | Passed |
| regression: unnormalised weights | 1.417323 | 1.417323 | Passed |
| regression: early window truncation | 2.76 | 2.76 | Passed |
| control: boundary window reaching day 0 | None | None | Passed |
| control: t out of range | None | None | Passed |
| control: flat incidence | 1.0 | 1.0 | Passed |
SHA-256 / c49651ec288500eee55f9e435e07d2e3ffc9ab1f3f37efdec44e72b20a40e98f
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:30.852589+00:00.
Case digest / 3ea9c31b4daf6717734b653c3e9fe0aa5915fc35975573016353d4bcb8e5c3bc