FAILURE MAP
← Case archive

FA-66756 / Airline fare rule evaluation / Open access

Coupon shares rounded to nearest cent before remainder · case 01

Earlier coupons gain or lose a cent compared with the settlement contract.

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

ROOT CAUSE

Each share is rounded to the nearest cent instead of floored.

VERIFIED REPAIR

Floor each share in integer cents and give the remainder to the designated coupon.

Unsuccessful approach: Ceiling shares push the remainder negative.

Case contract

Input {'fare','tpm':[miles per coupon, 0 for surface]}. Work in integer cents: each coupon gets floor(cents*tpm/total); the rounding remainder goes to the last coupon with nonzero miles; surface coupons get 0. No miles -> 'ERR_NO_MILES'. Return coupon values in currency units.

Why this case matters

Prorating a through fare across coupons by mileage must conserve the fare to the cent and keep value off surface sectors.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    tpm = x['tpm']
    total = sum(tpm)
    if total == 0: return 'ERR_NO_MILES'
    cents = round(x['fare'] * 100)
    shares = [round(cents * t / total) for t in tpm]
    last = max(i for i, t in enumerate(tpm) if t > 0)
    shares[last] += cents - sum(shares)
    return [s / 100 for s in shares]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['three coupons uneven', {'fare': 1001.0, 'tpm': [1200, 350, 2900]}, [269.93, 78.73, 652.34]], ['surface sector last', {'fare': 777.77, 'tpm': [800, 1501, 0]}, [270.41, 507.36, 0.0]], ['surface sector first', {'fare': 500.01, 'tpm': [0, 700, 901]}, [0.0, 218.61, 281.4]], ['single coupon', {'fare': 123.45, 'tpm': [2475]}, [123.45]], ['equal miles odd cents', {'fare': 100.0, 'tpm': [500, 500, 500]}, [33.33, 33.33, 33.34]], ['all surface', {'fare': 50.0, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 1', {'fare': 1565.87, 'tpm': [193, 5089]}, [57.21, 1508.66]], ['sampled case 2', {'fare': 583.22, 'tpm': [1271, 0, 0]}, [583.22, 0.0, 0.0]], ['sampled case 3', {'fare': 2079.37, 'tpm': [1800]}, [2079.37]]], [['three coupons uneven', {'fare': 1002.0, 'tpm': [1200, 350, 2900]}, [270.2, 78.8, 653.0]], ['surface sector last', {'fare': 777.77, 'tpm': [800, 1502, 0]}, [270.29, 507.48, 0.0]], ['surface sector first', {'fare': 500.01, 'tpm': [0, 700, 902]}, [0.0, 218.48, 281.53]], ['single coupon', {'fare': 246.9, 'tpm': [2475]}, [246.9]], ['equal miles odd cents', {'fare': 100.0, 'tpm': [500, 500, 500]}, [33.33, 33.33, 33.34]], ['all surface', {'fare': 50.0, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 1', {'fare': 2915.76, 'tpm': [0, 5491, 214, 782]}, [0.0, 2468.08, 96.18, 351.5]], ['sampled case 2', {'fare': 2482.84, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 3', {'fare': 1177.57, 'tpm': [0, 0]}, 'ERR_NO_MILES']], [['three coupons uneven', {'fare': 1003.0, 'tpm': [1200, 350, 2900]}, [270.47, 78.88, 653.65]], ['surface sector last', {'fare': 777.77, 'tpm': [800, 1503, 0]}, [270.17, 507.6, 0.0]], ['surface sector first', {'fare': 500.01, 'tpm': [0, 700, 903]}, [0.0, 218.34, 281.67]], ['single coupon', {'fare': 370.35, 'tpm': [2475]}, [370.35]], ['equal miles odd cents', {'fare': 100.0, 'tpm': [500, 500, 500]}, [33.33, 33.33, 33.34]], ['all surface', {'fare': 50.0, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 1', {'fare': 110.22, 'tpm': [0]}, 'ERR_NO_MILES'], ['sampled case 2', {'fare': 836.64, 'tpm': [5298, 5970, 0, 5279]}, [267.87, 301.85, 0.0, 266.92]], ['sampled case 3', {'fare': 218.58, 'tpm': [5530]}, [218.58]]], [['three coupons uneven', {'fare': 1004.0, 'tpm': [1200, 350, 2900]}, [270.74, 78.96, 654.3]], ['surface sector last', {'fare': 777.77, 'tpm': [800, 1504, 0]}, [270.05, 507.72, 0.0]], ['surface sector first', {'fare': 500.01, 'tpm': [0, 700, 904]}, [0.0, 218.2, 281.81]], ['single coupon', {'fare': 493.8, 'tpm': [2475]}, [493.8]], ['equal miles odd cents', {'fare': 100.0, 'tpm': [500, 500, 500]}, [33.33, 33.33, 33.34]], ['all surface', {'fare': 50.0, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 1', {'fare': 524.52, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 2', {'fare': 1224.53, 'tpm': [0, 1463]}, [0.0, 1224.53]], ['sampled case 3', {'fare': 2475.89, 'tpm': [0]}, 'ERR_NO_MILES']], [['three coupons uneven', {'fare': 1005.0, 'tpm': [1200, 350, 2900]}, [271.01, 79.04, 654.95]], ['surface sector last', {'fare': 777.77, 'tpm': [800, 1505, 0]}, [269.94, 507.83, 0.0]], ['surface sector first', {'fare': 500.01, 'tpm': [0, 700, 905]}, [0.0, 218.07, 281.94]], ['single coupon', {'fare': 617.25, 'tpm': [2475]}, [617.25]], ['equal miles odd cents', {'fare': 100.0, 'tpm': [500, 500, 500]}, [33.33, 33.33, 33.34]], ['all surface', {'fare': 50.0, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 1', {'fare': 927.71, 'tpm': [5167, 2555]}, [620.75, 306.96]], ['sampled case 2', {'fare': 574.25, 'tpm': [3022]}, [574.25]], ['sampled case 3', {'fare': 1349.84, 'tpm': [0, 0]}, 'ERR_NO_MILES']]]
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
three coupons uneven[269.93, 78.73, 652.34][269.93, 78.73, 652.34]Passed
surface sector last[270.41, 507.36, 0.0][270.41, 507.36, 0.0]Passed
surface sector first[0.0, 218.62, 281.39][0.0, 218.61, 281.4]Failed
single coupon[123.45][123.45]Passed
equal miles odd cents[33.33, 33.33, 33.34][33.33, 33.33, 33.34]Passed
all surfaceERR_NO_MILESERR_NO_MILESPassed
sampled case 1[57.22, 1508.65][57.21, 1508.66]Failed
sampled case 2[583.22, 0.0, 0.0][583.22, 0.0, 0.0]Passed
sampled case 3[2079.37][2079.37]Passed

SHA-256 / f458d79640f98a071daebe8817b011540c558bc27e62d6ef25c61909649b939a

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    tpm = x['tpm']
    total = sum(tpm)
    if total == 0: return 'ERR_NO_MILES'
    cents = round(x['fare'] * 100)
    shares = [math.ceil(cents * t / total) for t in tpm]
    last = max(i for i, t in enumerate(tpm) if t > 0)
    shares[last] += cents - sum(shares)
    return [s / 100 for s in shares]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['three coupons uneven', {'fare': 1001.0, 'tpm': [1200, 350, 2900]}, [269.93, 78.73, 652.34]], ['surface sector last', {'fare': 777.77, 'tpm': [800, 1501, 0]}, [270.41, 507.36, 0.0]], ['surface sector first', {'fare': 500.01, 'tpm': [0, 700, 901]}, [0.0, 218.61, 281.4]], ['single coupon', {'fare': 123.45, 'tpm': [2475]}, [123.45]], ['equal miles odd cents', {'fare': 100.0, 'tpm': [500, 500, 500]}, [33.33, 33.33, 33.34]], ['all surface', {'fare': 50.0, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 1', {'fare': 1565.87, 'tpm': [193, 5089]}, [57.21, 1508.66]], ['sampled case 2', {'fare': 583.22, 'tpm': [1271, 0, 0]}, [583.22, 0.0, 0.0]], ['sampled case 3', {'fare': 2079.37, 'tpm': [1800]}, [2079.37]]], [['three coupons uneven', {'fare': 1002.0, 'tpm': [1200, 350, 2900]}, [270.2, 78.8, 653.0]], ['surface sector last', {'fare': 777.77, 'tpm': [800, 1502, 0]}, [270.29, 507.48, 0.0]], ['surface sector first', {'fare': 500.01, 'tpm': [0, 700, 902]}, [0.0, 218.48, 281.53]], ['single coupon', {'fare': 246.9, 'tpm': [2475]}, [246.9]], ['equal miles odd cents', {'fare': 100.0, 'tpm': [500, 500, 500]}, [33.33, 33.33, 33.34]], ['all surface', {'fare': 50.0, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 1', {'fare': 2915.76, 'tpm': [0, 5491, 214, 782]}, [0.0, 2468.08, 96.18, 351.5]], ['sampled case 2', {'fare': 2482.84, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 3', {'fare': 1177.57, 'tpm': [0, 0]}, 'ERR_NO_MILES']], [['three coupons uneven', {'fare': 1003.0, 'tpm': [1200, 350, 2900]}, [270.47, 78.88, 653.65]], ['surface sector last', {'fare': 777.77, 'tpm': [800, 1503, 0]}, [270.17, 507.6, 0.0]], ['surface sector first', {'fare': 500.01, 'tpm': [0, 700, 903]}, [0.0, 218.34, 281.67]], ['single coupon', {'fare': 370.35, 'tpm': [2475]}, [370.35]], ['equal miles odd cents', {'fare': 100.0, 'tpm': [500, 500, 500]}, [33.33, 33.33, 33.34]], ['all surface', {'fare': 50.0, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 1', {'fare': 110.22, 'tpm': [0]}, 'ERR_NO_MILES'], ['sampled case 2', {'fare': 836.64, 'tpm': [5298, 5970, 0, 5279]}, [267.87, 301.85, 0.0, 266.92]], ['sampled case 3', {'fare': 218.58, 'tpm': [5530]}, [218.58]]], [['three coupons uneven', {'fare': 1004.0, 'tpm': [1200, 350, 2900]}, [270.74, 78.96, 654.3]], ['surface sector last', {'fare': 777.77, 'tpm': [800, 1504, 0]}, [270.05, 507.72, 0.0]], ['surface sector first', {'fare': 500.01, 'tpm': [0, 700, 904]}, [0.0, 218.2, 281.81]], ['single coupon', {'fare': 493.8, 'tpm': [2475]}, [493.8]], ['equal miles odd cents', {'fare': 100.0, 'tpm': [500, 500, 500]}, [33.33, 33.33, 33.34]], ['all surface', {'fare': 50.0, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 1', {'fare': 524.52, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 2', {'fare': 1224.53, 'tpm': [0, 1463]}, [0.0, 1224.53]], ['sampled case 3', {'fare': 2475.89, 'tpm': [0]}, 'ERR_NO_MILES']], [['three coupons uneven', {'fare': 1005.0, 'tpm': [1200, 350, 2900]}, [271.01, 79.04, 654.95]], ['surface sector last', {'fare': 777.77, 'tpm': [800, 1505, 0]}, [269.94, 507.83, 0.0]], ['surface sector first', {'fare': 500.01, 'tpm': [0, 700, 905]}, [0.0, 218.07, 281.94]], ['single coupon', {'fare': 617.25, 'tpm': [2475]}, [617.25]], ['equal miles odd cents', {'fare': 100.0, 'tpm': [500, 500, 500]}, [33.33, 33.33, 33.34]], ['all surface', {'fare': 50.0, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 1', {'fare': 927.71, 'tpm': [5167, 2555]}, [620.75, 306.96]], ['sampled case 2', {'fare': 574.25, 'tpm': [3022]}, [574.25]], ['sampled case 3', {'fare': 1349.84, 'tpm': [0, 0]}, 'ERR_NO_MILES']]]
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
three coupons uneven[269.94, 78.74, 652.32][269.93, 78.73, 652.34]Failed
surface sector last[270.42, 507.35, 0.0][270.41, 507.36, 0.0]Failed
surface sector first[0.0, 218.62, 281.39][0.0, 218.61, 281.4]Failed
single coupon[123.45][123.45]Passed
equal miles odd cents[33.34, 33.34, 33.32][33.33, 33.33, 33.34]Failed
all surfaceERR_NO_MILESERR_NO_MILESPassed
sampled case 1[57.22, 1508.65][57.21, 1508.66]Failed
sampled case 2[583.22, 0.0, 0.0][583.22, 0.0, 0.0]Passed
sampled case 3[2079.37][2079.37]Passed

SHA-256 / b848de553fda0f7cf503da025662d2454f5d11d8c5bf7136961255a6adc44250

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    tpm = x['tpm']
    total = sum(tpm)
    if total == 0: return 'ERR_NO_MILES'
    cents = round(x['fare'] * 100)
    shares = [cents * t // total for t in tpm]
    last = max(i for i, t in enumerate(tpm) if t > 0)
    shares[last] += cents - sum(shares)
    return [s / 100 for s in shares]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['three coupons uneven', {'fare': 1001.0, 'tpm': [1200, 350, 2900]}, [269.93, 78.73, 652.34]], ['surface sector last', {'fare': 777.77, 'tpm': [800, 1501, 0]}, [270.41, 507.36, 0.0]], ['surface sector first', {'fare': 500.01, 'tpm': [0, 700, 901]}, [0.0, 218.61, 281.4]], ['single coupon', {'fare': 123.45, 'tpm': [2475]}, [123.45]], ['equal miles odd cents', {'fare': 100.0, 'tpm': [500, 500, 500]}, [33.33, 33.33, 33.34]], ['all surface', {'fare': 50.0, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 1', {'fare': 1565.87, 'tpm': [193, 5089]}, [57.21, 1508.66]], ['sampled case 2', {'fare': 583.22, 'tpm': [1271, 0, 0]}, [583.22, 0.0, 0.0]], ['sampled case 3', {'fare': 2079.37, 'tpm': [1800]}, [2079.37]]], [['three coupons uneven', {'fare': 1002.0, 'tpm': [1200, 350, 2900]}, [270.2, 78.8, 653.0]], ['surface sector last', {'fare': 777.77, 'tpm': [800, 1502, 0]}, [270.29, 507.48, 0.0]], ['surface sector first', {'fare': 500.01, 'tpm': [0, 700, 902]}, [0.0, 218.48, 281.53]], ['single coupon', {'fare': 246.9, 'tpm': [2475]}, [246.9]], ['equal miles odd cents', {'fare': 100.0, 'tpm': [500, 500, 500]}, [33.33, 33.33, 33.34]], ['all surface', {'fare': 50.0, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 1', {'fare': 2915.76, 'tpm': [0, 5491, 214, 782]}, [0.0, 2468.08, 96.18, 351.5]], ['sampled case 2', {'fare': 2482.84, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 3', {'fare': 1177.57, 'tpm': [0, 0]}, 'ERR_NO_MILES']], [['three coupons uneven', {'fare': 1003.0, 'tpm': [1200, 350, 2900]}, [270.47, 78.88, 653.65]], ['surface sector last', {'fare': 777.77, 'tpm': [800, 1503, 0]}, [270.17, 507.6, 0.0]], ['surface sector first', {'fare': 500.01, 'tpm': [0, 700, 903]}, [0.0, 218.34, 281.67]], ['single coupon', {'fare': 370.35, 'tpm': [2475]}, [370.35]], ['equal miles odd cents', {'fare': 100.0, 'tpm': [500, 500, 500]}, [33.33, 33.33, 33.34]], ['all surface', {'fare': 50.0, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 1', {'fare': 110.22, 'tpm': [0]}, 'ERR_NO_MILES'], ['sampled case 2', {'fare': 836.64, 'tpm': [5298, 5970, 0, 5279]}, [267.87, 301.85, 0.0, 266.92]], ['sampled case 3', {'fare': 218.58, 'tpm': [5530]}, [218.58]]], [['three coupons uneven', {'fare': 1004.0, 'tpm': [1200, 350, 2900]}, [270.74, 78.96, 654.3]], ['surface sector last', {'fare': 777.77, 'tpm': [800, 1504, 0]}, [270.05, 507.72, 0.0]], ['surface sector first', {'fare': 500.01, 'tpm': [0, 700, 904]}, [0.0, 218.2, 281.81]], ['single coupon', {'fare': 493.8, 'tpm': [2475]}, [493.8]], ['equal miles odd cents', {'fare': 100.0, 'tpm': [500, 500, 500]}, [33.33, 33.33, 33.34]], ['all surface', {'fare': 50.0, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 1', {'fare': 524.52, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 2', {'fare': 1224.53, 'tpm': [0, 1463]}, [0.0, 1224.53]], ['sampled case 3', {'fare': 2475.89, 'tpm': [0]}, 'ERR_NO_MILES']], [['three coupons uneven', {'fare': 1005.0, 'tpm': [1200, 350, 2900]}, [271.01, 79.04, 654.95]], ['surface sector last', {'fare': 777.77, 'tpm': [800, 1505, 0]}, [269.94, 507.83, 0.0]], ['surface sector first', {'fare': 500.01, 'tpm': [0, 700, 905]}, [0.0, 218.07, 281.94]], ['single coupon', {'fare': 617.25, 'tpm': [2475]}, [617.25]], ['equal miles odd cents', {'fare': 100.0, 'tpm': [500, 500, 500]}, [33.33, 33.33, 33.34]], ['all surface', {'fare': 50.0, 'tpm': [0, 0]}, 'ERR_NO_MILES'], ['sampled case 1', {'fare': 927.71, 'tpm': [5167, 2555]}, [620.75, 306.96]], ['sampled case 2', {'fare': 574.25, 'tpm': [3022]}, [574.25]], ['sampled case 3', {'fare': 1349.84, 'tpm': [0, 0]}, 'ERR_NO_MILES']]]
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
three coupons uneven[269.93, 78.73, 652.34][269.93, 78.73, 652.34]Passed
surface sector last[270.41, 507.36, 0.0][270.41, 507.36, 0.0]Passed
surface sector first[0.0, 218.61, 281.4][0.0, 218.61, 281.4]Passed
single coupon[123.45][123.45]Passed
equal miles odd cents[33.33, 33.33, 33.34][33.33, 33.33, 33.34]Passed
all surfaceERR_NO_MILESERR_NO_MILESPassed
sampled case 1[57.21, 1508.66][57.21, 1508.66]Passed
sampled case 2[583.22, 0.0, 0.0][583.22, 0.0, 0.0]Passed
sampled case 3[2079.37][2079.37]Passed

SHA-256 / 0fb09043b9c4f45f0e65863b16df995545ef944ae79663b010da03b6b59d9ff0

Verification & scope

A stipulated toy fare-rule contract with invented constants; it is not an ATPCO or carrier tariff implementation and makes no claim of industry-standard conformance. 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:46.720078+00:00.

Case digest / ab81828902221f6201fdf6d236f5d62e6e6a6815bbe733fb0e29861c71e48504