FA-65296 / Epidemic compartment models / Open access
Household secondary attack rate: secondary consistency guard · case 01
Data-entry errors produce household SARs above 100%.
ROOT CAUSE
Households reporting more secondaries than at-risk members are not skipped.
VERIFIED REPAIR
Restore the secondary consistency guard rule: `if secondary > at_risk: / continue`.
Unsuccessful approach: Clamping keeps an inconsistent record in the estimate.
Case contract
Each household is [size, index_cases, secondary]; skip households without an index case, without members at risk, or with more secondaries than at-risk members; pooled SAR = sum secondary / sum (size-index); per-size table sorted by size ascending; return [pooled rounded 6 or None, table].
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(households):
num = 0
den = 0
by_size = {}
for size, index, secondary in households:
at_risk = size - index
if index < 1 or at_risk <= 0:
continue
num += secondary
den += at_risk
a, b = by_size.get(size, (0, 0))
by_size[size] = (a + secondary, b + at_risk)
overall = round(num / den, 6) if den else None
table = [[k, round(a / b, 6)] for k, (a, b) in sorted(by_size.items())]
return [overall, table]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control: mixed households',
([[4, 1, 2], [3, 1, 0], [5, 2, 1], [2, 1, 1]],),
[0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]]),
('control: two index cases', ([[6, 2, 3], [6, 1, 1], [3, 1, 1]],), [0.454545, [[3, 0.5], [6, 0.444444]]]),
('control: no index household', ([[4, 0, 0], [4, 1, 1], [3, 1, 2]],), [0.6, [[3, 1.0], [4, 0.333333]]]),
('control: single-person household', ([[1, 1, 0], [2, 1, 1]],), [1.0, [[2, 1.0]]]),
('regression: data error secondary too high',
([[3, 1, 4], [3, 1, 1], [5, 1, 2]],),
[0.5, [[3, 0.5], [5, 0.5]]]),
('control: empty input', ([],), [None, []]),
('control: descending sizes',
([[7, 1, 3], [2, 1, 0], [4, 1, 1]],),
[0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]])],
[('control: mixed households',
([[4, 1, 2], [3, 1, 0], [5, 2, 1], [2, 1, 1]],),
[0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]]),
('control: single-person household', ([[1, 1, 0], [2, 1, 1]],), [1.0, [[2, 1.0]]]),
('regression: data error secondary too high',
([[3, 1, 4], [3, 1, 1], [5, 1, 2]],),
[0.5, [[3, 0.5], [5, 0.5]]]),
('control: empty input', ([],), [None, []]),
('control: descending sizes',
([[7, 1, 3], [2, 1, 0], [4, 1, 1]],),
[0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]]),
('control: all index', ([[2, 2, 0], [3, 3, 0]],), [None, []]),
('control: large and small',
([[8, 1, 6], [2, 1, 1], [8, 2, 1], [3, 1, 0]],),
[0.5, [[2, 1.0], [3, 0.0], [8, 0.538462]]])],
[('control: mixed households',
([[4, 1, 2], [3, 1, 0], [5, 2, 1], [2, 1, 1]],),
[0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]]),
('control: two index cases', ([[6, 2, 3], [6, 1, 1], [3, 1, 1]],), [0.454545, [[3, 0.5], [6, 0.444444]]]),
('control: no index household', ([[4, 0, 0], [4, 1, 1], [3, 1, 2]],), [0.6, [[3, 1.0], [4, 0.333333]]]),
('regression: data error secondary too high',
([[3, 1, 4], [3, 1, 1], [5, 1, 2]],),
[0.5, [[3, 0.5], [5, 0.5]]]),
('control: descending sizes',
([[7, 1, 3], [2, 1, 0], [4, 1, 1]],),
[0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]]),
('control: all index', ([[2, 2, 0], [3, 3, 0]],), [None, []]),
('control: large and small',
([[8, 1, 6], [2, 1, 1], [8, 2, 1], [3, 1, 0]],),
[0.5, [[2, 1.0], [3, 0.0], [8, 0.538462]]])],
[('control: mixed households',
([[4, 1, 2], [3, 1, 0], [5, 2, 1], [2, 1, 1]],),
[0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]]),
('control: two index cases', ([[6, 2, 3], [6, 1, 1], [3, 1, 1]],), [0.454545, [[3, 0.5], [6, 0.444444]]]),
('control: no index household', ([[4, 0, 0], [4, 1, 1], [3, 1, 2]],), [0.6, [[3, 1.0], [4, 0.333333]]]),
('control: single-person household', ([[1, 1, 0], [2, 1, 1]],), [1.0, [[2, 1.0]]]),
('regression: data error secondary too high',
([[3, 1, 4], [3, 1, 1], [5, 1, 2]],),
[0.5, [[3, 0.5], [5, 0.5]]]),
('control: empty input', ([],), [None, []]),
('control: descending sizes',
([[7, 1, 3], [2, 1, 0], [4, 1, 1]],),
[0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]])],
[('control: mixed households',
([[4, 1, 2], [3, 1, 0], [5, 2, 1], [2, 1, 1]],),
[0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]]),
('control: single-person household', ([[1, 1, 0], [2, 1, 1]],), [1.0, [[2, 1.0]]]),
('regression: data error secondary too high',
([[3, 1, 4], [3, 1, 1], [5, 1, 2]],),
[0.5, [[3, 0.5], [5, 0.5]]]),
('control: empty input', ([],), [None, []]),
('control: descending sizes',
([[7, 1, 3], [2, 1, 0], [4, 1, 1]],),
[0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]]),
('control: all index', ([[2, 2, 0], [3, 3, 0]],), [None, []]),
('control: large and small',
([[8, 1, 6], [2, 1, 1], [8, 2, 1], [3, 1, 0]],),
[0.5, [[2, 1.0], [3, 0.0], [8, 0.538462]]])]]
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 |
|---|---|---|---|
| control: mixed households | [0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]] | [0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]] | Passed |
| control: two index cases | [0.454545, [[3, 0.5], [6, 0.444444]]] | [0.454545, [[3, 0.5], [6, 0.444444]]] | Passed |
| control: no index household | [0.6, [[3, 1.0], [4, 0.333333]]] | [0.6, [[3, 1.0], [4, 0.333333]]] | Passed |
| control: single-person household | [1.0, [[2, 1.0]]] | [1.0, [[2, 1.0]]] | Passed |
| regression: data error secondary too high | [0.875, [[3, 1.25], [5, 0.5]]] | [0.5, [[3, 0.5], [5, 0.5]]] | Failed |
| control: empty input | [None, []] | [None, []] | Passed |
| control: descending sizes | [0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]] | [0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]] | Passed |
SHA-256 / d66c5ce7dfb2abdc0a6a520eb5b87b32e30a2ea3366583d7c39eec32eca0e317
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(households):
num = 0
den = 0
by_size = {}
for size, index, secondary in households:
at_risk = size - index
if index < 1 or at_risk <= 0:
continue
secondary = min(secondary, at_risk)
num += secondary
den += at_risk
a, b = by_size.get(size, (0, 0))
by_size[size] = (a + secondary, b + at_risk)
overall = round(num / den, 6) if den else None
table = [[k, round(a / b, 6)] for k, (a, b) in sorted(by_size.items())]
return [overall, table]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control: mixed households',
([[4, 1, 2], [3, 1, 0], [5, 2, 1], [2, 1, 1]],),
[0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]]),
('control: two index cases', ([[6, 2, 3], [6, 1, 1], [3, 1, 1]],), [0.454545, [[3, 0.5], [6, 0.444444]]]),
('control: no index household', ([[4, 0, 0], [4, 1, 1], [3, 1, 2]],), [0.6, [[3, 1.0], [4, 0.333333]]]),
('control: single-person household', ([[1, 1, 0], [2, 1, 1]],), [1.0, [[2, 1.0]]]),
('regression: data error secondary too high',
([[3, 1, 4], [3, 1, 1], [5, 1, 2]],),
[0.5, [[3, 0.5], [5, 0.5]]]),
('control: empty input', ([],), [None, []]),
('control: descending sizes',
([[7, 1, 3], [2, 1, 0], [4, 1, 1]],),
[0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]])],
[('control: mixed households',
([[4, 1, 2], [3, 1, 0], [5, 2, 1], [2, 1, 1]],),
[0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]]),
('control: single-person household', ([[1, 1, 0], [2, 1, 1]],), [1.0, [[2, 1.0]]]),
('regression: data error secondary too high',
([[3, 1, 4], [3, 1, 1], [5, 1, 2]],),
[0.5, [[3, 0.5], [5, 0.5]]]),
('control: empty input', ([],), [None, []]),
('control: descending sizes',
([[7, 1, 3], [2, 1, 0], [4, 1, 1]],),
[0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]]),
('control: all index', ([[2, 2, 0], [3, 3, 0]],), [None, []]),
('control: large and small',
([[8, 1, 6], [2, 1, 1], [8, 2, 1], [3, 1, 0]],),
[0.5, [[2, 1.0], [3, 0.0], [8, 0.538462]]])],
[('control: mixed households',
([[4, 1, 2], [3, 1, 0], [5, 2, 1], [2, 1, 1]],),
[0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]]),
('control: two index cases', ([[6, 2, 3], [6, 1, 1], [3, 1, 1]],), [0.454545, [[3, 0.5], [6, 0.444444]]]),
('control: no index household', ([[4, 0, 0], [4, 1, 1], [3, 1, 2]],), [0.6, [[3, 1.0], [4, 0.333333]]]),
('regression: data error secondary too high',
([[3, 1, 4], [3, 1, 1], [5, 1, 2]],),
[0.5, [[3, 0.5], [5, 0.5]]]),
('control: descending sizes',
([[7, 1, 3], [2, 1, 0], [4, 1, 1]],),
[0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]]),
('control: all index', ([[2, 2, 0], [3, 3, 0]],), [None, []]),
('control: large and small',
([[8, 1, 6], [2, 1, 1], [8, 2, 1], [3, 1, 0]],),
[0.5, [[2, 1.0], [3, 0.0], [8, 0.538462]]])],
[('control: mixed households',
([[4, 1, 2], [3, 1, 0], [5, 2, 1], [2, 1, 1]],),
[0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]]),
('control: two index cases', ([[6, 2, 3], [6, 1, 1], [3, 1, 1]],), [0.454545, [[3, 0.5], [6, 0.444444]]]),
('control: no index household', ([[4, 0, 0], [4, 1, 1], [3, 1, 2]],), [0.6, [[3, 1.0], [4, 0.333333]]]),
('control: single-person household', ([[1, 1, 0], [2, 1, 1]],), [1.0, [[2, 1.0]]]),
('regression: data error secondary too high',
([[3, 1, 4], [3, 1, 1], [5, 1, 2]],),
[0.5, [[3, 0.5], [5, 0.5]]]),
('control: empty input', ([],), [None, []]),
('control: descending sizes',
([[7, 1, 3], [2, 1, 0], [4, 1, 1]],),
[0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]])],
[('control: mixed households',
([[4, 1, 2], [3, 1, 0], [5, 2, 1], [2, 1, 1]],),
[0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]]),
('control: single-person household', ([[1, 1, 0], [2, 1, 1]],), [1.0, [[2, 1.0]]]),
('regression: data error secondary too high',
([[3, 1, 4], [3, 1, 1], [5, 1, 2]],),
[0.5, [[3, 0.5], [5, 0.5]]]),
('control: empty input', ([],), [None, []]),
('control: descending sizes',
([[7, 1, 3], [2, 1, 0], [4, 1, 1]],),
[0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]]),
('control: all index', ([[2, 2, 0], [3, 3, 0]],), [None, []]),
('control: large and small',
([[8, 1, 6], [2, 1, 1], [8, 2, 1], [3, 1, 0]],),
[0.5, [[2, 1.0], [3, 0.0], [8, 0.538462]]])]]
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 |
|---|---|---|---|
| control: mixed households | [0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]] | [0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]] | Passed |
| control: two index cases | [0.454545, [[3, 0.5], [6, 0.444444]]] | [0.454545, [[3, 0.5], [6, 0.444444]]] | Passed |
| control: no index household | [0.6, [[3, 1.0], [4, 0.333333]]] | [0.6, [[3, 1.0], [4, 0.333333]]] | Passed |
| control: single-person household | [1.0, [[2, 1.0]]] | [1.0, [[2, 1.0]]] | Passed |
| regression: data error secondary too high | [0.625, [[3, 0.75], [5, 0.5]]] | [0.5, [[3, 0.5], [5, 0.5]]] | Failed |
| control: empty input | [None, []] | [None, []] | Passed |
| control: descending sizes | [0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]] | [0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]] | Passed |
SHA-256 / a5172652c59e7b15ee06256415373417c4df9adc535a1e441c063a8ed73bc066
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(households):
num = 0
den = 0
by_size = {}
for size, index, secondary in households:
at_risk = size - index
if index < 1 or at_risk <= 0:
continue
if secondary > at_risk:
continue
num += secondary
den += at_risk
a, b = by_size.get(size, (0, 0))
by_size[size] = (a + secondary, b + at_risk)
overall = round(num / den, 6) if den else None
table = [[k, round(a / b, 6)] for k, (a, b) in sorted(by_size.items())]
return [overall, table]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control: mixed households',
([[4, 1, 2], [3, 1, 0], [5, 2, 1], [2, 1, 1]],),
[0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]]),
('control: two index cases', ([[6, 2, 3], [6, 1, 1], [3, 1, 1]],), [0.454545, [[3, 0.5], [6, 0.444444]]]),
('control: no index household', ([[4, 0, 0], [4, 1, 1], [3, 1, 2]],), [0.6, [[3, 1.0], [4, 0.333333]]]),
('control: single-person household', ([[1, 1, 0], [2, 1, 1]],), [1.0, [[2, 1.0]]]),
('regression: data error secondary too high',
([[3, 1, 4], [3, 1, 1], [5, 1, 2]],),
[0.5, [[3, 0.5], [5, 0.5]]]),
('control: empty input', ([],), [None, []]),
('control: descending sizes',
([[7, 1, 3], [2, 1, 0], [4, 1, 1]],),
[0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]])],
[('control: mixed households',
([[4, 1, 2], [3, 1, 0], [5, 2, 1], [2, 1, 1]],),
[0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]]),
('control: single-person household', ([[1, 1, 0], [2, 1, 1]],), [1.0, [[2, 1.0]]]),
('regression: data error secondary too high',
([[3, 1, 4], [3, 1, 1], [5, 1, 2]],),
[0.5, [[3, 0.5], [5, 0.5]]]),
('control: empty input', ([],), [None, []]),
('control: descending sizes',
([[7, 1, 3], [2, 1, 0], [4, 1, 1]],),
[0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]]),
('control: all index', ([[2, 2, 0], [3, 3, 0]],), [None, []]),
('control: large and small',
([[8, 1, 6], [2, 1, 1], [8, 2, 1], [3, 1, 0]],),
[0.5, [[2, 1.0], [3, 0.0], [8, 0.538462]]])],
[('control: mixed households',
([[4, 1, 2], [3, 1, 0], [5, 2, 1], [2, 1, 1]],),
[0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]]),
('control: two index cases', ([[6, 2, 3], [6, 1, 1], [3, 1, 1]],), [0.454545, [[3, 0.5], [6, 0.444444]]]),
('control: no index household', ([[4, 0, 0], [4, 1, 1], [3, 1, 2]],), [0.6, [[3, 1.0], [4, 0.333333]]]),
('regression: data error secondary too high',
([[3, 1, 4], [3, 1, 1], [5, 1, 2]],),
[0.5, [[3, 0.5], [5, 0.5]]]),
('control: descending sizes',
([[7, 1, 3], [2, 1, 0], [4, 1, 1]],),
[0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]]),
('control: all index', ([[2, 2, 0], [3, 3, 0]],), [None, []]),
('control: large and small',
([[8, 1, 6], [2, 1, 1], [8, 2, 1], [3, 1, 0]],),
[0.5, [[2, 1.0], [3, 0.0], [8, 0.538462]]])],
[('control: mixed households',
([[4, 1, 2], [3, 1, 0], [5, 2, 1], [2, 1, 1]],),
[0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]]),
('control: two index cases', ([[6, 2, 3], [6, 1, 1], [3, 1, 1]],), [0.454545, [[3, 0.5], [6, 0.444444]]]),
('control: no index household', ([[4, 0, 0], [4, 1, 1], [3, 1, 2]],), [0.6, [[3, 1.0], [4, 0.333333]]]),
('control: single-person household', ([[1, 1, 0], [2, 1, 1]],), [1.0, [[2, 1.0]]]),
('regression: data error secondary too high',
([[3, 1, 4], [3, 1, 1], [5, 1, 2]],),
[0.5, [[3, 0.5], [5, 0.5]]]),
('control: empty input', ([],), [None, []]),
('control: descending sizes',
([[7, 1, 3], [2, 1, 0], [4, 1, 1]],),
[0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]])],
[('control: mixed households',
([[4, 1, 2], [3, 1, 0], [5, 2, 1], [2, 1, 1]],),
[0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]]),
('control: single-person household', ([[1, 1, 0], [2, 1, 1]],), [1.0, [[2, 1.0]]]),
('regression: data error secondary too high',
([[3, 1, 4], [3, 1, 1], [5, 1, 2]],),
[0.5, [[3, 0.5], [5, 0.5]]]),
('control: empty input', ([],), [None, []]),
('control: descending sizes',
([[7, 1, 3], [2, 1, 0], [4, 1, 1]],),
[0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]]),
('control: all index', ([[2, 2, 0], [3, 3, 0]],), [None, []]),
('control: large and small',
([[8, 1, 6], [2, 1, 1], [8, 2, 1], [3, 1, 0]],),
[0.5, [[2, 1.0], [3, 0.0], [8, 0.538462]]])]]
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 |
|---|---|---|---|
| control: mixed households | [0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]] | [0.444444, [[2, 1.0], [3, 0.0], [4, 0.666667], [5, 0.333333]]] | Passed |
| control: two index cases | [0.454545, [[3, 0.5], [6, 0.444444]]] | [0.454545, [[3, 0.5], [6, 0.444444]]] | Passed |
| control: no index household | [0.6, [[3, 1.0], [4, 0.333333]]] | [0.6, [[3, 1.0], [4, 0.333333]]] | Passed |
| control: single-person household | [1.0, [[2, 1.0]]] | [1.0, [[2, 1.0]]] | Passed |
| regression: data error secondary too high | [0.5, [[3, 0.5], [5, 0.5]]] | [0.5, [[3, 0.5], [5, 0.5]]] | Passed |
| control: empty input | [None, []] | [None, []] | Passed |
| control: descending sizes | [0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]] | [0.4, [[2, 0.0], [4, 0.333333], [7, 0.5]]] | Passed |
SHA-256 / 4042ba9927c9a3e3951d6eddfaf040e88e598a939336947d9deafc05d7e04efa
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:32.646072+00:00.
Case digest / fdacac65afaaf37334efe3cd6f58ff5434c11799a99369788d0ce171c4a68fb2