FAILURE MAP
← Case archive

FA-63496 / Actuarial life tables / Open access

Net level annual premium: Premiums are valued as payable in arrears · case 01

Net premiums are too high because premiums are discounted an extra year.

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

ROOT CAUSE

The premium annuity uses v^(k+1).

VERIFIED REPAIR

Premiums are due at the start of each year.

Unsuccessful approach: Dropping survival values premiums as certain payments.

Case contract

Input q (per 100000), n (coverage years), m (premium years, 1<=m<=n and n<=table length else 'invalid'), type term|endowment (else 'invalid type'), i (per mille), benefit. A = sum v^(k+1) kp q_k (+ v^n np for endowment); premium annuity-due over m years; return benefit*A/annuity rounded half-up.

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):
    qs=[Fraction(q,100000) for q in x['q']]; n=x['n']; m=x['m']
    if m>n or m<1 or n>len(qs): return 'invalid'
    if x['type'] not in ('term','endowment'): return 'invalid type'
    v=1/(1+Fraction(x['i'],1000))
    A=Fraction(0); ann=Fraction(0); kp=Fraction(1)
    for k in range(n):
        if k<m: ann+=v**(k+1)*kp
        A+=v**(k+1)*kp*qs[k]
        kp*=1-qs[k]
    if x['type']=='endowment': A+=v**n*kp
    return math.floor(x['benefit']*A/ann+Fraction(1,2))
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['limited pay term', {'q': [1116, 1354, 1667, 2034, 2465, 2963, 3571, 4298, 5197, 6274, 7556, 9080], 'n': 10, 'm': 6, 'type': 'term', 'i': 50, 'benefit': 32417307}, 1236317], ['limited pay endowment', {'q': [805, 1014, 1237, 1505, 1844, 2262, 2735, 3316, 3991, 4822, 5826, 6998], 'n': 8, 'm': 3, 'type': 'endowment', 'i': 50, 'benefit': 53744860}, 13078746], ['full pay endowment', {'q': [1226, 1472, 1786, 2144, 2583, 3103, 3749, 4533, 5446, 6546, 7888, 9479], 'n': 6, 'm': 6, 'type': 'endowment', 'i': 30, 'benefit': 17182267}, 2700402], ['full pay term', {'q': [636, 786, 984, 1192, 1450, 1750, 2140, 2614, 3160, 3797, 4603, 5551], 'n': 12, 'm': 12, 'type': 'term', 'i': 50, 'benefit': 77720826}, 1517456], ['single premium', {'q': [586, 718, 878, 1062, 1306, 1614, 1972, 2399, 2899, 3512, 4240, 5126], 'n': 5, 'm': 1, 'type': 'endowment', 'i': 40, 'benefit': 23235362}, 19155246], ['pay period exceeds term', {'q': [704, 861, 1036, 1286, 1567, 1897, 2281, 2786, 3359, 4046, 4868, 5860], 'n': 5, 'm': 7, 'type': 'term', 'i': 40, 'benefit': 97510456}, 'invalid'], ['unknown plan type', {'q': [966, 1164, 1413, 1738, 2095, 2527, 3060, 3675, 4454, 5384, 6480, 7790], 'n': 5, 'm': 5, 'type': 'whole', 'i': 50, 'benefit': 52803794}, 'invalid type'], ['term too long for table', {'q': [1168, 1420, 1752, 2109, 2552, 3075, 3725, 4498, 5446, 6543, 7899, 9488], 'n': 13, 'm': 5, 'type': 'term', 'i': 30, 'benefit': 68032420}, 'invalid']], [['limited pay term', {'q': [841, 1053, 1267, 1547, 1901, 2290, 2783, 3379, 4070, 4927, 5917, 7143], 'n': 10, 'm': 5, 'type': 'term', 'i': 40, 'benefit': 10621995}, 390243], ['limited pay endowment', {'q': [1237, 1529, 1837, 2215, 2701, 3286, 3958, 4782, 5775, 6980, 8396, 10091], 'n': 8, 'm': 4, 'type': 'endowment', 'i': 50, 'benefit': 28755476}, 5487845], ['full pay endowment', {'q': [1149, 1421, 1734, 2104, 2524, 3074, 3738, 4524, 5429, 6522, 7842, 9459], 'n': 6, 'm': 6, 'type': 'endowment', 'i': 50, 'benefit': 68984205}, 10136985], ['full pay term', {'q': [1155, 1401, 1706, 2084, 2505, 3052, 3702, 4479, 5396, 6523, 7831, 9442], 'n': 12, 'm': 12, 'type': 'term', 'i': 50, 'benefit': 77815499}, 2534596], ['single premium', {'q': [1488, 1827, 2210, 2701, 3269, 3941, 4765, 5757, 6948, 8343, 10034, 12042], 'n': 5, 'm': 1, 'type': 'endowment', 'i': 30, 'benefit': 10091605}, 8753895], ['pay period exceeds term', {'q': [1434, 1757, 2137, 2589, 3128, 3764, 4523, 5445, 6554, 7912, 9512, 11438], 'n': 5, 'm': 7, 'type': 'term', 'i': 30, 'benefit': 70676453}, 'invalid'], ['unknown plan type', {'q': [1212, 1472, 1779, 2143, 2614, 3137, 3779, 4543, 5470, 6612, 7956, 9572], 'n': 5, 'm': 5, 'type': 'whole', 'i': 30, 'benefit': 15889609}, 'invalid type'], ['term too long for table', {'q': [663, 804, 993, 1231, 1479, 1787, 2159, 2637, 3213, 3881, 4704, 5656], 'n': 13, 'm': 5, 'type': 'term', 'i': 50, 'benefit': 54460124}, 'invalid']], [['limited pay term', {'q': [747, 913, 1131, 1395, 1717, 2081, 2524, 3065, 3693, 4464, 5404, 6511], 'n': 10, 'm': 5, 'type': 'term', 'i': 30, 'benefit': 87228387}, 3048879], ['limited pay endowment', {'q': [829, 1036, 1275, 1538, 1848, 2245, 2727, 3321, 4019, 4840, 5840, 7033], 'n': 8, 'm': 5, 'type': 'endowment', 'i': 40, 'benefit': 74915366}, 12250027], ['full pay endowment', {'q': [1425, 1755, 2109, 2552, 3068, 3709, 4452, 5354, 6453, 7758, 9346, 11251], 'n': 6, 'm': 6, 'type': 'endowment', 'i': 40, 'benefit': 37157222}, 5700405], ['full pay term', {'q': [1109, 1368, 1651, 2017, 2431, 2939, 3572, 4303, 5195, 6284, 7585, 9152], 'n': 12, 'm': 12, 'type': 'term', 'i': 50, 'benefit': 11656982}, 367794], ['single premium', {'q': [526, 657, 804, 1002, 1248, 1531, 1861, 2269, 2740, 3321, 4011, 4832], 'n': 5, 'm': 1, 'type': 'endowment', 'i': 40, 'benefit': 36779454}, 30313184], ['pay period exceeds term', {'q': [1308, 1603, 1941, 2359, 2865, 3473, 4180, 5051, 6103, 7351, 8863, 10680], 'n': 5, 'm': 7, 'type': 'term', 'i': 40, 'benefit': 33579689}, 'invalid'], ['unknown plan type', {'q': [1363, 1655, 1992, 2437, 2924, 3536, 4286, 5167, 6239, 7489, 9002, 10816], 'n': 5, 'm': 5, 'type': 'whole', 'i': 50, 'benefit': 98225689}, 'invalid type'], ['term too long for table', {'q': [1070, 1313, 1595, 1918, 2328, 2810, 3419, 4135, 5012, 6063, 7304, 8777], 'n': 13, 'm': 5, 'type': 'term', 'i': 50, 'benefit': 38738726}, 'invalid']], [['limited pay term', {'q': [512, 643, 815, 1003, 1212, 1489, 1831, 2210, 2664, 3227, 3916, 4712], 'n': 10, 'm': 3, 'type': 'term', 'i': 50, 'benefit': 45807977}, 1688215], ['limited pay endowment', {'q': [590, 709, 861, 1043, 1276, 1575, 1926, 2361, 2871, 3492, 4201, 5086], 'n': 8, 'm': 3, 'type': 'endowment', 'i': 40, 'benefit': 38192191}, 9833950], ['full pay endowment', {'q': [528, 644, 806, 1014, 1235, 1482, 1819, 2204, 2655, 3234, 3922, 4713], 'n': 6, 'm': 6, 'type': 'endowment', 'i': 40, 'benefit': 71007672}, 10519104], ['full pay term', {'q': [1074, 1331, 1597, 1959, 2390, 2877, 3476, 4185, 5055, 6067, 7296, 8779], 'n': 12, 'm': 12, 'type': 'term', 'i': 30, 'benefit': 83944206}, 2733193], ['single premium', {'q': [678, 813, 994, 1206, 1488, 1828, 2220, 2693, 3274, 3956, 4750, 5720], 'n': 5, 'm': 1, 'type': 'endowment', 'i': 40, 'benefit': 89899331}, 74144103], ['pay period exceeds term', {'q': [983, 1186, 1467, 1792, 2157, 2607, 3155, 3832, 4617, 5558, 6707, 8062], 'n': 5, 'm': 7, 'type': 'term', 'i': 30, 'benefit': 49415695}, 'invalid'], ['unknown plan type', {'q': [730, 884, 1091, 1323, 1616, 1984, 2415, 2929, 3548, 4275, 5150, 6215], 'n': 5, 'm': 5, 'type': 'whole', 'i': 50, 'benefit': 99033643}, 'invalid type'], ['term too long for table', {'q': [1353, 1640, 1996, 2435, 2922, 3548, 4298, 5204, 6275, 7580, 9134, 10967], 'n': 13, 'm': 5, 'type': 'term', 'i': 30, 'benefit': 56917171}, 'invalid']], [['limited pay term', {'q': [855, 1042, 1283, 1573, 1895, 2291, 2795, 3365, 4084, 4937, 5928, 7133], 'n': 10, 'm': 4, 'type': 'term', 'i': 30, 'benefit': 26591939}, 1254982], ['limited pay endowment', {'q': [1284, 1558, 1913, 2335, 2838, 3409, 4127, 4953, 5987, 7192, 8649, 10419], 'n': 8, 'm': 5, 'type': 'endowment', 'i': 40, 'benefit': 31636962}, 5267026], ['full pay endowment', {'q': [689, 831, 1026, 1257, 1516, 1826, 2201, 2686, 3249, 3931, 4730, 5695], 'n': 6, 'm': 6, 'type': 'endowment', 'i': 40, 'benefit': 16318284}, 2431737], ['full pay term', {'q': [631, 779, 957, 1167, 1436, 1770, 2163, 2608, 3149, 3826, 4607, 5557], 'n': 12, 'm': 12, 'type': 'term', 'i': 40, 'benefit': 14803880}, 297673], ['single premium', {'q': [1499, 1817, 2219, 2684, 3268, 3964, 4795, 5778, 6979, 8381, 10061, 12080], 'n': 5, 'm': 1, 'type': 'endowment', 'i': 30, 'benefit': 45588105}, 39545285], ['pay period exceeds term', {'q': [1089, 1329, 1604, 1944, 2381, 2862, 3441, 4130, 4970, 5966, 7192, 8664], 'n': 5, 'm': 7, 'type': 'term', 'i': 30, 'benefit': 16169173}, 'invalid'], ['unknown plan type', {'q': [627, 776, 934, 1161, 1422, 1733, 2096, 2520, 3024, 3638, 4377, 5280], 'n': 5, 'm': 5, 'type': 'whole', 'i': 30, 'benefit': 97706465}, 'invalid type'], ['term too long for table', {'q': [697, 840, 1013, 1239, 1511, 1819, 2198, 2660, 3234, 3882, 4708, 5676], 'n': 13, 'm': 5, 'type': 'term', 'i': 50, 'benefit': 62443585}, 'invalid']]]
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
limited pay term12981331236317Failed
limited pay endowment1373268313078746Failed
full pay endowment27814142700402Failed
full pay term15933291517456Failed
single premium1992145619155246Failed
pay period exceeds terminvalidinvalidPassed
unknown plan typeinvalid typeinvalid typePassed
term too long for tableinvalidinvalidPassed

SHA-256 / abca6490cc2f62750eb349621a34924d27eee085148feb0672487a15d1c3aaa1

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):
    qs=[Fraction(q,100000) for q in x['q']]; n=x['n']; m=x['m']
    if m>n or m<1 or n>len(qs): return 'invalid'
    if x['type'] not in ('term','endowment'): return 'invalid type'
    v=1/(1+Fraction(x['i'],1000))
    A=Fraction(0); ann=Fraction(0); kp=Fraction(1)
    for k in range(n):
        if k<m: ann+=v**k
        A+=v**(k+1)*kp*qs[k]
        kp*=1-qs[k]
    if x['type']=='endowment': A+=v**n*kp
    return math.floor(x['benefit']*A/ann+Fraction(1,2))
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['limited pay term', {'q': [1116, 1354, 1667, 2034, 2465, 2963, 3571, 4298, 5197, 6274, 7556, 9080], 'n': 10, 'm': 6, 'type': 'term', 'i': 50, 'benefit': 32417307}, 1236317], ['limited pay endowment', {'q': [805, 1014, 1237, 1505, 1844, 2262, 2735, 3316, 3991, 4822, 5826, 6998], 'n': 8, 'm': 3, 'type': 'endowment', 'i': 50, 'benefit': 53744860}, 13078746], ['full pay endowment', {'q': [1226, 1472, 1786, 2144, 2583, 3103, 3749, 4533, 5446, 6546, 7888, 9479], 'n': 6, 'm': 6, 'type': 'endowment', 'i': 30, 'benefit': 17182267}, 2700402], ['full pay term', {'q': [636, 786, 984, 1192, 1450, 1750, 2140, 2614, 3160, 3797, 4603, 5551], 'n': 12, 'm': 12, 'type': 'term', 'i': 50, 'benefit': 77720826}, 1517456], ['single premium', {'q': [586, 718, 878, 1062, 1306, 1614, 1972, 2399, 2899, 3512, 4240, 5126], 'n': 5, 'm': 1, 'type': 'endowment', 'i': 40, 'benefit': 23235362}, 19155246], ['pay period exceeds term', {'q': [704, 861, 1036, 1286, 1567, 1897, 2281, 2786, 3359, 4046, 4868, 5860], 'n': 5, 'm': 7, 'type': 'term', 'i': 40, 'benefit': 97510456}, 'invalid'], ['unknown plan type', {'q': [966, 1164, 1413, 1738, 2095, 2527, 3060, 3675, 4454, 5384, 6480, 7790], 'n': 5, 'm': 5, 'type': 'whole', 'i': 50, 'benefit': 52803794}, 'invalid type'], ['term too long for table', {'q': [1168, 1420, 1752, 2109, 2552, 3075, 3725, 4498, 5446, 6543, 7899, 9488], 'n': 13, 'm': 5, 'type': 'term', 'i': 30, 'benefit': 68032420}, 'invalid']], [['limited pay term', {'q': [841, 1053, 1267, 1547, 1901, 2290, 2783, 3379, 4070, 4927, 5917, 7143], 'n': 10, 'm': 5, 'type': 'term', 'i': 40, 'benefit': 10621995}, 390243], ['limited pay endowment', {'q': [1237, 1529, 1837, 2215, 2701, 3286, 3958, 4782, 5775, 6980, 8396, 10091], 'n': 8, 'm': 4, 'type': 'endowment', 'i': 50, 'benefit': 28755476}, 5487845], ['full pay endowment', {'q': [1149, 1421, 1734, 2104, 2524, 3074, 3738, 4524, 5429, 6522, 7842, 9459], 'n': 6, 'm': 6, 'type': 'endowment', 'i': 50, 'benefit': 68984205}, 10136985], ['full pay term', {'q': [1155, 1401, 1706, 2084, 2505, 3052, 3702, 4479, 5396, 6523, 7831, 9442], 'n': 12, 'm': 12, 'type': 'term', 'i': 50, 'benefit': 77815499}, 2534596], ['single premium', {'q': [1488, 1827, 2210, 2701, 3269, 3941, 4765, 5757, 6948, 8343, 10034, 12042], 'n': 5, 'm': 1, 'type': 'endowment', 'i': 30, 'benefit': 10091605}, 8753895], ['pay period exceeds term', {'q': [1434, 1757, 2137, 2589, 3128, 3764, 4523, 5445, 6554, 7912, 9512, 11438], 'n': 5, 'm': 7, 'type': 'term', 'i': 30, 'benefit': 70676453}, 'invalid'], ['unknown plan type', {'q': [1212, 1472, 1779, 2143, 2614, 3137, 3779, 4543, 5470, 6612, 7956, 9572], 'n': 5, 'm': 5, 'type': 'whole', 'i': 30, 'benefit': 15889609}, 'invalid type'], ['term too long for table', {'q': [663, 804, 993, 1231, 1479, 1787, 2159, 2637, 3213, 3881, 4704, 5656], 'n': 13, 'm': 5, 'type': 'term', 'i': 50, 'benefit': 54460124}, 'invalid']], [['limited pay term', {'q': [747, 913, 1131, 1395, 1717, 2081, 2524, 3065, 3693, 4464, 5404, 6511], 'n': 10, 'm': 5, 'type': 'term', 'i': 30, 'benefit': 87228387}, 3048879], ['limited pay endowment', {'q': [829, 1036, 1275, 1538, 1848, 2245, 2727, 3321, 4019, 4840, 5840, 7033], 'n': 8, 'm': 5, 'type': 'endowment', 'i': 40, 'benefit': 74915366}, 12250027], ['full pay endowment', {'q': [1425, 1755, 2109, 2552, 3068, 3709, 4452, 5354, 6453, 7758, 9346, 11251], 'n': 6, 'm': 6, 'type': 'endowment', 'i': 40, 'benefit': 37157222}, 5700405], ['full pay term', {'q': [1109, 1368, 1651, 2017, 2431, 2939, 3572, 4303, 5195, 6284, 7585, 9152], 'n': 12, 'm': 12, 'type': 'term', 'i': 50, 'benefit': 11656982}, 367794], ['single premium', {'q': [526, 657, 804, 1002, 1248, 1531, 1861, 2269, 2740, 3321, 4011, 4832], 'n': 5, 'm': 1, 'type': 'endowment', 'i': 40, 'benefit': 36779454}, 30313184], ['pay period exceeds term', {'q': [1308, 1603, 1941, 2359, 2865, 3473, 4180, 5051, 6103, 7351, 8863, 10680], 'n': 5, 'm': 7, 'type': 'term', 'i': 40, 'benefit': 33579689}, 'invalid'], ['unknown plan type', {'q': [1363, 1655, 1992, 2437, 2924, 3536, 4286, 5167, 6239, 7489, 9002, 10816], 'n': 5, 'm': 5, 'type': 'whole', 'i': 50, 'benefit': 98225689}, 'invalid type'], ['term too long for table', {'q': [1070, 1313, 1595, 1918, 2328, 2810, 3419, 4135, 5012, 6063, 7304, 8777], 'n': 13, 'm': 5, 'type': 'term', 'i': 50, 'benefit': 38738726}, 'invalid']], [['limited pay term', {'q': [512, 643, 815, 1003, 1212, 1489, 1831, 2210, 2664, 3227, 3916, 4712], 'n': 10, 'm': 3, 'type': 'term', 'i': 50, 'benefit': 45807977}, 1688215], ['limited pay endowment', {'q': [590, 709, 861, 1043, 1276, 1575, 1926, 2361, 2871, 3492, 4201, 5086], 'n': 8, 'm': 3, 'type': 'endowment', 'i': 40, 'benefit': 38192191}, 9833950], ['full pay endowment', {'q': [528, 644, 806, 1014, 1235, 1482, 1819, 2204, 2655, 3234, 3922, 4713], 'n': 6, 'm': 6, 'type': 'endowment', 'i': 40, 'benefit': 71007672}, 10519104], ['full pay term', {'q': [1074, 1331, 1597, 1959, 2390, 2877, 3476, 4185, 5055, 6067, 7296, 8779], 'n': 12, 'm': 12, 'type': 'term', 'i': 30, 'benefit': 83944206}, 2733193], ['single premium', {'q': [678, 813, 994, 1206, 1488, 1828, 2220, 2693, 3274, 3956, 4750, 5720], 'n': 5, 'm': 1, 'type': 'endowment', 'i': 40, 'benefit': 89899331}, 74144103], ['pay period exceeds term', {'q': [983, 1186, 1467, 1792, 2157, 2607, 3155, 3832, 4617, 5558, 6707, 8062], 'n': 5, 'm': 7, 'type': 'term', 'i': 30, 'benefit': 49415695}, 'invalid'], ['unknown plan type', {'q': [730, 884, 1091, 1323, 1616, 1984, 2415, 2929, 3548, 4275, 5150, 6215], 'n': 5, 'm': 5, 'type': 'whole', 'i': 50, 'benefit': 99033643}, 'invalid type'], ['term too long for table', {'q': [1353, 1640, 1996, 2435, 2922, 3548, 4298, 5204, 6275, 7580, 9134, 10967], 'n': 13, 'm': 5, 'type': 'term', 'i': 30, 'benefit': 56917171}, 'invalid']], [['limited pay term', {'q': [855, 1042, 1283, 1573, 1895, 2291, 2795, 3365, 4084, 4937, 5928, 7133], 'n': 10, 'm': 4, 'type': 'term', 'i': 30, 'benefit': 26591939}, 1254982], ['limited pay endowment', {'q': [1284, 1558, 1913, 2335, 2838, 3409, 4127, 4953, 5987, 7192, 8649, 10419], 'n': 8, 'm': 5, 'type': 'endowment', 'i': 40, 'benefit': 31636962}, 5267026], ['full pay endowment', {'q': [689, 831, 1026, 1257, 1516, 1826, 2201, 2686, 3249, 3931, 4730, 5695], 'n': 6, 'm': 6, 'type': 'endowment', 'i': 40, 'benefit': 16318284}, 2431737], ['full pay term', {'q': [631, 779, 957, 1167, 1436, 1770, 2163, 2608, 3149, 3826, 4607, 5557], 'n': 12, 'm': 12, 'type': 'term', 'i': 40, 'benefit': 14803880}, 297673], ['single premium', {'q': [1499, 1817, 2219, 2684, 3268, 3964, 4795, 5778, 6979, 8381, 10061, 12080], 'n': 5, 'm': 1, 'type': 'endowment', 'i': 30, 'benefit': 45588105}, 39545285], ['pay period exceeds term', {'q': [1089, 1329, 1604, 1944, 2381, 2862, 3441, 4130, 4970, 5966, 7192, 8664], 'n': 5, 'm': 7, 'type': 'term', 'i': 30, 'benefit': 16169173}, 'invalid'], ['unknown plan type', {'q': [627, 776, 934, 1161, 1422, 1733, 2096, 2520, 3024, 3638, 4377, 5280], 'n': 5, 'm': 5, 'type': 'whole', 'i': 30, 'benefit': 97706465}, 'invalid type'], ['term too long for table', {'q': [697, 840, 1013, 1239, 1511, 1819, 2198, 2660, 3234, 3882, 4708, 5676], 'n': 13, 'm': 5, 'type': 'term', 'i': 50, 'benefit': 62443585}, 'invalid']]]
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
limited pay term11938221236317Failed
limited pay endowment1296855313078746Failed
full pay endowment25979532700402Failed
full pay term14182151517456Failed
single premium1915524619155246Passed
pay period exceeds terminvalidinvalidPassed
unknown plan typeinvalid typeinvalid typePassed
term too long for tableinvalidinvalidPassed

SHA-256 / 31dc4edd7c51dda8d1390427b9e0f8281ea0e78dd9e73c9551d270f076530503

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):
    qs=[Fraction(q,100000) for q in x['q']]; n=x['n']; m=x['m']
    if m>n or m<1 or n>len(qs): return 'invalid'
    if x['type'] not in ('term','endowment'): return 'invalid type'
    v=1/(1+Fraction(x['i'],1000))
    A=Fraction(0); ann=Fraction(0); kp=Fraction(1)
    for k in range(n):
        if k<m: ann+=v**k*kp
        A+=v**(k+1)*kp*qs[k]
        kp*=1-qs[k]
    if x['type']=='endowment': A+=v**n*kp
    return math.floor(x['benefit']*A/ann+Fraction(1,2))
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['limited pay term', {'q': [1116, 1354, 1667, 2034, 2465, 2963, 3571, 4298, 5197, 6274, 7556, 9080], 'n': 10, 'm': 6, 'type': 'term', 'i': 50, 'benefit': 32417307}, 1236317], ['limited pay endowment', {'q': [805, 1014, 1237, 1505, 1844, 2262, 2735, 3316, 3991, 4822, 5826, 6998], 'n': 8, 'm': 3, 'type': 'endowment', 'i': 50, 'benefit': 53744860}, 13078746], ['full pay endowment', {'q': [1226, 1472, 1786, 2144, 2583, 3103, 3749, 4533, 5446, 6546, 7888, 9479], 'n': 6, 'm': 6, 'type': 'endowment', 'i': 30, 'benefit': 17182267}, 2700402], ['full pay term', {'q': [636, 786, 984, 1192, 1450, 1750, 2140, 2614, 3160, 3797, 4603, 5551], 'n': 12, 'm': 12, 'type': 'term', 'i': 50, 'benefit': 77720826}, 1517456], ['single premium', {'q': [586, 718, 878, 1062, 1306, 1614, 1972, 2399, 2899, 3512, 4240, 5126], 'n': 5, 'm': 1, 'type': 'endowment', 'i': 40, 'benefit': 23235362}, 19155246], ['pay period exceeds term', {'q': [704, 861, 1036, 1286, 1567, 1897, 2281, 2786, 3359, 4046, 4868, 5860], 'n': 5, 'm': 7, 'type': 'term', 'i': 40, 'benefit': 97510456}, 'invalid'], ['unknown plan type', {'q': [966, 1164, 1413, 1738, 2095, 2527, 3060, 3675, 4454, 5384, 6480, 7790], 'n': 5, 'm': 5, 'type': 'whole', 'i': 50, 'benefit': 52803794}, 'invalid type'], ['term too long for table', {'q': [1168, 1420, 1752, 2109, 2552, 3075, 3725, 4498, 5446, 6543, 7899, 9488], 'n': 13, 'm': 5, 'type': 'term', 'i': 30, 'benefit': 68032420}, 'invalid']], [['limited pay term', {'q': [841, 1053, 1267, 1547, 1901, 2290, 2783, 3379, 4070, 4927, 5917, 7143], 'n': 10, 'm': 5, 'type': 'term', 'i': 40, 'benefit': 10621995}, 390243], ['limited pay endowment', {'q': [1237, 1529, 1837, 2215, 2701, 3286, 3958, 4782, 5775, 6980, 8396, 10091], 'n': 8, 'm': 4, 'type': 'endowment', 'i': 50, 'benefit': 28755476}, 5487845], ['full pay endowment', {'q': [1149, 1421, 1734, 2104, 2524, 3074, 3738, 4524, 5429, 6522, 7842, 9459], 'n': 6, 'm': 6, 'type': 'endowment', 'i': 50, 'benefit': 68984205}, 10136985], ['full pay term', {'q': [1155, 1401, 1706, 2084, 2505, 3052, 3702, 4479, 5396, 6523, 7831, 9442], 'n': 12, 'm': 12, 'type': 'term', 'i': 50, 'benefit': 77815499}, 2534596], ['single premium', {'q': [1488, 1827, 2210, 2701, 3269, 3941, 4765, 5757, 6948, 8343, 10034, 12042], 'n': 5, 'm': 1, 'type': 'endowment', 'i': 30, 'benefit': 10091605}, 8753895], ['pay period exceeds term', {'q': [1434, 1757, 2137, 2589, 3128, 3764, 4523, 5445, 6554, 7912, 9512, 11438], 'n': 5, 'm': 7, 'type': 'term', 'i': 30, 'benefit': 70676453}, 'invalid'], ['unknown plan type', {'q': [1212, 1472, 1779, 2143, 2614, 3137, 3779, 4543, 5470, 6612, 7956, 9572], 'n': 5, 'm': 5, 'type': 'whole', 'i': 30, 'benefit': 15889609}, 'invalid type'], ['term too long for table', {'q': [663, 804, 993, 1231, 1479, 1787, 2159, 2637, 3213, 3881, 4704, 5656], 'n': 13, 'm': 5, 'type': 'term', 'i': 50, 'benefit': 54460124}, 'invalid']], [['limited pay term', {'q': [747, 913, 1131, 1395, 1717, 2081, 2524, 3065, 3693, 4464, 5404, 6511], 'n': 10, 'm': 5, 'type': 'term', 'i': 30, 'benefit': 87228387}, 3048879], ['limited pay endowment', {'q': [829, 1036, 1275, 1538, 1848, 2245, 2727, 3321, 4019, 4840, 5840, 7033], 'n': 8, 'm': 5, 'type': 'endowment', 'i': 40, 'benefit': 74915366}, 12250027], ['full pay endowment', {'q': [1425, 1755, 2109, 2552, 3068, 3709, 4452, 5354, 6453, 7758, 9346, 11251], 'n': 6, 'm': 6, 'type': 'endowment', 'i': 40, 'benefit': 37157222}, 5700405], ['full pay term', {'q': [1109, 1368, 1651, 2017, 2431, 2939, 3572, 4303, 5195, 6284, 7585, 9152], 'n': 12, 'm': 12, 'type': 'term', 'i': 50, 'benefit': 11656982}, 367794], ['single premium', {'q': [526, 657, 804, 1002, 1248, 1531, 1861, 2269, 2740, 3321, 4011, 4832], 'n': 5, 'm': 1, 'type': 'endowment', 'i': 40, 'benefit': 36779454}, 30313184], ['pay period exceeds term', {'q': [1308, 1603, 1941, 2359, 2865, 3473, 4180, 5051, 6103, 7351, 8863, 10680], 'n': 5, 'm': 7, 'type': 'term', 'i': 40, 'benefit': 33579689}, 'invalid'], ['unknown plan type', {'q': [1363, 1655, 1992, 2437, 2924, 3536, 4286, 5167, 6239, 7489, 9002, 10816], 'n': 5, 'm': 5, 'type': 'whole', 'i': 50, 'benefit': 98225689}, 'invalid type'], ['term too long for table', {'q': [1070, 1313, 1595, 1918, 2328, 2810, 3419, 4135, 5012, 6063, 7304, 8777], 'n': 13, 'm': 5, 'type': 'term', 'i': 50, 'benefit': 38738726}, 'invalid']], [['limited pay term', {'q': [512, 643, 815, 1003, 1212, 1489, 1831, 2210, 2664, 3227, 3916, 4712], 'n': 10, 'm': 3, 'type': 'term', 'i': 50, 'benefit': 45807977}, 1688215], ['limited pay endowment', {'q': [590, 709, 861, 1043, 1276, 1575, 1926, 2361, 2871, 3492, 4201, 5086], 'n': 8, 'm': 3, 'type': 'endowment', 'i': 40, 'benefit': 38192191}, 9833950], ['full pay endowment', {'q': [528, 644, 806, 1014, 1235, 1482, 1819, 2204, 2655, 3234, 3922, 4713], 'n': 6, 'm': 6, 'type': 'endowment', 'i': 40, 'benefit': 71007672}, 10519104], ['full pay term', {'q': [1074, 1331, 1597, 1959, 2390, 2877, 3476, 4185, 5055, 6067, 7296, 8779], 'n': 12, 'm': 12, 'type': 'term', 'i': 30, 'benefit': 83944206}, 2733193], ['single premium', {'q': [678, 813, 994, 1206, 1488, 1828, 2220, 2693, 3274, 3956, 4750, 5720], 'n': 5, 'm': 1, 'type': 'endowment', 'i': 40, 'benefit': 89899331}, 74144103], ['pay period exceeds term', {'q': [983, 1186, 1467, 1792, 2157, 2607, 3155, 3832, 4617, 5558, 6707, 8062], 'n': 5, 'm': 7, 'type': 'term', 'i': 30, 'benefit': 49415695}, 'invalid'], ['unknown plan type', {'q': [730, 884, 1091, 1323, 1616, 1984, 2415, 2929, 3548, 4275, 5150, 6215], 'n': 5, 'm': 5, 'type': 'whole', 'i': 50, 'benefit': 99033643}, 'invalid type'], ['term too long for table', {'q': [1353, 1640, 1996, 2435, 2922, 3548, 4298, 5204, 6275, 7580, 9134, 10967], 'n': 13, 'm': 5, 'type': 'term', 'i': 30, 'benefit': 56917171}, 'invalid']], [['limited pay term', {'q': [855, 1042, 1283, 1573, 1895, 2291, 2795, 3365, 4084, 4937, 5928, 7133], 'n': 10, 'm': 4, 'type': 'term', 'i': 30, 'benefit': 26591939}, 1254982], ['limited pay endowment', {'q': [1284, 1558, 1913, 2335, 2838, 3409, 4127, 4953, 5987, 7192, 8649, 10419], 'n': 8, 'm': 5, 'type': 'endowment', 'i': 40, 'benefit': 31636962}, 5267026], ['full pay endowment', {'q': [689, 831, 1026, 1257, 1516, 1826, 2201, 2686, 3249, 3931, 4730, 5695], 'n': 6, 'm': 6, 'type': 'endowment', 'i': 40, 'benefit': 16318284}, 2431737], ['full pay term', {'q': [631, 779, 957, 1167, 1436, 1770, 2163, 2608, 3149, 3826, 4607, 5557], 'n': 12, 'm': 12, 'type': 'term', 'i': 40, 'benefit': 14803880}, 297673], ['single premium', {'q': [1499, 1817, 2219, 2684, 3268, 3964, 4795, 5778, 6979, 8381, 10061, 12080], 'n': 5, 'm': 1, 'type': 'endowment', 'i': 30, 'benefit': 45588105}, 39545285], ['pay period exceeds term', {'q': [1089, 1329, 1604, 1944, 2381, 2862, 3441, 4130, 4970, 5966, 7192, 8664], 'n': 5, 'm': 7, 'type': 'term', 'i': 30, 'benefit': 16169173}, 'invalid'], ['unknown plan type', {'q': [627, 776, 934, 1161, 1422, 1733, 2096, 2520, 3024, 3638, 4377, 5280], 'n': 5, 'm': 5, 'type': 'whole', 'i': 30, 'benefit': 97706465}, 'invalid type'], ['term too long for table', {'q': [697, 840, 1013, 1239, 1511, 1819, 2198, 2660, 3234, 3882, 4708, 5676], 'n': 13, 'm': 5, 'type': 'term', 'i': 50, 'benefit': 62443585}, 'invalid']]]
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
limited pay term12363171236317Passed
limited pay endowment1307874613078746Passed
full pay endowment27004022700402Passed
full pay term15174561517456Passed
single premium1915524619155246Passed
pay period exceeds terminvalidinvalidPassed
unknown plan typeinvalid typeinvalid typePassed
term too long for tableinvalidinvalidPassed

SHA-256 / 0d64f6383f387abbefc1e2298ce7be85ea21fe43c4684d563834fa7bd0cff405

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:15.034376+00:00.

Case digest / 8a9f0eca3903e31483ed9fae052b1ecfaf4a361efb6fdcdbc480b97be3c684ae