FA-63716 / Actuarial life tables / Open access
Double-decrement death and lapse table: Deaths are reduced by the full lapse rate · case 01
Dependent death rates are too low.
ROOT CAUSE
The competing lapse rate is applied in full rather than half.
VERIFIED REPAIR
Use q'd(1-q'w/2).
Unsuccessful approach: Subtracting half the lapse rate is not the product form.
Case contract
Input qd, qw (associated single-decrement rates per 100000, equal lengths else 'length mismatch'), timing udd|eoy, radix. UDD in each decrement: q(d)=q'd(1-q'w/2), q(w)=q'w(1-q'd/2). eoy (lapses at year end): q(d)=q'd, q(w)=(1-q'd)q'w. Each year counts are rounded half-up and subtracted from l. Return [[deaths, lapses] per year, final l].
Why this case matters
Life-table arithmetic compounds across ages, so one misplaced index or assumption shifts every downstream value.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(x):
if len(x['qd'])!=len(x['qw']): return 'length mismatch'
l=x['radix']; out=[]
for qd,qw in zip(x['qd'],x['qw']):
qd=Fraction(qd,100000); qw=Fraction(qw,100000)
if x['timing']=='udd':
a=qd*(1-qw); b=qw*(1-qd/2)
else:
a=qd; b=(1-qd)*qw
dd=math.floor(l*a+Fraction(1,2)); ww=math.floor(l*b+Fraction(1,2))
out.append([dd,ww]); l=l-dd-ww
return [out,l]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['udd decrement table 0', {'qd': [1141, 1494, 1970, 2562, 3342], 'qw': [11888, 13297, 3547, 10964, 8496], 'timing': 'udd', 'radix': 37055}, [[[398, 4380], [450, 4260], [533, 968], [631, 2821], [724, 1889]], 20001]], ['udd decrement table 1', {'qd': [1456, 1926, 2551, 3360], 'qw': [9249, 5186, 14177, 11845], 'timing': 'udd', 'radix': 76371}, [[[1061, 7012], [1281, 3508], [1505, 8889], [1679, 6186]], 45250]], ['eoy decrement table 2', {'qd': [1176, 1554, 2037], 'qw': [5555, 4516, 10904], 'timing': 'eoy', 'radix': 17793}, [[[209, 977], [258, 738], [318, 1668]], 13625]], ['eoy decrement table 3', {'qd': [914, 1233, 1614, 2119, 2784, 3651], 'qw': [10472, 5562, 3304, 9768, 14288, 3207], 'timing': 'eoy', 'radix': 55727}, [[[509, 5782], [610, 2716], [744, 1499], [930, 4194], [1079, 5381], [1179, 998]], 30106]], ['high lapse udd', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'udd', 'radix': 10007}, [[[1601, 3603], [1081, 2041]], 1681]], ['high lapse year-end', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'eoy', 'radix': 10007}, [[[2001, 3202], [1441, 1681]], 1682]], ['length mismatch', {'qd': [1000, 2000, 3000], 'qw': [5000, 6000], 'timing': 'udd', 'radix': 1000}, 'length mismatch'], ['lapse list longer', {'qd': [1000], 'qw': [5000, 6000], 'timing': 'eoy', 'radix': 1000}, 'length mismatch'], ['long udd table', {'qd': [1238, 1628, 2136, 2796, 3668, 4778, 6251, 8129], 'qw': [3279, 5982, 12121, 4971, 8271, 12739, 8017, 14793], 'timing': 'udd', 'radix': 100000}, [[[1218, 3259], [1509, 5668], [1773, 10594], [2072, 3724], [2468, 5698], [2774, 7712], [3092, 4002], [3345, 6306]], 34786]]], [['udd decrement table 0', {'qd': [930, 1213, 1603], 'qw': [13393, 10163, 5206], 'timing': 'udd', 'radix': 54431}, [[[472, 7256], [538, 4718], [647, 2140]], 38660]], ['udd decrement table 1', {'qd': [755, 1006, 1311, 1719], 'qw': [10661, 14309, 10319, 6918], 'timing': 'udd', 'radix': 33489}, [[[239, 3557], [277, 4227], [313, 2582], [370, 1529]], 20395]], ['eoy decrement table 2', {'qd': [1190, 1564, 2044, 2694, 3536, 4612], 'qw': [4523, 14857, 3747, 14471, 13570, 14825], 'timing': 'eoy', 'radix': 14539}, [[[173, 650], [215, 2006], [235, 422], [292, 1526], [319, 1181], [347, 1063]], 6110]], ['eoy decrement table 3', {'qd': [1410, 1864, 2446], 'qw': [11121, 9322, 11894], 'timing': 'eoy', 'radix': 40451}, [[[570, 4435], [661, 3243], [772, 3660]], 27110]], ['high lapse udd', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'udd', 'radix': 10014}, [[[1602, 3605], [1082, 2043]], 1682]], ['high lapse year-end', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'eoy', 'radix': 10014}, [[[2003, 3204], [1442, 1682]], 1683]], ['length mismatch', {'qd': [1000, 2000, 3000], 'qw': [5000, 6000], 'timing': 'udd', 'radix': 1000}, 'length mismatch'], ['lapse list longer', {'qd': [1000], 'qw': [5000, 6000], 'timing': 'eoy', 'radix': 1000}, 'length mismatch'], ['long udd table', {'qd': [828, 1080, 1427, 1896, 2502, 3265, 4277, 5590], 'qw': [6711, 4424, 4588, 10512, 13157, 5312, 3373, 8767], 'timing': 'udd', 'radix': 100000}, [[[800, 6683], [977, 4071], [1220, 3984], [1478, 8566], [1688, 9383], [1944, 3195], [2355, 1849], [2769, 4415]], 44623]]], [['udd decrement table 0', {'qd': [1079, 1440, 1900, 2490], 'qw': [12382, 12480, 9166, 14124], 'timing': 'udd', 'radix': 97739}, [[[989, 12037], [1144, 10496], [1325, 6634], [1507, 9082]], 54525]], ['udd decrement table 1', {'qd': [926, 1207, 1573, 2050], 'qw': [5818, 14108, 5594, 7476], 'timing': 'udd', 'radix': 58255}, [[[524, 3374], [610, 7622], [705, 2560], [846, 3171]], 38843]], ['eoy decrement table 2', {'qd': [1496, 1992, 2610, 3423], 'qw': [7077, 5443, 10634, 8058], 'timing': 'eoy', 'radix': 97309}, [[[1456, 6784], [1774, 4751], [2154, 8549], [2459, 5591]], 63791]], ['eoy decrement table 3', {'qd': [1123, 1473, 1932], 'qw': [9193, 3282, 4474], 'timing': 'eoy', 'radix': 99825}, [[[1121, 9074], [1320, 2898], [1650, 3748]], 80014]], ['high lapse udd', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'udd', 'radix': 10021}, [[[1603, 3608], [1082, 2044]], 1684]], ['high lapse year-end', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'eoy', 'radix': 10021}, [[[2004, 3207], [1443, 1684]], 1683]], ['length mismatch', {'qd': [1000, 2000, 3000], 'qw': [5000, 6000], 'timing': 'udd', 'radix': 1000}, 'length mismatch'], ['lapse list longer', {'qd': [1000], 'qw': [5000, 6000], 'timing': 'eoy', 'radix': 1000}, 'length mismatch'], ['long udd table', {'qd': [1439, 1878, 2462, 3201, 4200, 5488, 7157, 9346], 'qw': [9710, 12625, 8404, 8046, 3063, 8590, 14798, 7301], 'timing': 'udd', 'radix': 100000}, [[[1369, 9640], [1566, 11130], [1799, 6333], [2094, 5397], [2509, 1819], [2959, 4707], [3226, 6946], [3467, 2680]], 32359]]], [['udd decrement table 0', {'qd': [529, 709, 958], 'qw': [13843, 8215, 5302], 'timing': 'udd', 'radix': 93791}, [[[462, 12949], [546, 6580], [683, 3865]], 68706]], ['udd decrement table 1', {'qd': [846, 1101, 1460, 1909, 2488, 3271], 'qw': [8145, 7576, 8774, 6560, 7393, 6414], 'timing': 'udd', 'radix': 15725}, [[[128, 1275], [152, 1079], [183, 1140], [217, 765], [258, 787], [308, 615]], 8818]], ['eoy decrement table 2', {'qd': [940, 1250, 1628], 'qw': [8737, 12691, 6270], 'timing': 'eoy', 'radix': 35371}, [[[332, 3061], [400, 4008], [449, 1700]], 25421]], ['eoy decrement table 3', {'qd': [649, 890, 1181, 1569, 2056], 'qw': [3329, 10015, 13961, 3880, 4359], 'timing': 'eoy', 'radix': 51217}, [[[332, 1694], [438, 4883], [518, 6052], [585, 1425], [726, 1507]], 33057]], ['high lapse udd', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'udd', 'radix': 10028}, [[[1604, 3610], [1083, 2046]], 1685]], ['high lapse year-end', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'eoy', 'radix': 10028}, [[[2006, 3209], [1444, 1685]], 1684]], ['length mismatch', {'qd': [1000, 2000, 3000], 'qw': [5000, 6000], 'timing': 'udd', 'radix': 1000}, 'length mismatch'], ['lapse list longer', {'qd': [1000], 'qw': [5000, 6000], 'timing': 'eoy', 'radix': 1000}, 'length mismatch'], ['long udd table', {'qd': [1103, 1461, 1917, 2496, 3281, 4301, 5597, 7311], 'qw': [12505, 9020, 5190, 7658, 5537, 11768, 6537, 14241], 'timing': 'udd', 'radix': 100000}, [[[1034, 12436], [1207, 7748], [1449, 3988], [1732, 5455], [2072, 3537], [2402, 6833], [2713, 3184], [3002, 6066]], 35142]]], [['udd decrement table 0', {'qd': [507, 663, 903, 1187, 1545, 2051], 'qw': [8115, 12097, 11178, 14750, 10909, 8914], 'timing': 'udd', 'radix': 91817}, [[[447, 7432], [523, 10120], [625, 8156], [709, 9459], [794, 5883], [934, 4206]], 42529]], ['udd decrement table 1', {'qd': [908, 1197, 1597, 2118, 2774], 'qw': [5334, 8356, 12199, 5950, 3708], 'timing': 'udd', 'radix': 44847}, [[[396, 2381], [483, 3494], [571, 4610], [676, 1938], [825, 1108]], 28365]], ['eoy decrement table 2', {'qd': [731, 983, 1287, 1699, 2237, 2954], 'qw': [13569, 10174, 10715, 12076, 6449, 3074], 'timing': 'eoy', 'radix': 91077}, [[[666, 12268], [768, 7872], [895, 7351], [1041, 7272], [1184, 3338], [1430, 1445]], 45547]], ['eoy decrement table 3', {'qd': [883, 1167, 1548], 'qw': [3198, 5134, 5923], 'timing': 'eoy', 'radix': 23497}, [[[207, 745], [263, 1144], [327, 1233]], 19578]], ['high lapse udd', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'udd', 'radix': 10035}, [[[1606, 3613], [1084, 2047]], 1685]], ['high lapse year-end', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'eoy', 'radix': 10035}, [[[2007, 3211], [1445, 1686]], 1686]], ['length mismatch', {'qd': [1000, 2000, 3000], 'qw': [5000, 6000], 'timing': 'udd', 'radix': 1000}, 'length mismatch'], ['lapse list longer', {'qd': [1000], 'qw': [5000, 6000], 'timing': 'eoy', 'radix': 1000}, 'length mismatch'], ['long udd table', {'qd': [1256, 1663, 2199, 2866, 3731, 4859, 6351, 8258], 'qw': [8556, 10289, 12789, 3526, 8367, 5298, 13350, 9941], 'timing': 'udd', 'radix': 100000}, [[[1202, 8502], [1424, 9213], [1640, 10076], [1913, 2361], [2276, 5228], [2657, 2903], [2999, 6541], [3223, 3914]], 33928]]]]
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 |
|---|---|---|---|
| udd decrement table 0 | [[[373, 4380], [418, 4263], [525, 970], [596, 2828], [694, 1897]], 20111] | [[[398, 4380], [450, 4260], [533, 968], [631, 2821], [724, 1889]], 20001] | Failed |
| udd decrement table 1 | [[[1009, 7012], [1248, 3510], [1392, 8900], [1579, 6207]], 45514] | [[[1061, 7012], [1281, 3508], [1505, 8889], [1679, 6186]], 45250] | Failed |
| eoy decrement table 2 | [[[209, 977], [258, 738], [318, 1668]], 13625] | [[[209, 977], [258, 738], [318, 1668]], 13625] | Passed |
| eoy decrement table 3 | [[[509, 5782], [610, 2716], [744, 1499], [930, 4194], [1079, 5381], [1179, 998]], 30106] | [[[509, 5782], [610, 2716], [744, 1499], [930, 4194], [1079, 5381], [1179, 998]], 30106] | Passed |
| high lapse udd | [[[1201, 3603], [780, 2211]], 2212] | [[[1601, 3603], [1081, 2041]], 1681] | Failed |
| high lapse year-end | [[[2001, 3202], [1441, 1681]], 1682] | [[[2001, 3202], [1441, 1681]], 1682] | Passed |
| length mismatch | length mismatch | length mismatch | Passed |
| lapse list longer | length mismatch | length mismatch | Passed |
| long udd table | [[[1197, 3259], [1462, 5669], [1660, 10602], [2023, 3733], [2369, 5716], [2598, 7748], [2988, 4036], [3113, 6378]], 35449] | [[[1218, 3259], [1509, 5668], [1773, 10594], [2072, 3724], [2468, 5698], [2774, 7712], [3092, 4002], [3345, 6306]], 34786] | Failed |
SHA-256 / 128648f121f1ae2cdac7ac5aab291a3b1116bd04b9dd00c5b9a239142cd81b37
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(x):
if len(x['qd'])!=len(x['qw']): return 'length mismatch'
l=x['radix']; out=[]
for qd,qw in zip(x['qd'],x['qw']):
qd=Fraction(qd,100000); qw=Fraction(qw,100000)
if x['timing']=='udd':
a=qd-qw/2; b=qw*(1-qd/2)
else:
a=qd; b=(1-qd)*qw
dd=math.floor(l*a+Fraction(1,2)); ww=math.floor(l*b+Fraction(1,2))
out.append([dd,ww]); l=l-dd-ww
return [out,l]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['udd decrement table 0', {'qd': [1141, 1494, 1970, 2562, 3342], 'qw': [11888, 13297, 3547, 10964, 8496], 'timing': 'udd', 'radix': 37055}, [[[398, 4380], [450, 4260], [533, 968], [631, 2821], [724, 1889]], 20001]], ['udd decrement table 1', {'qd': [1456, 1926, 2551, 3360], 'qw': [9249, 5186, 14177, 11845], 'timing': 'udd', 'radix': 76371}, [[[1061, 7012], [1281, 3508], [1505, 8889], [1679, 6186]], 45250]], ['eoy decrement table 2', {'qd': [1176, 1554, 2037], 'qw': [5555, 4516, 10904], 'timing': 'eoy', 'radix': 17793}, [[[209, 977], [258, 738], [318, 1668]], 13625]], ['eoy decrement table 3', {'qd': [914, 1233, 1614, 2119, 2784, 3651], 'qw': [10472, 5562, 3304, 9768, 14288, 3207], 'timing': 'eoy', 'radix': 55727}, [[[509, 5782], [610, 2716], [744, 1499], [930, 4194], [1079, 5381], [1179, 998]], 30106]], ['high lapse udd', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'udd', 'radix': 10007}, [[[1601, 3603], [1081, 2041]], 1681]], ['high lapse year-end', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'eoy', 'radix': 10007}, [[[2001, 3202], [1441, 1681]], 1682]], ['length mismatch', {'qd': [1000, 2000, 3000], 'qw': [5000, 6000], 'timing': 'udd', 'radix': 1000}, 'length mismatch'], ['lapse list longer', {'qd': [1000], 'qw': [5000, 6000], 'timing': 'eoy', 'radix': 1000}, 'length mismatch'], ['long udd table', {'qd': [1238, 1628, 2136, 2796, 3668, 4778, 6251, 8129], 'qw': [3279, 5982, 12121, 4971, 8271, 12739, 8017, 14793], 'timing': 'udd', 'radix': 100000}, [[[1218, 3259], [1509, 5668], [1773, 10594], [2072, 3724], [2468, 5698], [2774, 7712], [3092, 4002], [3345, 6306]], 34786]]], [['udd decrement table 0', {'qd': [930, 1213, 1603], 'qw': [13393, 10163, 5206], 'timing': 'udd', 'radix': 54431}, [[[472, 7256], [538, 4718], [647, 2140]], 38660]], ['udd decrement table 1', {'qd': [755, 1006, 1311, 1719], 'qw': [10661, 14309, 10319, 6918], 'timing': 'udd', 'radix': 33489}, [[[239, 3557], [277, 4227], [313, 2582], [370, 1529]], 20395]], ['eoy decrement table 2', {'qd': [1190, 1564, 2044, 2694, 3536, 4612], 'qw': [4523, 14857, 3747, 14471, 13570, 14825], 'timing': 'eoy', 'radix': 14539}, [[[173, 650], [215, 2006], [235, 422], [292, 1526], [319, 1181], [347, 1063]], 6110]], ['eoy decrement table 3', {'qd': [1410, 1864, 2446], 'qw': [11121, 9322, 11894], 'timing': 'eoy', 'radix': 40451}, [[[570, 4435], [661, 3243], [772, 3660]], 27110]], ['high lapse udd', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'udd', 'radix': 10014}, [[[1602, 3605], [1082, 2043]], 1682]], ['high lapse year-end', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'eoy', 'radix': 10014}, [[[2003, 3204], [1442, 1682]], 1683]], ['length mismatch', {'qd': [1000, 2000, 3000], 'qw': [5000, 6000], 'timing': 'udd', 'radix': 1000}, 'length mismatch'], ['lapse list longer', {'qd': [1000], 'qw': [5000, 6000], 'timing': 'eoy', 'radix': 1000}, 'length mismatch'], ['long udd table', {'qd': [828, 1080, 1427, 1896, 2502, 3265, 4277, 5590], 'qw': [6711, 4424, 4588, 10512, 13157, 5312, 3373, 8767], 'timing': 'udd', 'radix': 100000}, [[[800, 6683], [977, 4071], [1220, 3984], [1478, 8566], [1688, 9383], [1944, 3195], [2355, 1849], [2769, 4415]], 44623]]], [['udd decrement table 0', {'qd': [1079, 1440, 1900, 2490], 'qw': [12382, 12480, 9166, 14124], 'timing': 'udd', 'radix': 97739}, [[[989, 12037], [1144, 10496], [1325, 6634], [1507, 9082]], 54525]], ['udd decrement table 1', {'qd': [926, 1207, 1573, 2050], 'qw': [5818, 14108, 5594, 7476], 'timing': 'udd', 'radix': 58255}, [[[524, 3374], [610, 7622], [705, 2560], [846, 3171]], 38843]], ['eoy decrement table 2', {'qd': [1496, 1992, 2610, 3423], 'qw': [7077, 5443, 10634, 8058], 'timing': 'eoy', 'radix': 97309}, [[[1456, 6784], [1774, 4751], [2154, 8549], [2459, 5591]], 63791]], ['eoy decrement table 3', {'qd': [1123, 1473, 1932], 'qw': [9193, 3282, 4474], 'timing': 'eoy', 'radix': 99825}, [[[1121, 9074], [1320, 2898], [1650, 3748]], 80014]], ['high lapse udd', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'udd', 'radix': 10021}, [[[1603, 3608], [1082, 2044]], 1684]], ['high lapse year-end', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'eoy', 'radix': 10021}, [[[2004, 3207], [1443, 1684]], 1683]], ['length mismatch', {'qd': [1000, 2000, 3000], 'qw': [5000, 6000], 'timing': 'udd', 'radix': 1000}, 'length mismatch'], ['lapse list longer', {'qd': [1000], 'qw': [5000, 6000], 'timing': 'eoy', 'radix': 1000}, 'length mismatch'], ['long udd table', {'qd': [1439, 1878, 2462, 3201, 4200, 5488, 7157, 9346], 'qw': [9710, 12625, 8404, 8046, 3063, 8590, 14798, 7301], 'timing': 'udd', 'radix': 100000}, [[[1369, 9640], [1566, 11130], [1799, 6333], [2094, 5397], [2509, 1819], [2959, 4707], [3226, 6946], [3467, 2680]], 32359]]], [['udd decrement table 0', {'qd': [529, 709, 958], 'qw': [13843, 8215, 5302], 'timing': 'udd', 'radix': 93791}, [[[462, 12949], [546, 6580], [683, 3865]], 68706]], ['udd decrement table 1', {'qd': [846, 1101, 1460, 1909, 2488, 3271], 'qw': [8145, 7576, 8774, 6560, 7393, 6414], 'timing': 'udd', 'radix': 15725}, [[[128, 1275], [152, 1079], [183, 1140], [217, 765], [258, 787], [308, 615]], 8818]], ['eoy decrement table 2', {'qd': [940, 1250, 1628], 'qw': [8737, 12691, 6270], 'timing': 'eoy', 'radix': 35371}, [[[332, 3061], [400, 4008], [449, 1700]], 25421]], ['eoy decrement table 3', {'qd': [649, 890, 1181, 1569, 2056], 'qw': [3329, 10015, 13961, 3880, 4359], 'timing': 'eoy', 'radix': 51217}, [[[332, 1694], [438, 4883], [518, 6052], [585, 1425], [726, 1507]], 33057]], ['high lapse udd', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'udd', 'radix': 10028}, [[[1604, 3610], [1083, 2046]], 1685]], ['high lapse year-end', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'eoy', 'radix': 10028}, [[[2006, 3209], [1444, 1685]], 1684]], ['length mismatch', {'qd': [1000, 2000, 3000], 'qw': [5000, 6000], 'timing': 'udd', 'radix': 1000}, 'length mismatch'], ['lapse list longer', {'qd': [1000], 'qw': [5000, 6000], 'timing': 'eoy', 'radix': 1000}, 'length mismatch'], ['long udd table', {'qd': [1103, 1461, 1917, 2496, 3281, 4301, 5597, 7311], 'qw': [12505, 9020, 5190, 7658, 5537, 11768, 6537, 14241], 'timing': 'udd', 'radix': 100000}, [[[1034, 12436], [1207, 7748], [1449, 3988], [1732, 5455], [2072, 3537], [2402, 6833], [2713, 3184], [3002, 6066]], 35142]]], [['udd decrement table 0', {'qd': [507, 663, 903, 1187, 1545, 2051], 'qw': [8115, 12097, 11178, 14750, 10909, 8914], 'timing': 'udd', 'radix': 91817}, [[[447, 7432], [523, 10120], [625, 8156], [709, 9459], [794, 5883], [934, 4206]], 42529]], ['udd decrement table 1', {'qd': [908, 1197, 1597, 2118, 2774], 'qw': [5334, 8356, 12199, 5950, 3708], 'timing': 'udd', 'radix': 44847}, [[[396, 2381], [483, 3494], [571, 4610], [676, 1938], [825, 1108]], 28365]], ['eoy decrement table 2', {'qd': [731, 983, 1287, 1699, 2237, 2954], 'qw': [13569, 10174, 10715, 12076, 6449, 3074], 'timing': 'eoy', 'radix': 91077}, [[[666, 12268], [768, 7872], [895, 7351], [1041, 7272], [1184, 3338], [1430, 1445]], 45547]], ['eoy decrement table 3', {'qd': [883, 1167, 1548], 'qw': [3198, 5134, 5923], 'timing': 'eoy', 'radix': 23497}, [[[207, 745], [263, 1144], [327, 1233]], 19578]], ['high lapse udd', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'udd', 'radix': 10035}, [[[1606, 3613], [1084, 2047]], 1685]], ['high lapse year-end', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'eoy', 'radix': 10035}, [[[2007, 3211], [1445, 1686]], 1686]], ['length mismatch', {'qd': [1000, 2000, 3000], 'qw': [5000, 6000], 'timing': 'udd', 'radix': 1000}, 'length mismatch'], ['lapse list longer', {'qd': [1000], 'qw': [5000, 6000], 'timing': 'eoy', 'radix': 1000}, 'length mismatch'], ['long udd table', {'qd': [1256, 1663, 2199, 2866, 3731, 4859, 6351, 8258], 'qw': [8556, 10289, 12789, 3526, 8367, 5298, 13350, 9941], 'timing': 'udd', 'radix': 100000}, [[[1202, 8502], [1424, 9213], [1640, 10076], [1913, 2361], [2276, 5228], [2657, 2903], [2999, 6541], [3223, 3914]], 33928]]]]
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 |
|---|---|---|---|
| udd decrement table 0 | [[[-1780, 4380], [-1776, 4547], [62, 1113], [-891, 3302], [-255, 2347]], 26006] | [[[398, 4380], [450, 4260], [533, 968], [631, 2821], [724, 1889]], 20001] | Failed |
| udd decrement table 1 | [[[-2420, 7012], [-479, 3687], [-3111, 9597], [-1591, 7230]], 56446] | [[[1061, 7012], [1281, 3508], [1505, 8889], [1679, 6186]], 45250] | Failed |
| eoy decrement table 2 | [[[209, 977], [258, 738], [318, 1668]], 13625] | [[[209, 977], [258, 738], [318, 1668]], 13625] | Passed |
| eoy decrement table 3 | [[[509, 5782], [610, 2716], [744, 1499], [930, 4194], [1079, 5381], [1179, 998]], 30106] | [[[509, 5782], [610, 2716], [744, 1499], [930, 4194], [1079, 5381], [1179, 998]], 30106] | Passed |
| high lapse udd | [[[0, 3603], [320, 2722]], 3362] | [[[1601, 3603], [1081, 2041]], 1681] | Failed |
| high lapse year-end | [[[2001, 3202], [1441, 1681]], 1682] | [[[2001, 3202], [1441, 1681]], 1682] | Passed |
| length mismatch | length mismatch | length mismatch | Passed |
| lapse list longer | length mismatch | length mismatch | Passed |
| long udd table | [[[-401, 3259], [-1324, 5764], [-3638, 11116], [265, 4177], [-378, 6559], [-1187, 9276], [1492, 5166], [438, 8494]], 50922] | [[[1218, 3259], [1509, 5668], [1773, 10594], [2072, 3724], [2468, 5698], [2774, 7712], [3092, 4002], [3345, 6306]], 34786] | Failed |
SHA-256 / 5130ee4d09978d25e340ee116c383e10e42e5a3d7f304b07aa7bfa6e2c3092ae
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(x):
if len(x['qd'])!=len(x['qw']): return 'length mismatch'
l=x['radix']; out=[]
for qd,qw in zip(x['qd'],x['qw']):
qd=Fraction(qd,100000); qw=Fraction(qw,100000)
if x['timing']=='udd':
a=qd*(1-qw/2); b=qw*(1-qd/2)
else:
a=qd; b=(1-qd)*qw
dd=math.floor(l*a+Fraction(1,2)); ww=math.floor(l*b+Fraction(1,2))
out.append([dd,ww]); l=l-dd-ww
return [out,l]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['udd decrement table 0', {'qd': [1141, 1494, 1970, 2562, 3342], 'qw': [11888, 13297, 3547, 10964, 8496], 'timing': 'udd', 'radix': 37055}, [[[398, 4380], [450, 4260], [533, 968], [631, 2821], [724, 1889]], 20001]], ['udd decrement table 1', {'qd': [1456, 1926, 2551, 3360], 'qw': [9249, 5186, 14177, 11845], 'timing': 'udd', 'radix': 76371}, [[[1061, 7012], [1281, 3508], [1505, 8889], [1679, 6186]], 45250]], ['eoy decrement table 2', {'qd': [1176, 1554, 2037], 'qw': [5555, 4516, 10904], 'timing': 'eoy', 'radix': 17793}, [[[209, 977], [258, 738], [318, 1668]], 13625]], ['eoy decrement table 3', {'qd': [914, 1233, 1614, 2119, 2784, 3651], 'qw': [10472, 5562, 3304, 9768, 14288, 3207], 'timing': 'eoy', 'radix': 55727}, [[[509, 5782], [610, 2716], [744, 1499], [930, 4194], [1079, 5381], [1179, 998]], 30106]], ['high lapse udd', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'udd', 'radix': 10007}, [[[1601, 3603], [1081, 2041]], 1681]], ['high lapse year-end', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'eoy', 'radix': 10007}, [[[2001, 3202], [1441, 1681]], 1682]], ['length mismatch', {'qd': [1000, 2000, 3000], 'qw': [5000, 6000], 'timing': 'udd', 'radix': 1000}, 'length mismatch'], ['lapse list longer', {'qd': [1000], 'qw': [5000, 6000], 'timing': 'eoy', 'radix': 1000}, 'length mismatch'], ['long udd table', {'qd': [1238, 1628, 2136, 2796, 3668, 4778, 6251, 8129], 'qw': [3279, 5982, 12121, 4971, 8271, 12739, 8017, 14793], 'timing': 'udd', 'radix': 100000}, [[[1218, 3259], [1509, 5668], [1773, 10594], [2072, 3724], [2468, 5698], [2774, 7712], [3092, 4002], [3345, 6306]], 34786]]], [['udd decrement table 0', {'qd': [930, 1213, 1603], 'qw': [13393, 10163, 5206], 'timing': 'udd', 'radix': 54431}, [[[472, 7256], [538, 4718], [647, 2140]], 38660]], ['udd decrement table 1', {'qd': [755, 1006, 1311, 1719], 'qw': [10661, 14309, 10319, 6918], 'timing': 'udd', 'radix': 33489}, [[[239, 3557], [277, 4227], [313, 2582], [370, 1529]], 20395]], ['eoy decrement table 2', {'qd': [1190, 1564, 2044, 2694, 3536, 4612], 'qw': [4523, 14857, 3747, 14471, 13570, 14825], 'timing': 'eoy', 'radix': 14539}, [[[173, 650], [215, 2006], [235, 422], [292, 1526], [319, 1181], [347, 1063]], 6110]], ['eoy decrement table 3', {'qd': [1410, 1864, 2446], 'qw': [11121, 9322, 11894], 'timing': 'eoy', 'radix': 40451}, [[[570, 4435], [661, 3243], [772, 3660]], 27110]], ['high lapse udd', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'udd', 'radix': 10014}, [[[1602, 3605], [1082, 2043]], 1682]], ['high lapse year-end', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'eoy', 'radix': 10014}, [[[2003, 3204], [1442, 1682]], 1683]], ['length mismatch', {'qd': [1000, 2000, 3000], 'qw': [5000, 6000], 'timing': 'udd', 'radix': 1000}, 'length mismatch'], ['lapse list longer', {'qd': [1000], 'qw': [5000, 6000], 'timing': 'eoy', 'radix': 1000}, 'length mismatch'], ['long udd table', {'qd': [828, 1080, 1427, 1896, 2502, 3265, 4277, 5590], 'qw': [6711, 4424, 4588, 10512, 13157, 5312, 3373, 8767], 'timing': 'udd', 'radix': 100000}, [[[800, 6683], [977, 4071], [1220, 3984], [1478, 8566], [1688, 9383], [1944, 3195], [2355, 1849], [2769, 4415]], 44623]]], [['udd decrement table 0', {'qd': [1079, 1440, 1900, 2490], 'qw': [12382, 12480, 9166, 14124], 'timing': 'udd', 'radix': 97739}, [[[989, 12037], [1144, 10496], [1325, 6634], [1507, 9082]], 54525]], ['udd decrement table 1', {'qd': [926, 1207, 1573, 2050], 'qw': [5818, 14108, 5594, 7476], 'timing': 'udd', 'radix': 58255}, [[[524, 3374], [610, 7622], [705, 2560], [846, 3171]], 38843]], ['eoy decrement table 2', {'qd': [1496, 1992, 2610, 3423], 'qw': [7077, 5443, 10634, 8058], 'timing': 'eoy', 'radix': 97309}, [[[1456, 6784], [1774, 4751], [2154, 8549], [2459, 5591]], 63791]], ['eoy decrement table 3', {'qd': [1123, 1473, 1932], 'qw': [9193, 3282, 4474], 'timing': 'eoy', 'radix': 99825}, [[[1121, 9074], [1320, 2898], [1650, 3748]], 80014]], ['high lapse udd', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'udd', 'radix': 10021}, [[[1603, 3608], [1082, 2044]], 1684]], ['high lapse year-end', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'eoy', 'radix': 10021}, [[[2004, 3207], [1443, 1684]], 1683]], ['length mismatch', {'qd': [1000, 2000, 3000], 'qw': [5000, 6000], 'timing': 'udd', 'radix': 1000}, 'length mismatch'], ['lapse list longer', {'qd': [1000], 'qw': [5000, 6000], 'timing': 'eoy', 'radix': 1000}, 'length mismatch'], ['long udd table', {'qd': [1439, 1878, 2462, 3201, 4200, 5488, 7157, 9346], 'qw': [9710, 12625, 8404, 8046, 3063, 8590, 14798, 7301], 'timing': 'udd', 'radix': 100000}, [[[1369, 9640], [1566, 11130], [1799, 6333], [2094, 5397], [2509, 1819], [2959, 4707], [3226, 6946], [3467, 2680]], 32359]]], [['udd decrement table 0', {'qd': [529, 709, 958], 'qw': [13843, 8215, 5302], 'timing': 'udd', 'radix': 93791}, [[[462, 12949], [546, 6580], [683, 3865]], 68706]], ['udd decrement table 1', {'qd': [846, 1101, 1460, 1909, 2488, 3271], 'qw': [8145, 7576, 8774, 6560, 7393, 6414], 'timing': 'udd', 'radix': 15725}, [[[128, 1275], [152, 1079], [183, 1140], [217, 765], [258, 787], [308, 615]], 8818]], ['eoy decrement table 2', {'qd': [940, 1250, 1628], 'qw': [8737, 12691, 6270], 'timing': 'eoy', 'radix': 35371}, [[[332, 3061], [400, 4008], [449, 1700]], 25421]], ['eoy decrement table 3', {'qd': [649, 890, 1181, 1569, 2056], 'qw': [3329, 10015, 13961, 3880, 4359], 'timing': 'eoy', 'radix': 51217}, [[[332, 1694], [438, 4883], [518, 6052], [585, 1425], [726, 1507]], 33057]], ['high lapse udd', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'udd', 'radix': 10028}, [[[1604, 3610], [1083, 2046]], 1685]], ['high lapse year-end', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'eoy', 'radix': 10028}, [[[2006, 3209], [1444, 1685]], 1684]], ['length mismatch', {'qd': [1000, 2000, 3000], 'qw': [5000, 6000], 'timing': 'udd', 'radix': 1000}, 'length mismatch'], ['lapse list longer', {'qd': [1000], 'qw': [5000, 6000], 'timing': 'eoy', 'radix': 1000}, 'length mismatch'], ['long udd table', {'qd': [1103, 1461, 1917, 2496, 3281, 4301, 5597, 7311], 'qw': [12505, 9020, 5190, 7658, 5537, 11768, 6537, 14241], 'timing': 'udd', 'radix': 100000}, [[[1034, 12436], [1207, 7748], [1449, 3988], [1732, 5455], [2072, 3537], [2402, 6833], [2713, 3184], [3002, 6066]], 35142]]], [['udd decrement table 0', {'qd': [507, 663, 903, 1187, 1545, 2051], 'qw': [8115, 12097, 11178, 14750, 10909, 8914], 'timing': 'udd', 'radix': 91817}, [[[447, 7432], [523, 10120], [625, 8156], [709, 9459], [794, 5883], [934, 4206]], 42529]], ['udd decrement table 1', {'qd': [908, 1197, 1597, 2118, 2774], 'qw': [5334, 8356, 12199, 5950, 3708], 'timing': 'udd', 'radix': 44847}, [[[396, 2381], [483, 3494], [571, 4610], [676, 1938], [825, 1108]], 28365]], ['eoy decrement table 2', {'qd': [731, 983, 1287, 1699, 2237, 2954], 'qw': [13569, 10174, 10715, 12076, 6449, 3074], 'timing': 'eoy', 'radix': 91077}, [[[666, 12268], [768, 7872], [895, 7351], [1041, 7272], [1184, 3338], [1430, 1445]], 45547]], ['eoy decrement table 3', {'qd': [883, 1167, 1548], 'qw': [3198, 5134, 5923], 'timing': 'eoy', 'radix': 23497}, [[[207, 745], [263, 1144], [327, 1233]], 19578]], ['high lapse udd', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'udd', 'radix': 10035}, [[[1606, 3613], [1084, 2047]], 1685]], ['high lapse year-end', {'qd': [20000, 30000], 'qw': [40000, 50000], 'timing': 'eoy', 'radix': 10035}, [[[2007, 3211], [1445, 1686]], 1686]], ['length mismatch', {'qd': [1000, 2000, 3000], 'qw': [5000, 6000], 'timing': 'udd', 'radix': 1000}, 'length mismatch'], ['lapse list longer', {'qd': [1000], 'qw': [5000, 6000], 'timing': 'eoy', 'radix': 1000}, 'length mismatch'], ['long udd table', {'qd': [1256, 1663, 2199, 2866, 3731, 4859, 6351, 8258], 'qw': [8556, 10289, 12789, 3526, 8367, 5298, 13350, 9941], 'timing': 'udd', 'radix': 100000}, [[[1202, 8502], [1424, 9213], [1640, 10076], [1913, 2361], [2276, 5228], [2657, 2903], [2999, 6541], [3223, 3914]], 33928]]]]
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 |
|---|---|---|---|
| udd decrement table 0 | [[[398, 4380], [450, 4260], [533, 968], [631, 2821], [724, 1889]], 20001] | [[[398, 4380], [450, 4260], [533, 968], [631, 2821], [724, 1889]], 20001] | Passed |
| udd decrement table 1 | [[[1061, 7012], [1281, 3508], [1505, 8889], [1679, 6186]], 45250] | [[[1061, 7012], [1281, 3508], [1505, 8889], [1679, 6186]], 45250] | Passed |
| eoy decrement table 2 | [[[209, 977], [258, 738], [318, 1668]], 13625] | [[[209, 977], [258, 738], [318, 1668]], 13625] | Passed |
| eoy decrement table 3 | [[[509, 5782], [610, 2716], [744, 1499], [930, 4194], [1079, 5381], [1179, 998]], 30106] | [[[509, 5782], [610, 2716], [744, 1499], [930, 4194], [1079, 5381], [1179, 998]], 30106] | Passed |
| high lapse udd | [[[1601, 3603], [1081, 2041]], 1681] | [[[1601, 3603], [1081, 2041]], 1681] | Passed |
| high lapse year-end | [[[2001, 3202], [1441, 1681]], 1682] | [[[2001, 3202], [1441, 1681]], 1682] | Passed |
| length mismatch | length mismatch | length mismatch | Passed |
| lapse list longer | length mismatch | length mismatch | Passed |
| long udd table | [[[1218, 3259], [1509, 5668], [1773, 10594], [2072, 3724], [2468, 5698], [2774, 7712], [3092, 4002], [3345, 6306]], 34786] | [[[1218, 3259], [1509, 5668], [1773, 10594], [2072, 3724], [2468, 5698], [2774, 7712], [3092, 4002], [3345, 6306]], 34786] | Passed |
SHA-256 / f51bb8307cd56ee2507f92fc091cf47f6685942d4635604a55729d39e26f543b
Verification & scope
A deterministic bounded teaching model of a stipulated toy actuarial contract. Rates are small synthetic tables, exact rationals are used where practical and floats are rounded at the output; it makes no claim of conformance with any published table, standard of practice or regulation. 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:17.112545+00:00.
Case digest / c07fff60ee5c5cb81843c2e7cab5d56142827e0b21459a4df9181635cd542cb5