FA-65986 / Aviation weight and balance / Open access
Ballast sized to reach the opposite limit · case 01
An aft-CG aircraft is ballasted all the way to the forward limit, adding hundreds of unnecessary pounds.
ROOT CAUSE
The target limit is chosen backwards: aft violations target the forward limit and vice versa.
VERIFIED REPAIR
Target the aft limit for aft CG and the forward limit for forward CG.
Unsuccessful approach: Targeting mid-envelope is conservative but still over-ballasts and triggers false overweight results.
Case contract
Input [W lb, CG, fwd limit, aft limit, ballast arm, max weight]. Inside inclusive limits -> 0. Otherwise ballast B brings CG to the violated limit: B = W*(CG-limit)/(limit-arm), rounded up to whole lb; ballast arm not on the corrective side of that limit -> 'ERR_BALLAST_ARM'; W+B above max -> 'ERR_OVERWEIGHT'.
Why this case matters
Ballast adds weight at a fixed station; the required amount depends on the distance from the ballast arm to the violated limit, and adds to gross weight.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
W, cg, fwd, aft, ba, maxw = x
if fwd <= cg <= aft: return 0
lim = fwd if cg > aft else aft
if (cg > aft and ba >= aft) or (cg < fwd and ba <= fwd): return 'ERR_BALLAST_ARM'
b = math.ceil(round(W * (cg - lim) / (lim - ba), 6))
if W + b > maxw: return 'ERR_OVERWEIGHT'
return b
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['aft CG nose ballast', [1800, 48.0, 35.0, 47.3, 10.0, 2550], 34], ['forward CG tail ballast', [1700, 34.2, 35.05, 47.3, 150.0, 2550], 13], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 21.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2250, 36.0, 36.0, 46.0, 101.0, 2700], 0], ['sampled case 2', [2220, 44.7, 33.9, 44.7, 121.5, 2550], 0], ['sampled case 3', [2400, 39.05, 36.3, 46.8, 9.5, 2400], 0]], [['aft CG nose ballast', [1800, 48.1, 35.0, 47.3, 10.0, 2550], 39], ['forward CG tail ballast', [1700, 34.2, 35.1, 47.3, 150.0, 2550], 14], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 22.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2035, 44.73, 36.5, 45.1, 11.9, 3000], 0], ['sampled case 2', [1925, 46.69, 36.9, 45.7, 120.5, 2550], 'ERR_BALLAST_ARM'], ['sampled case 3', [2440, 47.5, 35.1, 47.5, 46.2, 2400], 0]], [['aft CG nose ballast', [1800, 48.199999999999996, 35.0, 47.3, 10.0, 2550], 44], ['forward CG tail ballast', [1700, 34.2, 35.15, 47.3, 150.0, 2550], 15], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 23.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2510, 41.12, 36.1, 47.4, 155.2, 2700], 0], ['sampled case 2', [1785, 32.94, 35.6, 44.4, 94.3, 2400], 81], ['sampled case 3', [2400, 37.65, 34.3, 45.9, 140.6, 2550], 0]], [['aft CG nose ballast', [1800, 48.3, 35.0, 47.3, 10.0, 2550], 49], ['forward CG tail ballast', [1700, 34.2, 35.2, 47.3, 150.0, 2550], 15], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 24.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [1590, 30.16, 33.1, 46.2, 118.7, 2550], 55], ['sampled case 2', [1710, 32.9, 34.8, 45.0, 129.9, 2550], 35], ['sampled case 3', [1755, 35.34, 36.3, 47.0, 127.7, 2700], 19]], [['aft CG nose ballast', [1800, 48.4, 35.0, 47.3, 10.0, 2550], 54], ['forward CG tail ballast', [1700, 34.2, 35.25, 47.3, 150.0, 2550], 16], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 25.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [1745, 31.68, 34.3, 46.9, 112.4, 2550], 59], ['sampled case 2', [1645, 34.52, 36.5, 47.5, 5.2, 2400], 'ERR_BALLAST_ARM'], ['sampled case 3', [1850, 32.93, 34.5, 46.9, 56.9, 2700], 130]]]
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 |
|---|---|---|---|
| aft CG nose ballast | ERR_OVERWEIGHT | 34 | Failed |
| forward CG tail ballast | 217 | 13 | Failed |
| in envelope | 0 | 0 | Passed |
| exactly on aft limit | 0 | 0 | Passed |
| exactly on forward limit | 0 | 0 | Passed |
| ballast arm behind aft limit | ERR_BALLAST_ARM | ERR_BALLAST_ARM | Passed |
| forward case ballast in nose | ERR_BALLAST_ARM | ERR_BALLAST_ARM | Passed |
| ballast would overweight | ERR_OVERWEIGHT | ERR_OVERWEIGHT | Passed |
| ballast reaches exactly max | ERR_OVERWEIGHT | 10 | Failed |
| sampled case 1 | 0 | 0 | Passed |
| sampled case 2 | 0 | 0 | Passed |
| sampled case 3 | 0 | 0 | Passed |
SHA-256 / c6e293a813130a2c86ddb71220a7cabc352616a87210537f07bdee008b9d7f08
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
W, cg, fwd, aft, ba, maxw = x
if fwd <= cg <= aft: return 0
lim = (fwd + aft) / 2
if (cg > aft and ba >= aft) or (cg < fwd and ba <= fwd): return 'ERR_BALLAST_ARM'
b = math.ceil(round(W * (cg - lim) / (lim - ba), 6))
if W + b > maxw: return 'ERR_OVERWEIGHT'
return b
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['aft CG nose ballast', [1800, 48.0, 35.0, 47.3, 10.0, 2550], 34], ['forward CG tail ballast', [1700, 34.2, 35.05, 47.3, 150.0, 2550], 13], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 21.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2250, 36.0, 36.0, 46.0, 101.0, 2700], 0], ['sampled case 2', [2220, 44.7, 33.9, 44.7, 121.5, 2550], 0], ['sampled case 3', [2400, 39.05, 36.3, 46.8, 9.5, 2400], 0]], [['aft CG nose ballast', [1800, 48.1, 35.0, 47.3, 10.0, 2550], 39], ['forward CG tail ballast', [1700, 34.2, 35.1, 47.3, 150.0, 2550], 14], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 22.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2035, 44.73, 36.5, 45.1, 11.9, 3000], 0], ['sampled case 2', [1925, 46.69, 36.9, 45.7, 120.5, 2550], 'ERR_BALLAST_ARM'], ['sampled case 3', [2440, 47.5, 35.1, 47.5, 46.2, 2400], 0]], [['aft CG nose ballast', [1800, 48.199999999999996, 35.0, 47.3, 10.0, 2550], 44], ['forward CG tail ballast', [1700, 34.2, 35.15, 47.3, 150.0, 2550], 15], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 23.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2510, 41.12, 36.1, 47.4, 155.2, 2700], 0], ['sampled case 2', [1785, 32.94, 35.6, 44.4, 94.3, 2400], 81], ['sampled case 3', [2400, 37.65, 34.3, 45.9, 140.6, 2550], 0]], [['aft CG nose ballast', [1800, 48.3, 35.0, 47.3, 10.0, 2550], 49], ['forward CG tail ballast', [1700, 34.2, 35.2, 47.3, 150.0, 2550], 15], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 24.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [1590, 30.16, 33.1, 46.2, 118.7, 2550], 55], ['sampled case 2', [1710, 32.9, 34.8, 45.0, 129.9, 2550], 35], ['sampled case 3', [1755, 35.34, 36.3, 47.0, 127.7, 2700], 19]], [['aft CG nose ballast', [1800, 48.4, 35.0, 47.3, 10.0, 2550], 54], ['forward CG tail ballast', [1700, 34.2, 35.25, 47.3, 150.0, 2550], 16], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 25.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [1745, 31.68, 34.3, 46.9, 112.4, 2550], 59], ['sampled case 2', [1645, 34.52, 36.5, 47.5, 5.2, 2400], 'ERR_BALLAST_ARM'], ['sampled case 3', [1850, 32.93, 34.5, 46.9, 56.9, 2700], 130]]]
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 |
|---|---|---|---|
| aft CG nose ballast | 396 | 34 | Failed |
| forward CG tail ballast | 109 | 13 | Failed |
| in envelope | 0 | 0 | Passed |
| exactly on aft limit | 0 | 0 | Passed |
| exactly on forward limit | 0 | 0 | Passed |
| ballast arm behind aft limit | ERR_BALLAST_ARM | ERR_BALLAST_ARM | Passed |
| forward case ballast in nose | ERR_BALLAST_ARM | ERR_BALLAST_ARM | Passed |
| ballast would overweight | ERR_OVERWEIGHT | ERR_OVERWEIGHT | Passed |
| ballast reaches exactly max | ERR_OVERWEIGHT | 10 | Failed |
| sampled case 1 | 0 | 0 | Passed |
| sampled case 2 | 0 | 0 | Passed |
| sampled case 3 | 0 | 0 | Passed |
SHA-256 / 6fd17b72e4d7b63c257538010ffe9f7996360acc5b4c22c456fdf02b365e56a5
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
W, cg, fwd, aft, ba, maxw = x
if fwd <= cg <= aft: return 0
lim = aft if cg > aft else fwd
if (cg > aft and ba >= aft) or (cg < fwd and ba <= fwd): return 'ERR_BALLAST_ARM'
b = math.ceil(round(W * (cg - lim) / (lim - ba), 6))
if W + b > maxw: return 'ERR_OVERWEIGHT'
return b
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['aft CG nose ballast', [1800, 48.0, 35.0, 47.3, 10.0, 2550], 34], ['forward CG tail ballast', [1700, 34.2, 35.05, 47.3, 150.0, 2550], 13], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 21.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2250, 36.0, 36.0, 46.0, 101.0, 2700], 0], ['sampled case 2', [2220, 44.7, 33.9, 44.7, 121.5, 2550], 0], ['sampled case 3', [2400, 39.05, 36.3, 46.8, 9.5, 2400], 0]], [['aft CG nose ballast', [1800, 48.1, 35.0, 47.3, 10.0, 2550], 39], ['forward CG tail ballast', [1700, 34.2, 35.1, 47.3, 150.0, 2550], 14], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 22.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2035, 44.73, 36.5, 45.1, 11.9, 3000], 0], ['sampled case 2', [1925, 46.69, 36.9, 45.7, 120.5, 2550], 'ERR_BALLAST_ARM'], ['sampled case 3', [2440, 47.5, 35.1, 47.5, 46.2, 2400], 0]], [['aft CG nose ballast', [1800, 48.199999999999996, 35.0, 47.3, 10.0, 2550], 44], ['forward CG tail ballast', [1700, 34.2, 35.15, 47.3, 150.0, 2550], 15], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 23.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2510, 41.12, 36.1, 47.4, 155.2, 2700], 0], ['sampled case 2', [1785, 32.94, 35.6, 44.4, 94.3, 2400], 81], ['sampled case 3', [2400, 37.65, 34.3, 45.9, 140.6, 2550], 0]], [['aft CG nose ballast', [1800, 48.3, 35.0, 47.3, 10.0, 2550], 49], ['forward CG tail ballast', [1700, 34.2, 35.2, 47.3, 150.0, 2550], 15], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 24.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [1590, 30.16, 33.1, 46.2, 118.7, 2550], 55], ['sampled case 2', [1710, 32.9, 34.8, 45.0, 129.9, 2550], 35], ['sampled case 3', [1755, 35.34, 36.3, 47.0, 127.7, 2700], 19]], [['aft CG nose ballast', [1800, 48.4, 35.0, 47.3, 10.0, 2550], 54], ['forward CG tail ballast', [1700, 34.2, 35.25, 47.3, 150.0, 2550], 16], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 25.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [1745, 31.68, 34.3, 46.9, 112.4, 2550], 59], ['sampled case 2', [1645, 34.52, 36.5, 47.5, 5.2, 2400], 'ERR_BALLAST_ARM'], ['sampled case 3', [1850, 32.93, 34.5, 46.9, 56.9, 2700], 130]]]
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 |
|---|---|---|---|
| aft CG nose ballast | 34 | 34 | Passed |
| forward CG tail ballast | 13 | 13 | Passed |
| in envelope | 0 | 0 | Passed |
| exactly on aft limit | 0 | 0 | Passed |
| exactly on forward limit | 0 | 0 | Passed |
| ballast arm behind aft limit | ERR_BALLAST_ARM | ERR_BALLAST_ARM | Passed |
| forward case ballast in nose | ERR_BALLAST_ARM | ERR_BALLAST_ARM | Passed |
| ballast would overweight | ERR_OVERWEIGHT | ERR_OVERWEIGHT | Passed |
| ballast reaches exactly max | 10 | 10 | Passed |
| sampled case 1 | 0 | 0 | Passed |
| sampled case 2 | 0 | 0 | Passed |
| sampled case 3 | 0 | 0 | Passed |
SHA-256 / 0c56172482e7f73b04eefe0b9dc455f717a913852fbca2f64676928558b1268f
Verification & scope
A deterministic toy loading model with stipulated constants; it is not an approved aircraft flight manual procedure and makes no claim of regulatory 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:39.120334+00:00.
Case digest / 561132edaa3187345402c1a93496d9cb56b775b35384648f58985e2cb0d96b83