FA-64971 / Epidemic compartment models / Open access
SIRS waning-immunity simulation: cumulative incidence · case 01
Cumulative incidence stops growing, and even falls, once reinfections occur.
ROOT CAUSE
Cumulative incidence is inferred from susceptible depletion, which waning refills.
VERIFIED REPAIR
Restore the cumulative incidence rule: `cumulative += inf`.
Unsuccessful approach: Current I+R misses everyone whose immunity has already waned.
Case contract
Daily forward-Euler SIRS; waning flow is R/immunity_days back to S (immunity_days 0 means permanent immunity); cumulative incidence sums every S->I flow including reinfections; return [S, I, R, cumulative incidence] rounded to 3.
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(beta, gamma, immunity_days, pop, i0, days):
s, i, r = float(pop - i0), float(i0), 0.0
cumulative = 0.0
for _ in range(days):
inf = beta * s * i / pop
rec = gamma * i
wane = r / immunity_days if immunity_days > 0 else 0.0
s += wane - inf
i += inf - rec
r += rec - wane
cumulative = pop - s
return [round(s, 3), round(i, 3), round(r, 3), round(cumulative, 3)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: seasonal coronavirus', (0.4, 0.2, 30, 1000, 5, 80), [543.377, 58.225, 398.398, 1339.789]),
('regression: permanent immunity sentinel', (0.5, 0.2, 0, 500, 5, 40), [48.675, 7.802, 443.523, 446.325]),
('regression: short immunity endemic', (0.6, 0.25, 10, 800, 8, 100), [333.272, 133.331, 333.396, 3385.33]),
('control: boundary zero days', (0.4, 0.2, 30, 100, 5, 0), [95.0, 5.0, 0.0, 0.0]),
('regression: no transmission waning only', (0.0, 0.3, 5, 100, 50, 20), [98.35, 0.04, 1.61, 0.0]),
('regression: long immunity single wave',
(0.5, 0.1, 365, 2000, 10, 120),
[376.102, 3.345, 1620.554, 2084.424]),
('regression: one day immunity', (0.5, 0.3, 1, 300, 3, 30), [188.175, 86.35, 25.475, 420.744])],
[('regression: seasonal coronavirus', (0.4, 0.2, 30, 1000, 5, 80), [543.377, 58.225, 398.398, 1339.789]),
('regression: permanent immunity sentinel', (0.5, 0.2, 0, 500, 5, 40), [48.675, 7.802, 443.523, 446.325]),
('control: boundary zero days', (0.4, 0.2, 30, 100, 5, 0), [95.0, 5.0, 0.0, 0.0]),
('regression: no transmission waning only', (0.0, 0.3, 5, 100, 50, 20), [98.35, 0.04, 1.61, 0.0]),
('regression: long immunity single wave',
(0.5, 0.1, 365, 2000, 10, 120),
[376.102, 3.345, 1620.554, 2084.424]),
('regression: one day immunity', (0.5, 0.3, 1, 300, 3, 30), [188.175, 86.35, 25.475, 420.744]),
('regression: two week run', (0.9, 0.3, 20, 400, 4, 14), [58.25, 94.786, 246.964, 386.248])],
[('regression: seasonal coronavirus', (0.4, 0.2, 30, 1000, 5, 80), [543.377, 58.225, 398.398, 1339.789]),
('regression: permanent immunity sentinel', (0.5, 0.2, 0, 500, 5, 40), [48.675, 7.802, 443.523, 446.325]),
('regression: short immunity endemic', (0.6, 0.25, 10, 800, 8, 100), [333.272, 133.331, 333.396, 3385.33]),
('control: boundary zero days', (0.4, 0.2, 30, 100, 5, 0), [95.0, 5.0, 0.0, 0.0]),
('regression: no transmission waning only', (0.0, 0.3, 5, 100, 50, 20), [98.35, 0.04, 1.61, 0.0]),
('regression: one day immunity', (0.5, 0.3, 1, 300, 3, 30), [188.175, 86.35, 25.475, 420.744]),
('regression: two week run', (0.9, 0.3, 20, 400, 4, 14), [58.25, 94.786, 246.964, 386.248])],
[('regression: permanent immunity sentinel', (0.5, 0.2, 0, 500, 5, 40), [48.675, 7.802, 443.523, 446.325]),
('regression: short immunity endemic', (0.6, 0.25, 10, 800, 8, 100), [333.272, 133.331, 333.396, 3385.33]),
('control: boundary zero days', (0.4, 0.2, 30, 100, 5, 0), [95.0, 5.0, 0.0, 0.0]),
('regression: no transmission waning only', (0.0, 0.3, 5, 100, 50, 20), [98.35, 0.04, 1.61, 0.0]),
('regression: long immunity single wave',
(0.5, 0.1, 365, 2000, 10, 120),
[376.102, 3.345, 1620.554, 2084.424]),
('regression: one day immunity', (0.5, 0.3, 1, 300, 3, 30), [188.175, 86.35, 25.475, 420.744]),
('regression: two week run', (0.9, 0.3, 20, 400, 4, 14), [58.25, 94.786, 246.964, 386.248])],
[('regression: seasonal coronavirus', (0.4, 0.2, 30, 1000, 5, 80), [543.377, 58.225, 398.398, 1339.789]),
('regression: permanent immunity sentinel', (0.5, 0.2, 0, 500, 5, 40), [48.675, 7.802, 443.523, 446.325]),
('control: boundary zero days', (0.4, 0.2, 30, 100, 5, 0), [95.0, 5.0, 0.0, 0.0]),
('regression: no transmission waning only', (0.0, 0.3, 5, 100, 50, 20), [98.35, 0.04, 1.61, 0.0]),
('regression: long immunity single wave',
(0.5, 0.1, 365, 2000, 10, 120),
[376.102, 3.345, 1620.554, 2084.424]),
('regression: one day immunity', (0.5, 0.3, 1, 300, 3, 30), [188.175, 86.35, 25.475, 420.744]),
('regression: two week run', (0.9, 0.3, 20, 400, 4, 14), [58.25, 94.786, 246.964, 386.248])]]
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: seasonal coronavirus | [543.377, 58.225, 398.398, 456.623] | [543.377, 58.225, 398.398, 1339.789] | Failed |
| regression: permanent immunity sentinel | [48.675, 7.802, 443.523, 451.325] | [48.675, 7.802, 443.523, 446.325] | Failed |
| regression: short immunity endemic | [333.272, 133.331, 333.396, 466.728] | [333.272, 133.331, 333.396, 3385.33] | Failed |
| control: boundary zero days | [95.0, 5.0, 0.0, 0.0] | [95.0, 5.0, 0.0, 0.0] | Passed |
| regression: no transmission waning only | [98.35, 0.04, 1.61, 1.65] | [98.35, 0.04, 1.61, 0.0] | Failed |
| regression: long immunity single wave | [376.102, 3.345, 1620.554, 1623.898] | [376.102, 3.345, 1620.554, 2084.424] | Failed |
| regression: one day immunity | [188.175, 86.35, 25.475, 111.825] | [188.175, 86.35, 25.475, 420.744] | Failed |
SHA-256 / 099c602af55f1761923c7e36d861d1fb281bbd7daec7f2e062babdb662ca4b14
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(beta, gamma, immunity_days, pop, i0, days):
s, i, r = float(pop - i0), float(i0), 0.0
cumulative = 0.0
for _ in range(days):
inf = beta * s * i / pop
rec = gamma * i
wane = r / immunity_days if immunity_days > 0 else 0.0
s += wane - inf
i += inf - rec
r += rec - wane
cumulative = i + r
return [round(s, 3), round(i, 3), round(r, 3), round(cumulative, 3)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: seasonal coronavirus', (0.4, 0.2, 30, 1000, 5, 80), [543.377, 58.225, 398.398, 1339.789]),
('regression: permanent immunity sentinel', (0.5, 0.2, 0, 500, 5, 40), [48.675, 7.802, 443.523, 446.325]),
('regression: short immunity endemic', (0.6, 0.25, 10, 800, 8, 100), [333.272, 133.331, 333.396, 3385.33]),
('control: boundary zero days', (0.4, 0.2, 30, 100, 5, 0), [95.0, 5.0, 0.0, 0.0]),
('regression: no transmission waning only', (0.0, 0.3, 5, 100, 50, 20), [98.35, 0.04, 1.61, 0.0]),
('regression: long immunity single wave',
(0.5, 0.1, 365, 2000, 10, 120),
[376.102, 3.345, 1620.554, 2084.424]),
('regression: one day immunity', (0.5, 0.3, 1, 300, 3, 30), [188.175, 86.35, 25.475, 420.744])],
[('regression: seasonal coronavirus', (0.4, 0.2, 30, 1000, 5, 80), [543.377, 58.225, 398.398, 1339.789]),
('regression: permanent immunity sentinel', (0.5, 0.2, 0, 500, 5, 40), [48.675, 7.802, 443.523, 446.325]),
('control: boundary zero days', (0.4, 0.2, 30, 100, 5, 0), [95.0, 5.0, 0.0, 0.0]),
('regression: no transmission waning only', (0.0, 0.3, 5, 100, 50, 20), [98.35, 0.04, 1.61, 0.0]),
('regression: long immunity single wave',
(0.5, 0.1, 365, 2000, 10, 120),
[376.102, 3.345, 1620.554, 2084.424]),
('regression: one day immunity', (0.5, 0.3, 1, 300, 3, 30), [188.175, 86.35, 25.475, 420.744]),
('regression: two week run', (0.9, 0.3, 20, 400, 4, 14), [58.25, 94.786, 246.964, 386.248])],
[('regression: seasonal coronavirus', (0.4, 0.2, 30, 1000, 5, 80), [543.377, 58.225, 398.398, 1339.789]),
('regression: permanent immunity sentinel', (0.5, 0.2, 0, 500, 5, 40), [48.675, 7.802, 443.523, 446.325]),
('regression: short immunity endemic', (0.6, 0.25, 10, 800, 8, 100), [333.272, 133.331, 333.396, 3385.33]),
('control: boundary zero days', (0.4, 0.2, 30, 100, 5, 0), [95.0, 5.0, 0.0, 0.0]),
('regression: no transmission waning only', (0.0, 0.3, 5, 100, 50, 20), [98.35, 0.04, 1.61, 0.0]),
('regression: one day immunity', (0.5, 0.3, 1, 300, 3, 30), [188.175, 86.35, 25.475, 420.744]),
('regression: two week run', (0.9, 0.3, 20, 400, 4, 14), [58.25, 94.786, 246.964, 386.248])],
[('regression: permanent immunity sentinel', (0.5, 0.2, 0, 500, 5, 40), [48.675, 7.802, 443.523, 446.325]),
('regression: short immunity endemic', (0.6, 0.25, 10, 800, 8, 100), [333.272, 133.331, 333.396, 3385.33]),
('control: boundary zero days', (0.4, 0.2, 30, 100, 5, 0), [95.0, 5.0, 0.0, 0.0]),
('regression: no transmission waning only', (0.0, 0.3, 5, 100, 50, 20), [98.35, 0.04, 1.61, 0.0]),
('regression: long immunity single wave',
(0.5, 0.1, 365, 2000, 10, 120),
[376.102, 3.345, 1620.554, 2084.424]),
('regression: one day immunity', (0.5, 0.3, 1, 300, 3, 30), [188.175, 86.35, 25.475, 420.744]),
('regression: two week run', (0.9, 0.3, 20, 400, 4, 14), [58.25, 94.786, 246.964, 386.248])],
[('regression: seasonal coronavirus', (0.4, 0.2, 30, 1000, 5, 80), [543.377, 58.225, 398.398, 1339.789]),
('regression: permanent immunity sentinel', (0.5, 0.2, 0, 500, 5, 40), [48.675, 7.802, 443.523, 446.325]),
('control: boundary zero days', (0.4, 0.2, 30, 100, 5, 0), [95.0, 5.0, 0.0, 0.0]),
('regression: no transmission waning only', (0.0, 0.3, 5, 100, 50, 20), [98.35, 0.04, 1.61, 0.0]),
('regression: long immunity single wave',
(0.5, 0.1, 365, 2000, 10, 120),
[376.102, 3.345, 1620.554, 2084.424]),
('regression: one day immunity', (0.5, 0.3, 1, 300, 3, 30), [188.175, 86.35, 25.475, 420.744]),
('regression: two week run', (0.9, 0.3, 20, 400, 4, 14), [58.25, 94.786, 246.964, 386.248])]]
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: seasonal coronavirus | [543.377, 58.225, 398.398, 456.623] | [543.377, 58.225, 398.398, 1339.789] | Failed |
| regression: permanent immunity sentinel | [48.675, 7.802, 443.523, 451.325] | [48.675, 7.802, 443.523, 446.325] | Failed |
| regression: short immunity endemic | [333.272, 133.331, 333.396, 466.728] | [333.272, 133.331, 333.396, 3385.33] | Failed |
| control: boundary zero days | [95.0, 5.0, 0.0, 0.0] | [95.0, 5.0, 0.0, 0.0] | Passed |
| regression: no transmission waning only | [98.35, 0.04, 1.61, 1.65] | [98.35, 0.04, 1.61, 0.0] | Failed |
| regression: long immunity single wave | [376.102, 3.345, 1620.554, 1623.898] | [376.102, 3.345, 1620.554, 2084.424] | Failed |
| regression: one day immunity | [188.175, 86.35, 25.475, 111.825] | [188.175, 86.35, 25.475, 420.744] | Failed |
SHA-256 / 9aa1bd985300a257c8e1515c673c6150aadc0bc95f904ec52d8cffd26a0b17f7
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(beta, gamma, immunity_days, pop, i0, days):
s, i, r = float(pop - i0), float(i0), 0.0
cumulative = 0.0
for _ in range(days):
inf = beta * s * i / pop
rec = gamma * i
wane = r / immunity_days if immunity_days > 0 else 0.0
s += wane - inf
i += inf - rec
r += rec - wane
cumulative += inf
return [round(s, 3), round(i, 3), round(r, 3), round(cumulative, 3)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: seasonal coronavirus', (0.4, 0.2, 30, 1000, 5, 80), [543.377, 58.225, 398.398, 1339.789]),
('regression: permanent immunity sentinel', (0.5, 0.2, 0, 500, 5, 40), [48.675, 7.802, 443.523, 446.325]),
('regression: short immunity endemic', (0.6, 0.25, 10, 800, 8, 100), [333.272, 133.331, 333.396, 3385.33]),
('control: boundary zero days', (0.4, 0.2, 30, 100, 5, 0), [95.0, 5.0, 0.0, 0.0]),
('regression: no transmission waning only', (0.0, 0.3, 5, 100, 50, 20), [98.35, 0.04, 1.61, 0.0]),
('regression: long immunity single wave',
(0.5, 0.1, 365, 2000, 10, 120),
[376.102, 3.345, 1620.554, 2084.424]),
('regression: one day immunity', (0.5, 0.3, 1, 300, 3, 30), [188.175, 86.35, 25.475, 420.744])],
[('regression: seasonal coronavirus', (0.4, 0.2, 30, 1000, 5, 80), [543.377, 58.225, 398.398, 1339.789]),
('regression: permanent immunity sentinel', (0.5, 0.2, 0, 500, 5, 40), [48.675, 7.802, 443.523, 446.325]),
('control: boundary zero days', (0.4, 0.2, 30, 100, 5, 0), [95.0, 5.0, 0.0, 0.0]),
('regression: no transmission waning only', (0.0, 0.3, 5, 100, 50, 20), [98.35, 0.04, 1.61, 0.0]),
('regression: long immunity single wave',
(0.5, 0.1, 365, 2000, 10, 120),
[376.102, 3.345, 1620.554, 2084.424]),
('regression: one day immunity', (0.5, 0.3, 1, 300, 3, 30), [188.175, 86.35, 25.475, 420.744]),
('regression: two week run', (0.9, 0.3, 20, 400, 4, 14), [58.25, 94.786, 246.964, 386.248])],
[('regression: seasonal coronavirus', (0.4, 0.2, 30, 1000, 5, 80), [543.377, 58.225, 398.398, 1339.789]),
('regression: permanent immunity sentinel', (0.5, 0.2, 0, 500, 5, 40), [48.675, 7.802, 443.523, 446.325]),
('regression: short immunity endemic', (0.6, 0.25, 10, 800, 8, 100), [333.272, 133.331, 333.396, 3385.33]),
('control: boundary zero days', (0.4, 0.2, 30, 100, 5, 0), [95.0, 5.0, 0.0, 0.0]),
('regression: no transmission waning only', (0.0, 0.3, 5, 100, 50, 20), [98.35, 0.04, 1.61, 0.0]),
('regression: one day immunity', (0.5, 0.3, 1, 300, 3, 30), [188.175, 86.35, 25.475, 420.744]),
('regression: two week run', (0.9, 0.3, 20, 400, 4, 14), [58.25, 94.786, 246.964, 386.248])],
[('regression: permanent immunity sentinel', (0.5, 0.2, 0, 500, 5, 40), [48.675, 7.802, 443.523, 446.325]),
('regression: short immunity endemic', (0.6, 0.25, 10, 800, 8, 100), [333.272, 133.331, 333.396, 3385.33]),
('control: boundary zero days', (0.4, 0.2, 30, 100, 5, 0), [95.0, 5.0, 0.0, 0.0]),
('regression: no transmission waning only', (0.0, 0.3, 5, 100, 50, 20), [98.35, 0.04, 1.61, 0.0]),
('regression: long immunity single wave',
(0.5, 0.1, 365, 2000, 10, 120),
[376.102, 3.345, 1620.554, 2084.424]),
('regression: one day immunity', (0.5, 0.3, 1, 300, 3, 30), [188.175, 86.35, 25.475, 420.744]),
('regression: two week run', (0.9, 0.3, 20, 400, 4, 14), [58.25, 94.786, 246.964, 386.248])],
[('regression: seasonal coronavirus', (0.4, 0.2, 30, 1000, 5, 80), [543.377, 58.225, 398.398, 1339.789]),
('regression: permanent immunity sentinel', (0.5, 0.2, 0, 500, 5, 40), [48.675, 7.802, 443.523, 446.325]),
('control: boundary zero days', (0.4, 0.2, 30, 100, 5, 0), [95.0, 5.0, 0.0, 0.0]),
('regression: no transmission waning only', (0.0, 0.3, 5, 100, 50, 20), [98.35, 0.04, 1.61, 0.0]),
('regression: long immunity single wave',
(0.5, 0.1, 365, 2000, 10, 120),
[376.102, 3.345, 1620.554, 2084.424]),
('regression: one day immunity', (0.5, 0.3, 1, 300, 3, 30), [188.175, 86.35, 25.475, 420.744]),
('regression: two week run', (0.9, 0.3, 20, 400, 4, 14), [58.25, 94.786, 246.964, 386.248])]]
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: seasonal coronavirus | [543.377, 58.225, 398.398, 1339.789] | [543.377, 58.225, 398.398, 1339.789] | Passed |
| regression: permanent immunity sentinel | [48.675, 7.802, 443.523, 446.325] | [48.675, 7.802, 443.523, 446.325] | Passed |
| regression: short immunity endemic | [333.272, 133.331, 333.396, 3385.33] | [333.272, 133.331, 333.396, 3385.33] | Passed |
| control: boundary zero days | [95.0, 5.0, 0.0, 0.0] | [95.0, 5.0, 0.0, 0.0] | Passed |
| regression: no transmission waning only | [98.35, 0.04, 1.61, 0.0] | [98.35, 0.04, 1.61, 0.0] | Passed |
| regression: long immunity single wave | [376.102, 3.345, 1620.554, 2084.424] | [376.102, 3.345, 1620.554, 2084.424] | Passed |
| regression: one day immunity | [188.175, 86.35, 25.475, 420.744] | [188.175, 86.35, 25.475, 420.744] | Passed |
SHA-256 / 55289b2c7cadb3a40b1730e77a858dd1f2456a1ef1d49416b15f79c673ac1343
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:29.537122+00:00.
Case digest / c04abf5b3ead168ccb3c78761e2f2aadce31ec24cc6231e5a2abf79246037a1f