FA-86951 / Physics integrator stability / Open access
Critical step uses one over omega instead of two over omega · case 01
The solver runs twice as many substeps as the contract bound requires.
ROOT CAUSE
The symplectic Euler limit 2/omega is written as 1/omega.
VERIFIED REPAIR
Keep the factor two from the leapfrog stability interval.
Unsuccessful approach: Using pi/omega exceeds the stability limit.
Case contract
solve(springs, safety, dt_frame, max_sub): springs are [k, inv_mass_a, inv_mass_b] (inverse mass 0 = static). A spring with k>0 and nonzero summed inverse mass w limits the substep to safety*2/sqrt(k*w). n=ceil(dt_frame/h_min) clamped to [1,max_sub]; return [n, dt_frame/n rounded to 6, whether n had to be clamped down]. No limiting spring gives [1, dt_frame, False].
Why this case matters
Game and robotics physics loops depend on integrator update order, step control and stabilization terms; a wrong decision point turns a stable simulation into drifting or exploding motion.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(springs, safety, dt_frame, max_sub):
hc = None
for k, im1, im2 in springs:
w = im1 + im2
if w == 0 or k <= 0:
continue
h = safety / math.sqrt(k * w)
if hc is None or h < hc:
hc = h
if hc is None:
return [1, round(dt_frame, 6), False]
n = math.ceil(dt_frame / hc - 1e-12)
clamped = n > max_sub
n = min(max(n, 1), max_sub)
return [n, round(dt_frame / n, 6), clamped]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[[[181.3, 0.765, 0.718], [113.7, 1.47, 0.0]], 0.8, 0.05, 2], [1, 0.05, False]], [[[[0.0, 0.185, 0.0], [369.7, 0.0, 1.891], [271.6, 0.712, 0.0], [0.0, 0.0, 0.0]], 0.9, 0.05, 5], [1, 0.05, False]], [[[[106.5, 1.63, 0.0]], 0.9, 0.016666666666666666, 2], [1, 0.016667, False]], [[[[148.6, 0.387, 0.848], [287.5, 0.0, 1.337]], 0.5, 0.03333333333333333, 2], [1, 0.033333, False]], [[[[127.0, 1.3, 0.0]], 0.5, 0.03333333333333333, 10], [1, 0.033333, False]], [[[[0.0, 0.133, 0.288], [277.5, 1.393, 0.313], [186.0, 1.259, 0.245], [78.0, 1.034, 0.148]], 0.9, 0.03333333333333333, 1], [1, 0.033333, False]], [[[[383.4, 1.008, 0.724]], 0.9, 0.1, 12], [2, 0.05, False]], [[[[200.1, 1.603, 0.972], [288.5, 1.122, 1.97]], 0.5, 0.1, 8], [3, 0.033333, False]]], [[[[[211.7, 1.064, 0.812], [384.0, 1.693, 1.686]], 0.5, 0.1, 7], [4, 0.025, False]], [[[[95.6, 1.372, 0.756], [95.0, 0.946, 1.265], [396.4, 1.377, 0.0], [218.5, 0.0, 1.301]], 0.5, 0.03333333333333333, 1], [1, 0.033333, False]], [[[[14.3, 0.266, 0.874], [8.7, 1.8, 1.042]], 0.8, 0.1, 10], [1, 0.1, False]], [[[[97.9, 0.409, 0.102], [187.1, 0.0, 1.876], [175.5, 0.772, 1.165]], 0.9, 0.1, 3], [2, 0.05, False]], [[[[0.0, 1.446, 0.0]], 0.8, 0.03333333333333333, 11], [1, 0.033333, False]], [[[[52.7, 0.654, 0.798], [173.5, 1.41, 0.659]], 0.9, 0.1, 3], [2, 0.05, False]], [[[[233.9, 0.0, 0.0], [376.9, 0.322, 1.171], [104.8, 1.006, 0.815]], 0.9, 0.05, 2], [1, 0.05, False]], [[[[205.5, 0.0, 0.24]], 0.8, 0.03333333333333333, 8], [1, 0.033333, False]]], [[[[[281.2, 0.534, 0.0], [35.0, 0.0, 0.0]], 0.5, 0.03333333333333333, 12], [1, 0.033333, False]], [[[[308.1, 0.0, 0.454], [396.0, 0.194, 1.062]], 0.5, 0.05, 10], [2, 0.025, False]], [[[[153.0, 0.822, 1.885]], 0.8, 0.016666666666666666, 11], [1, 0.016667, False]], [[[[349.4, 0.0, 1.034], [394.6, 1.246, 1.597], [212.5, 0.0, 0.0], [153.3, 0.0, 1.362]], 0.8, 0.03333333333333333, 10], [1, 0.033333, False]], [[[[194.8, 0.0, 1.946], [76.0, 0.616, 1.748], [133.0, 0.0, 1.751], [341.8, 1.754, 0.0]], 0.5, 0.05, 8], [2, 0.025, False]], [[[[84.5, 1.172, 0.389], [387.6, 0.894, 0.997], [341.4, 0.801, 0.0]], 0.9, 0.05, 1], [1, 0.05, False]], [[[[139.9, 1.445, 0.0], [19.1, 0.0, 0.157], [93.7, 1.683, 0.761], [185.2, 0.0, 0.0]], 0.9, 0.016666666666666666, 9], [1, 0.016667, False]], [[[[246.0, 0.0, 0.0], [348.1, 1.08, 0.0]], 0.9, 0.1, 7], [2, 0.05, False]]], [[[[[40.5, 0.524, 0.0], [195.2, 0.0, 0.632]], 0.8, 0.016666666666666666, 9], [1, 0.016667, False]], [[[[0.7, 0.0, 1.518], [157.3, 1.84, 0.368], [155.6, 0.0, 0.884], [325.1, 1.537, 0.59]], 0.5, 0.05, 9], [2, 0.025, False]], [[[[112.1, 1.978, 0.662]], 0.9, 0.016666666666666666, 10], [1, 0.016667, False]], [[[[20.9, 0.0, 0.0], [250.8, 0.0, 0.0]], 0.9, 0.05, 10], [1, 0.05, False]], [[[[348.9, 0.376, 0.912]], 0.5, 0.05, 6], [2, 0.025, False]], [[[[230.1, 0.0, 1.021], [77.8, 0.488, 1.614], [0.0, 0.798, 1.482]], 0.8, 0.03333333333333333, 5], [1, 0.033333, False]], [[[[295.6, 1.379, 0.496], [26.1, 1.99, 1.706], [6.0, 1.103, 1.549]], 0.8, 0.1, 10], [2, 0.05, False]], [[[[188.7, 1.402, 0.721], [392.3, 0.0, 1.896], [272.9, 0.701, 1.314], [383.2, 1.675, 1.515]], 0.5, 0.03333333333333333, 8], [2, 0.016667, False]]], [[[[[70.2, 1.762, 1.247], [340.8, 0.0, 1.231]], 0.9, 0.1, 12], [2, 0.05, False]], [[[[149.6, 1.802, 0.77], [102.2, 1.828, 0.436]], 0.5, 0.1, 7], [2, 0.05, False]], [[[[227.2, 1.778, 0.152]], 0.5, 0.05, 8], [2, 0.025, False]], [[[[336.1, 0.713, 0.0], [192.3, 1.124, 1.291], [177.3, 0.468, 0.473], [377.9, 0.567, 0.0]], 0.9, 0.03333333333333333, 11], [1, 0.033333, False]], [[[[0.0, 0.0, 1.51], [228.1, 0.0, 0.322], [74.8, 1.176, 1.179], [268.4, 1.044, 1.986]], 0.5, 0.05, 5], [2, 0.025, False]], [[[[333.7, 1.663, 0.348], [161.4, 0.0, 0.877]], 0.5, 0.1, 7], [3, 0.033333, False]], [[[[317.5, 0.0, 0.172]], 0.9, 0.03333333333333333, 3], [1, 0.033333, False]], [[[[140.9, 0.0, 0.527], [20.1, 0.0, 1.755], [0.0, 1.669, 0.955], [122.6, 0.0, 0.656]], 0.9, 0.016666666666666666, 8], [1, 0.016667, False]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("case %d" % i, 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 |
|---|---|---|---|
| case 0 | [2, 0.025, False] | [1, 0.05, False] | Failed |
| case 1 | [2, 0.025, False] | [1, 0.05, False] | Failed |
| case 2 | [1, 0.016667, False] | [1, 0.016667, False] | Passed |
| case 3 | [2, 0.016667, False] | [1, 0.033333, False] | Failed |
| case 4 | [1, 0.033333, False] | [1, 0.033333, False] | Passed |
| case 5 | [1, 0.033333, False] | [1, 0.033333, False] | Passed |
| case 6 | [3, 0.033333, False] | [2, 0.05, False] | Failed |
| case 7 | [6, 0.016667, False] | [3, 0.033333, False] | Failed |
SHA-256 / 93814adb2c792b83babe903abc4b52a360a77e9150b28f1c64acfb51a4e1087c
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(springs, safety, dt_frame, max_sub):
hc = None
for k, im1, im2 in springs:
w = im1 + im2
if w == 0 or k <= 0:
continue
h = safety * math.pi / math.sqrt(k * w)
if hc is None or h < hc:
hc = h
if hc is None:
return [1, round(dt_frame, 6), False]
n = math.ceil(dt_frame / hc - 1e-12)
clamped = n > max_sub
n = min(max(n, 1), max_sub)
return [n, round(dt_frame / n, 6), clamped]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[[[181.3, 0.765, 0.718], [113.7, 1.47, 0.0]], 0.8, 0.05, 2], [1, 0.05, False]], [[[[0.0, 0.185, 0.0], [369.7, 0.0, 1.891], [271.6, 0.712, 0.0], [0.0, 0.0, 0.0]], 0.9, 0.05, 5], [1, 0.05, False]], [[[[106.5, 1.63, 0.0]], 0.9, 0.016666666666666666, 2], [1, 0.016667, False]], [[[[148.6, 0.387, 0.848], [287.5, 0.0, 1.337]], 0.5, 0.03333333333333333, 2], [1, 0.033333, False]], [[[[127.0, 1.3, 0.0]], 0.5, 0.03333333333333333, 10], [1, 0.033333, False]], [[[[0.0, 0.133, 0.288], [277.5, 1.393, 0.313], [186.0, 1.259, 0.245], [78.0, 1.034, 0.148]], 0.9, 0.03333333333333333, 1], [1, 0.033333, False]], [[[[383.4, 1.008, 0.724]], 0.9, 0.1, 12], [2, 0.05, False]], [[[[200.1, 1.603, 0.972], [288.5, 1.122, 1.97]], 0.5, 0.1, 8], [3, 0.033333, False]]], [[[[[211.7, 1.064, 0.812], [384.0, 1.693, 1.686]], 0.5, 0.1, 7], [4, 0.025, False]], [[[[95.6, 1.372, 0.756], [95.0, 0.946, 1.265], [396.4, 1.377, 0.0], [218.5, 0.0, 1.301]], 0.5, 0.03333333333333333, 1], [1, 0.033333, False]], [[[[14.3, 0.266, 0.874], [8.7, 1.8, 1.042]], 0.8, 0.1, 10], [1, 0.1, False]], [[[[97.9, 0.409, 0.102], [187.1, 0.0, 1.876], [175.5, 0.772, 1.165]], 0.9, 0.1, 3], [2, 0.05, False]], [[[[0.0, 1.446, 0.0]], 0.8, 0.03333333333333333, 11], [1, 0.033333, False]], [[[[52.7, 0.654, 0.798], [173.5, 1.41, 0.659]], 0.9, 0.1, 3], [2, 0.05, False]], [[[[233.9, 0.0, 0.0], [376.9, 0.322, 1.171], [104.8, 1.006, 0.815]], 0.9, 0.05, 2], [1, 0.05, False]], [[[[205.5, 0.0, 0.24]], 0.8, 0.03333333333333333, 8], [1, 0.033333, False]]], [[[[[281.2, 0.534, 0.0], [35.0, 0.0, 0.0]], 0.5, 0.03333333333333333, 12], [1, 0.033333, False]], [[[[308.1, 0.0, 0.454], [396.0, 0.194, 1.062]], 0.5, 0.05, 10], [2, 0.025, False]], [[[[153.0, 0.822, 1.885]], 0.8, 0.016666666666666666, 11], [1, 0.016667, False]], [[[[349.4, 0.0, 1.034], [394.6, 1.246, 1.597], [212.5, 0.0, 0.0], [153.3, 0.0, 1.362]], 0.8, 0.03333333333333333, 10], [1, 0.033333, False]], [[[[194.8, 0.0, 1.946], [76.0, 0.616, 1.748], [133.0, 0.0, 1.751], [341.8, 1.754, 0.0]], 0.5, 0.05, 8], [2, 0.025, False]], [[[[84.5, 1.172, 0.389], [387.6, 0.894, 0.997], [341.4, 0.801, 0.0]], 0.9, 0.05, 1], [1, 0.05, False]], [[[[139.9, 1.445, 0.0], [19.1, 0.0, 0.157], [93.7, 1.683, 0.761], [185.2, 0.0, 0.0]], 0.9, 0.016666666666666666, 9], [1, 0.016667, False]], [[[[246.0, 0.0, 0.0], [348.1, 1.08, 0.0]], 0.9, 0.1, 7], [2, 0.05, False]]], [[[[[40.5, 0.524, 0.0], [195.2, 0.0, 0.632]], 0.8, 0.016666666666666666, 9], [1, 0.016667, False]], [[[[0.7, 0.0, 1.518], [157.3, 1.84, 0.368], [155.6, 0.0, 0.884], [325.1, 1.537, 0.59]], 0.5, 0.05, 9], [2, 0.025, False]], [[[[112.1, 1.978, 0.662]], 0.9, 0.016666666666666666, 10], [1, 0.016667, False]], [[[[20.9, 0.0, 0.0], [250.8, 0.0, 0.0]], 0.9, 0.05, 10], [1, 0.05, False]], [[[[348.9, 0.376, 0.912]], 0.5, 0.05, 6], [2, 0.025, False]], [[[[230.1, 0.0, 1.021], [77.8, 0.488, 1.614], [0.0, 0.798, 1.482]], 0.8, 0.03333333333333333, 5], [1, 0.033333, False]], [[[[295.6, 1.379, 0.496], [26.1, 1.99, 1.706], [6.0, 1.103, 1.549]], 0.8, 0.1, 10], [2, 0.05, False]], [[[[188.7, 1.402, 0.721], [392.3, 0.0, 1.896], [272.9, 0.701, 1.314], [383.2, 1.675, 1.515]], 0.5, 0.03333333333333333, 8], [2, 0.016667, False]]], [[[[[70.2, 1.762, 1.247], [340.8, 0.0, 1.231]], 0.9, 0.1, 12], [2, 0.05, False]], [[[[149.6, 1.802, 0.77], [102.2, 1.828, 0.436]], 0.5, 0.1, 7], [2, 0.05, False]], [[[[227.2, 1.778, 0.152]], 0.5, 0.05, 8], [2, 0.025, False]], [[[[336.1, 0.713, 0.0], [192.3, 1.124, 1.291], [177.3, 0.468, 0.473], [377.9, 0.567, 0.0]], 0.9, 0.03333333333333333, 11], [1, 0.033333, False]], [[[[0.0, 0.0, 1.51], [228.1, 0.0, 0.322], [74.8, 1.176, 1.179], [268.4, 1.044, 1.986]], 0.5, 0.05, 5], [2, 0.025, False]], [[[[333.7, 1.663, 0.348], [161.4, 0.0, 0.877]], 0.5, 0.1, 7], [3, 0.033333, False]], [[[[317.5, 0.0, 0.172]], 0.9, 0.03333333333333333, 3], [1, 0.033333, False]], [[[[140.9, 0.0, 0.527], [20.1, 0.0, 1.755], [0.0, 1.669, 0.955], [122.6, 0.0, 0.656]], 0.9, 0.016666666666666666, 8], [1, 0.016667, False]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("case %d" % i, 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 |
|---|---|---|---|
| case 0 | [1, 0.05, False] | [1, 0.05, False] | Passed |
| case 1 | [1, 0.05, False] | [1, 0.05, False] | Passed |
| case 2 | [1, 0.016667, False] | [1, 0.016667, False] | Passed |
| case 3 | [1, 0.033333, False] | [1, 0.033333, False] | Passed |
| case 4 | [1, 0.033333, False] | [1, 0.033333, False] | Passed |
| case 5 | [1, 0.033333, False] | [1, 0.033333, False] | Passed |
| case 6 | [1, 0.1, False] | [2, 0.05, False] | Failed |
| case 7 | [2, 0.05, False] | [3, 0.033333, False] | Failed |
SHA-256 / 6d50e3cefd8208152f69cd1dc6fd75595ad118b34293f2055c1569583b1d966b
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(springs, safety, dt_frame, max_sub):
hc = None
for k, im1, im2 in springs:
w = im1 + im2
if w == 0 or k <= 0:
continue
h = safety * 2.0 / math.sqrt(k * w)
if hc is None or h < hc:
hc = h
if hc is None:
return [1, round(dt_frame, 6), False]
n = math.ceil(dt_frame / hc - 1e-12)
clamped = n > max_sub
n = min(max(n, 1), max_sub)
return [n, round(dt_frame / n, 6), clamped]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[[[181.3, 0.765, 0.718], [113.7, 1.47, 0.0]], 0.8, 0.05, 2], [1, 0.05, False]], [[[[0.0, 0.185, 0.0], [369.7, 0.0, 1.891], [271.6, 0.712, 0.0], [0.0, 0.0, 0.0]], 0.9, 0.05, 5], [1, 0.05, False]], [[[[106.5, 1.63, 0.0]], 0.9, 0.016666666666666666, 2], [1, 0.016667, False]], [[[[148.6, 0.387, 0.848], [287.5, 0.0, 1.337]], 0.5, 0.03333333333333333, 2], [1, 0.033333, False]], [[[[127.0, 1.3, 0.0]], 0.5, 0.03333333333333333, 10], [1, 0.033333, False]], [[[[0.0, 0.133, 0.288], [277.5, 1.393, 0.313], [186.0, 1.259, 0.245], [78.0, 1.034, 0.148]], 0.9, 0.03333333333333333, 1], [1, 0.033333, False]], [[[[383.4, 1.008, 0.724]], 0.9, 0.1, 12], [2, 0.05, False]], [[[[200.1, 1.603, 0.972], [288.5, 1.122, 1.97]], 0.5, 0.1, 8], [3, 0.033333, False]]], [[[[[211.7, 1.064, 0.812], [384.0, 1.693, 1.686]], 0.5, 0.1, 7], [4, 0.025, False]], [[[[95.6, 1.372, 0.756], [95.0, 0.946, 1.265], [396.4, 1.377, 0.0], [218.5, 0.0, 1.301]], 0.5, 0.03333333333333333, 1], [1, 0.033333, False]], [[[[14.3, 0.266, 0.874], [8.7, 1.8, 1.042]], 0.8, 0.1, 10], [1, 0.1, False]], [[[[97.9, 0.409, 0.102], [187.1, 0.0, 1.876], [175.5, 0.772, 1.165]], 0.9, 0.1, 3], [2, 0.05, False]], [[[[0.0, 1.446, 0.0]], 0.8, 0.03333333333333333, 11], [1, 0.033333, False]], [[[[52.7, 0.654, 0.798], [173.5, 1.41, 0.659]], 0.9, 0.1, 3], [2, 0.05, False]], [[[[233.9, 0.0, 0.0], [376.9, 0.322, 1.171], [104.8, 1.006, 0.815]], 0.9, 0.05, 2], [1, 0.05, False]], [[[[205.5, 0.0, 0.24]], 0.8, 0.03333333333333333, 8], [1, 0.033333, False]]], [[[[[281.2, 0.534, 0.0], [35.0, 0.0, 0.0]], 0.5, 0.03333333333333333, 12], [1, 0.033333, False]], [[[[308.1, 0.0, 0.454], [396.0, 0.194, 1.062]], 0.5, 0.05, 10], [2, 0.025, False]], [[[[153.0, 0.822, 1.885]], 0.8, 0.016666666666666666, 11], [1, 0.016667, False]], [[[[349.4, 0.0, 1.034], [394.6, 1.246, 1.597], [212.5, 0.0, 0.0], [153.3, 0.0, 1.362]], 0.8, 0.03333333333333333, 10], [1, 0.033333, False]], [[[[194.8, 0.0, 1.946], [76.0, 0.616, 1.748], [133.0, 0.0, 1.751], [341.8, 1.754, 0.0]], 0.5, 0.05, 8], [2, 0.025, False]], [[[[84.5, 1.172, 0.389], [387.6, 0.894, 0.997], [341.4, 0.801, 0.0]], 0.9, 0.05, 1], [1, 0.05, False]], [[[[139.9, 1.445, 0.0], [19.1, 0.0, 0.157], [93.7, 1.683, 0.761], [185.2, 0.0, 0.0]], 0.9, 0.016666666666666666, 9], [1, 0.016667, False]], [[[[246.0, 0.0, 0.0], [348.1, 1.08, 0.0]], 0.9, 0.1, 7], [2, 0.05, False]]], [[[[[40.5, 0.524, 0.0], [195.2, 0.0, 0.632]], 0.8, 0.016666666666666666, 9], [1, 0.016667, False]], [[[[0.7, 0.0, 1.518], [157.3, 1.84, 0.368], [155.6, 0.0, 0.884], [325.1, 1.537, 0.59]], 0.5, 0.05, 9], [2, 0.025, False]], [[[[112.1, 1.978, 0.662]], 0.9, 0.016666666666666666, 10], [1, 0.016667, False]], [[[[20.9, 0.0, 0.0], [250.8, 0.0, 0.0]], 0.9, 0.05, 10], [1, 0.05, False]], [[[[348.9, 0.376, 0.912]], 0.5, 0.05, 6], [2, 0.025, False]], [[[[230.1, 0.0, 1.021], [77.8, 0.488, 1.614], [0.0, 0.798, 1.482]], 0.8, 0.03333333333333333, 5], [1, 0.033333, False]], [[[[295.6, 1.379, 0.496], [26.1, 1.99, 1.706], [6.0, 1.103, 1.549]], 0.8, 0.1, 10], [2, 0.05, False]], [[[[188.7, 1.402, 0.721], [392.3, 0.0, 1.896], [272.9, 0.701, 1.314], [383.2, 1.675, 1.515]], 0.5, 0.03333333333333333, 8], [2, 0.016667, False]]], [[[[[70.2, 1.762, 1.247], [340.8, 0.0, 1.231]], 0.9, 0.1, 12], [2, 0.05, False]], [[[[149.6, 1.802, 0.77], [102.2, 1.828, 0.436]], 0.5, 0.1, 7], [2, 0.05, False]], [[[[227.2, 1.778, 0.152]], 0.5, 0.05, 8], [2, 0.025, False]], [[[[336.1, 0.713, 0.0], [192.3, 1.124, 1.291], [177.3, 0.468, 0.473], [377.9, 0.567, 0.0]], 0.9, 0.03333333333333333, 11], [1, 0.033333, False]], [[[[0.0, 0.0, 1.51], [228.1, 0.0, 0.322], [74.8, 1.176, 1.179], [268.4, 1.044, 1.986]], 0.5, 0.05, 5], [2, 0.025, False]], [[[[333.7, 1.663, 0.348], [161.4, 0.0, 0.877]], 0.5, 0.1, 7], [3, 0.033333, False]], [[[[317.5, 0.0, 0.172]], 0.9, 0.03333333333333333, 3], [1, 0.033333, False]], [[[[140.9, 0.0, 0.527], [20.1, 0.0, 1.755], [0.0, 1.669, 0.955], [122.6, 0.0, 0.656]], 0.9, 0.016666666666666666, 8], [1, 0.016667, False]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("case %d" % i, 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 |
|---|---|---|---|
| case 0 | [1, 0.05, False] | [1, 0.05, False] | Passed |
| case 1 | [1, 0.05, False] | [1, 0.05, False] | Passed |
| case 2 | [1, 0.016667, False] | [1, 0.016667, False] | Passed |
| case 3 | [1, 0.033333, False] | [1, 0.033333, False] | Passed |
| case 4 | [1, 0.033333, False] | [1, 0.033333, False] | Passed |
| case 5 | [1, 0.033333, False] | [1, 0.033333, False] | Passed |
| case 6 | [2, 0.05, False] | [2, 0.05, False] | Passed |
| case 7 | [3, 0.033333, False] | [3, 0.033333, False] | Passed |
SHA-256 / 47073622d633ffce4fc60e69381ff14fa5e58437f0c2a2453ecc4d447625fcc4
Verification & scope
A deterministic bounded teaching model with stipulated toy conventions and rounded float output; not a production physics engine or a proof of numerical stability. 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:50:54.330998+00:00.
Case digest / 003c6b72e6753cd30635cb3551441220921d087d036aa662a0e308928a97c2a6