FAILURE MAP
← Case archive

FA-66746 / Airline fare rule evaluation / Open access

Rounding remainder assigned to the first coupon · case 01

The first coupon carries the remainder, even when it is a surface sector with no miles.

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

ROOT CAUSE

The remainder index is hard-coded to the first coupon.

VERIFIED REPAIR

Assign the remainder to the last coupon with nonzero miles.

Unsuccessful approach: Using the last coupon can put value on a trailing surface sector.

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 = [cents * t // total for t in tpm]
    last = 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.73, 652.33][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.01, 218.61, 281.39][0.0, 218.61, 281.4]Failed
single coupon[123.45][123.45]Passed
equal miles odd cents[33.34, 33.33, 33.33][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 / cce92b20f8d10b6086a1f3a86ca76256b3bee9eb371f1426f9e205ca34a44640

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 = [cents * t // total for t in tpm]
    last = len(tpm) - 1
    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.35, 0.01][270.41, 507.36, 0.0]Failed
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 / b63033daf67b19642504aca84d4cccf21e35756f67147a02ef8f964ea84d3909

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

Case digest / bb6e3db5dddd7a3941e518fe17bf78fe345f3a95ba4593fba07aace61816acd4