FAILURE MAP
← Case archive

FA-87241 / Physics integrator stability / Open access

Linear damping uses the explicit 1 - c*dt factor · case 01

High damping at coarse steps flips the velocity sign and the body jitters.

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

ROOT CAUSE

dl = 1 - dt*lin_damp can become negative.

VERIFIED REPAIR

Use the unconditionally stable 1/(1+dt*c) factor.

Unsuccessful approach: Clamping 1 - c*dt at zero stops the flip but still over-damps relative to the contract.

Case contract

solve(v, omega, lin_damp, ang_damp, dt, max_speed, sleep_lin, sleep_ang, sleep_time, kicks): per frame, a sleeping body wakes (timer reset) only when that frame's kick is nonzero, else it is skipped. Add the kick [dvx,dvy,domega], damp with 1/(1+dt*c) (linear and angular coefficients), clamp speed magnitude, then accumulate sleep time while |v|<sleep_lin and |omega|<sleep_ang (else reset). When timer>=sleep_time the body sleeps and velocities are zeroed. Return [vx, vy, omega, timer, asleep, frame index slept or -1].

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(v, omega, lin_damp, ang_damp, dt, max_speed, sleep_lin, sleep_ang, sleep_time, kicks):
    vx, vy = v
    w = omega
    timer = 0.0
    asleep = False
    slept_at = -1
    for f, (ax, ay, aw) in enumerate(kicks):
        if asleep:
            if ax or ay or aw:
                asleep = False
                timer = 0.0
            else:
                continue
        vx += ax
        vy += ay
        w += aw
        dl = 1.0 - dt * lin_damp
        vx *= dl
        vy *= dl
        w *= 1.0 / (1.0 + dt * ang_damp)
        sp = math.hypot(vx, vy)
        if sp > max_speed:
            s = max_speed / sp
            vx *= s
            vy *= s
        if math.hypot(vx, vy) < sleep_lin and abs(w) < sleep_ang:
            timer += dt
        else:
            timer = 0.0
        if timer >= sleep_time:
            asleep = True
            slept_at = f
            vx = vy = w = 0.0
    return [round(vx, 6), round(vy, 6), round(w, 6), round(timer, 6), asleep, slept_at]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[[-0.0, 0.0], 0.99, 2.0, 0.5, 0.015625, 8.0, 2.0, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [-2, 8, 0], [0, 0, 0], [0, 0, 0]]], [-1.823636, 7.294543, 0.0, 0.0, False, 1]], [[[-0.01, -0.01], 1.26, 0.5, 40.0, 0.015625, 3.0, 0.5, 1.0, 0.015625, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [1, 0, 0], [0, 0, 0], [0, 0, 0], [0, 8, 2]]], [0.363645, 2.977879, 1.230769, 0.0, False, 0]], [[[0.02, 0.01], 0.0, 0.5, 0.5, 0.015625, 8.0, 0.5, 1.0, 0.03125, [[0, 0, -0.5], [0, 0, 0], [0, 0, 0.5], [0, 0, -0.5], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.03125, True, 3]], [[[2.14, -0.12], 1.88, 80.0, 0.5, 0.015625, 8.0, 0.5, 0.3, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.007331, -0.000411, 1.780327, 0.0, False, -1]], [[[-0.02, 0.07], 0.0, 2.0, 5.0, 0.03125, 8.0, 0.5, 0.3, 0.0625, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0.5], [0, 0, 0.5]]], [0.0, 0.0, 0.806428, 0.0, False, 1]], [[[0.0, -0.04], 0.0, 0.5, 0.5, 0.015625, 8.0, 0.5, 0.3, 0.03125, [[0, 0, 0], [0, 0, -1.5], [0, 0, -1.5], [0, 0, 1.5], [0, 0, 0]]], [0.0, -0.038473, -1.442578, 0.0, False, -1]], [[[0.0, -0.02], -0.16, 20.0, 40.0, 0.015625, 8.0, 2.0, 1.0, 0.046875, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0.5], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.046875, True, 5]], [[[-3.19, -0.03], 1.71, 20.0, 0.5, 0.015625, 3.0, 0.5, 1.0, 0.015625, [[0, 8, -1], [0, 1, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [-0.374853, 1.272803, 0.682904, 0.0, False, -1]]], [[[[0.02, 0.02], 1.76, 80.0, 40.0, 0.03125, 8.0, 0.5, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.03125, True, 0]], [[[0.06, -0.1], 0.0, 2.0, 0.5, 0.0625, 8.0, 0.5, 0.3, 0.1875, [[0, 0, 0], [0, 0, -1.5], [0, 0, 0], [0, 0, 0], [0, 0, -1.5], [0, 0, -1.5], [0, 0, 0], [0, 0, 1.5]]], [0.023385, -0.038974, -2.448788, 0.0, False, -1]], [[[1.54, 3.78], -0.99, 20.0, 5.0, 0.03125, 8.0, 0.5, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.03125, True, 4]], [[[0.07, 0.04], 0.0, 2.0, 0.5, 0.0625, 8.0, 0.5, 0.3, 0.1875, [[0, 0, 0], [0, 0, 1.5], [0, 0, 0], [0, 0, 1.5]]], [0.043701, 0.024972, 2.822272, 0.0, False, -1]], [[[-0.04, -0.09], 0.0, 2.0, 0.5, 0.03125, 8.0, 0.5, 1.0, 0.0625, [[0, 0, -1.5], [0, 0, -1.5], [0, 0, 0], [0, 0, -1.5], [0, 0, -1.5]]], [-0.02954, -0.066466, -5.729036, 0.0, False, -1]], [[[-0.02, -0.0], 1.5, 0.5, 5.0, 0.03125, 3.0, 0.5, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 8, 0.5]]], [0.0, 3.0, 0.432432, 0.0, False, 2]], [[[0.04, 0.05], -1.81, 20.0, 40.0, 0.0625, 3.0, 2.0, 1.0, 0.1875, [[5, 0, 0.5], [0, 0, 0], [1, -3, -1], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [1, 1, 0], [0, 8, 0]]], [0.157676, 2.995853, 0.0, 0.0, False, 3]], [[[0.63, 0.72], -1.08, 20.0, 0.5, 0.0625, 3.0, 2.0, 1.0, 0.1875, [[0, 0, 0], [0, 0, 0], [5, 0, 2], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0.5], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.1875, True, 8]]], [[[[-0.0, -0.04], 1.8, 0.5, 40.0, 0.03125, 8.0, 2.0, 0.3, 0.0625, [[0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, -0.038182, 0.158025, 0.03125, False, -1]], [[[0.09, 0.02], 0.0, 0.5, 5.0, 0.03125, 8.0, 0.5, 0.3, 0.0625, [[0, 0, 1.5], [0, 0, -1.5], [0, 0, -1.5], [0, 0, 1.5], [0, 0, 0], [0, 0, 1.5]]], [0.0, 0.0, 1.297297, 0.0, False, 4]], [[[-1.31, 0.47], 0.1, 80.0, 5.0, 0.0625, 8.0, 2.0, 0.3, 0.125, [[0, 0, 0], [-2, 8, -1], [0, 0, 0], [0, 0, 0], [1, 0, 0.5], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.125, True, 5]], [[[0.05, -0.02], 0.0, 2.0, 0.5, 0.015625, 8.0, 0.5, 1.0, 0.046875, [[0, 0, -1.5], [0, 0, 1.5], [0, 0, -1.5], [0, 0, 1.5], [0, 0, 0], [0, 0, 0], [0, 0, -1.5], [0, 0, 1.5]]], [0.0, 0.0, 0.011538, 0.015625, False, 5]], [[[3.31, 5.08], -0.33, 2.0, 40.0, 0.03125, 3.0, 0.5, 0.3, 0.0625, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.949044, 1.456539, -9.9e-05, 0.0, False, -1]], [[[0.08, -0.01], 0.0, 0.5, 5.0, 0.03125, 8.0, 0.5, 1.0, 0.09375, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, -1.5], [0, 0, -1.5], [0, 0, 1.5], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.09375, True, 8]], [[[-0.07, 0.04], 0.0, 2.0, 0.5, 0.03125, 8.0, 0.5, 0.3, 0.09375, [[0, 0, 0], [0, 0, 1.5], [0, 0, 0], [0, 0, 0], [0, 0, -1.5], [0, 0, 0], [0, 0, -1.5], [0, 0, 0]]], [-0.043099, 0.024628, -1.518273, 0.0, False, -1]], [[[4.65, -4.7], -0.73, 20.0, 0.5, 0.0625, 3.0, 2.0, 1.0, 0.1875, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0.5]]], [0.0, 0.0, 0.484848, 0.0625, False, 3]]], [[[[4.92, 4.59], 0.62, 20.0, 0.5, 0.0625, 3.0, 0.5, 1.0, 0.1875, [[0, 0, 0], [0, 8, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [-2, 0, 0.5]]], [-0.888889, 0.0, 0.484848, 0.0, False, 6]], [[[-5.56, 0.39], -1.79, 2.0, 40.0, 0.03125, 3.0, 0.5, 1.0, 0.0625, [[-2, 8, 0.5], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [1, 1, 0.5], [5, -3, 0.5], [0, 0, 0]]], [2.80594, -0.31467, 0.141788, 0.0, False, -1]], [[[-0.02, 0.03], 0.27, 2.0, 40.0, 0.03125, 3.0, 0.5, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.03125, True, 0]], [[[-0.03, 0.05], -1.01, 80.0, 0.5, 0.03125, 8.0, 2.0, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0.5], [0, 0, 0], [0, 0, 0], [5, 0, 2], [0, 0, 0], [0, 0, 0]]], [0.116618, 0.0, 1.909105, 0.0, False, 3]], [[[4.25, 3.24], 1.04, 2.0, 0.5, 0.015625, 3.0, 2.0, 1.0, 0.015625, [[0, 0, 0], [0, 0, 0], [1, 8, -1], [0, 0, 0]]], [0.934883, 2.754778, 0.023569, 0.0, False, -1]], [[[-0.05, 0.02], 0.0, 0.5, 5.0, 0.015625, 8.0, 0.5, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0.5], [0, 0, -0.5], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.03125, True, 3]], [[[5.93, 2.95], -1.5, 2.0, 0.5, 0.03125, 8.0, 0.5, 0.3, 0.09375, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [4.379353, 2.178599, -1.388111, 0.0, False, -1]], [[[-0.04, -0.04], 0.45, 20.0, 40.0, 0.0625, 3.0, 0.5, 0.3, 0.0625, [[0, 1, -1], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.0625, True, 0]]], [[[[-4.0, -0.28], -1.66, 20.0, 0.5, 0.0625, 8.0, 0.5, 1.0, 0.125, [[-2, 8, 2], [0, 0, 0], [-2, 0, 2], [0, 0, 0], [0, 0, 0]]], [-0.279632, 0.133877, 2.11515, 0.0, False, -1]], [[[0.05, -0.01], 0.0, 0.5, 0.5, 0.0625, 8.0, 0.5, 1.0, 0.1875, [[0, 0, 0.5], [0, 0, -0.5], [0, 0, -0.5], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.1875, True, 2]], [[[0.18, -1.7], -1.08, 80.0, 0.5, 0.0625, 3.0, 2.0, 1.0, 0.1875, [[0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.000833, -0.00787, -0.984763, 0.0625, False, -1]], [[[-0.01, 0.03], -0.14, 0.5, 0.5, 0.0625, 3.0, 0.5, 1.0, 0.0625, [[0, 0, 0], [1, 1, -1], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0.5], [0, 0, 0]]], [0.806218, 0.806218, -0.336061, 0.0, False, 0]], [[[-4.85, -4.08], 0.8, 2.0, 0.5, 0.03125, 3.0, 2.0, 0.3, 0.0625, [[0, 0, 0], [0, 0, 0], [5, 0, 2], [0, 0, 0]]], [2.378, -1.522313, 2.690829, 0.0, False, -1]], [[[-0.03, -0.03], 0.71, 80.0, 40.0, 0.0625, 3.0, 0.5, 0.3, 0.1875, [[0, 0, 0], [0, 0, -1], [0, 0, 0], [0, 0, 0], [-2, 0, 0.5]]], [-0.333333, 0.0, 0.142857, 0.0625, False, 2]], [[[-0.02, 0.02], 1.56, 0.5, 40.0, 0.0625, 3.0, 2.0, 0.3, 0.1875, [[1, 0, 0.5], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.1875, True, 3]], [[[-0.08, 0.04], 0.0, 0.5, 0.5, 0.03125, 8.0, 0.5, 1.0, 0.0625, [[0, 0, -3.0], [0, 0, 0], [0, 0, 3.0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.0625, True, 3]]]]
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 fixtureActualExpectedOutcome
case 0[-1.818298, 7.273193, 0.0, 0.0, False, 1][-1.823636, 7.294543, 0.0, 0.0, False, 1]Failed
case 1[0.36358, 2.977887, 1.230769, 0.0, False, 0][0.363645, 2.977879, 1.230769, 0.0, False, 0]Failed
case 2[0.0, 0.0, 0.0, 0.03125, True, 3][0.0, 0.0, 0.0, 0.03125, True, 3]Passed
case 3[-0.000131, 7e-06, 1.780327, 0.0, False, -1][0.007331, -0.000411, 1.780327, 0.0, False, -1]Failed
case 4[0.0, 0.0, 0.806428, 0.0, False, 1][0.0, 0.0, 0.806428, 0.0, False, 1]Passed
case 5[0.0, -0.038462, -1.442578, 0.0, False, -1][0.0, -0.038473, -1.442578, 0.0, False, -1]Failed
case 6[0.0, 0.0, 0.0, 0.046875, True, 5][0.0, 0.0, 0.0, 0.046875, True, 5]Passed
case 7[-0.249045, 0.845626, 0.682904, 0.0, False, -1][-0.374853, 1.272803, 0.682904, 0.0, False, -1]Failed

SHA-256 / e9629a18936ecff78c80e5f3ed697a58785d52359aab02ab802abcab938bba90

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(v, omega, lin_damp, ang_damp, dt, max_speed, sleep_lin, sleep_ang, sleep_time, kicks):
    vx, vy = v
    w = omega
    timer = 0.0
    asleep = False
    slept_at = -1
    for f, (ax, ay, aw) in enumerate(kicks):
        if asleep:
            if ax or ay or aw:
                asleep = False
                timer = 0.0
            else:
                continue
        vx += ax
        vy += ay
        w += aw
        dl = max(0.0, 1.0 - dt * lin_damp)
        vx *= dl
        vy *= dl
        w *= 1.0 / (1.0 + dt * ang_damp)
        sp = math.hypot(vx, vy)
        if sp > max_speed:
            s = max_speed / sp
            vx *= s
            vy *= s
        if math.hypot(vx, vy) < sleep_lin and abs(w) < sleep_ang:
            timer += dt
        else:
            timer = 0.0
        if timer >= sleep_time:
            asleep = True
            slept_at = f
            vx = vy = w = 0.0
    return [round(vx, 6), round(vy, 6), round(w, 6), round(timer, 6), asleep, slept_at]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[[-0.0, 0.0], 0.99, 2.0, 0.5, 0.015625, 8.0, 2.0, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [-2, 8, 0], [0, 0, 0], [0, 0, 0]]], [-1.823636, 7.294543, 0.0, 0.0, False, 1]], [[[-0.01, -0.01], 1.26, 0.5, 40.0, 0.015625, 3.0, 0.5, 1.0, 0.015625, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [1, 0, 0], [0, 0, 0], [0, 0, 0], [0, 8, 2]]], [0.363645, 2.977879, 1.230769, 0.0, False, 0]], [[[0.02, 0.01], 0.0, 0.5, 0.5, 0.015625, 8.0, 0.5, 1.0, 0.03125, [[0, 0, -0.5], [0, 0, 0], [0, 0, 0.5], [0, 0, -0.5], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.03125, True, 3]], [[[2.14, -0.12], 1.88, 80.0, 0.5, 0.015625, 8.0, 0.5, 0.3, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.007331, -0.000411, 1.780327, 0.0, False, -1]], [[[-0.02, 0.07], 0.0, 2.0, 5.0, 0.03125, 8.0, 0.5, 0.3, 0.0625, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0.5], [0, 0, 0.5]]], [0.0, 0.0, 0.806428, 0.0, False, 1]], [[[0.0, -0.04], 0.0, 0.5, 0.5, 0.015625, 8.0, 0.5, 0.3, 0.03125, [[0, 0, 0], [0, 0, -1.5], [0, 0, -1.5], [0, 0, 1.5], [0, 0, 0]]], [0.0, -0.038473, -1.442578, 0.0, False, -1]], [[[0.0, -0.02], -0.16, 20.0, 40.0, 0.015625, 8.0, 2.0, 1.0, 0.046875, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0.5], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.046875, True, 5]], [[[-3.19, -0.03], 1.71, 20.0, 0.5, 0.015625, 3.0, 0.5, 1.0, 0.015625, [[0, 8, -1], [0, 1, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [-0.374853, 1.272803, 0.682904, 0.0, False, -1]]], [[[[0.02, 0.02], 1.76, 80.0, 40.0, 0.03125, 8.0, 0.5, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.03125, True, 0]], [[[0.06, -0.1], 0.0, 2.0, 0.5, 0.0625, 8.0, 0.5, 0.3, 0.1875, [[0, 0, 0], [0, 0, -1.5], [0, 0, 0], [0, 0, 0], [0, 0, -1.5], [0, 0, -1.5], [0, 0, 0], [0, 0, 1.5]]], [0.023385, -0.038974, -2.448788, 0.0, False, -1]], [[[1.54, 3.78], -0.99, 20.0, 5.0, 0.03125, 8.0, 0.5, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.03125, True, 4]], [[[0.07, 0.04], 0.0, 2.0, 0.5, 0.0625, 8.0, 0.5, 0.3, 0.1875, [[0, 0, 0], [0, 0, 1.5], [0, 0, 0], [0, 0, 1.5]]], [0.043701, 0.024972, 2.822272, 0.0, False, -1]], [[[-0.04, -0.09], 0.0, 2.0, 0.5, 0.03125, 8.0, 0.5, 1.0, 0.0625, [[0, 0, -1.5], [0, 0, -1.5], [0, 0, 0], [0, 0, -1.5], [0, 0, -1.5]]], [-0.02954, -0.066466, -5.729036, 0.0, False, -1]], [[[-0.02, -0.0], 1.5, 0.5, 5.0, 0.03125, 3.0, 0.5, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 8, 0.5]]], [0.0, 3.0, 0.432432, 0.0, False, 2]], [[[0.04, 0.05], -1.81, 20.0, 40.0, 0.0625, 3.0, 2.0, 1.0, 0.1875, [[5, 0, 0.5], [0, 0, 0], [1, -3, -1], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [1, 1, 0], [0, 8, 0]]], [0.157676, 2.995853, 0.0, 0.0, False, 3]], [[[0.63, 0.72], -1.08, 20.0, 0.5, 0.0625, 3.0, 2.0, 1.0, 0.1875, [[0, 0, 0], [0, 0, 0], [5, 0, 2], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0.5], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.1875, True, 8]]], [[[[-0.0, -0.04], 1.8, 0.5, 40.0, 0.03125, 8.0, 2.0, 0.3, 0.0625, [[0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, -0.038182, 0.158025, 0.03125, False, -1]], [[[0.09, 0.02], 0.0, 0.5, 5.0, 0.03125, 8.0, 0.5, 0.3, 0.0625, [[0, 0, 1.5], [0, 0, -1.5], [0, 0, -1.5], [0, 0, 1.5], [0, 0, 0], [0, 0, 1.5]]], [0.0, 0.0, 1.297297, 0.0, False, 4]], [[[-1.31, 0.47], 0.1, 80.0, 5.0, 0.0625, 8.0, 2.0, 0.3, 0.125, [[0, 0, 0], [-2, 8, -1], [0, 0, 0], [0, 0, 0], [1, 0, 0.5], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.125, True, 5]], [[[0.05, -0.02], 0.0, 2.0, 0.5, 0.015625, 8.0, 0.5, 1.0, 0.046875, [[0, 0, -1.5], [0, 0, 1.5], [0, 0, -1.5], [0, 0, 1.5], [0, 0, 0], [0, 0, 0], [0, 0, -1.5], [0, 0, 1.5]]], [0.0, 0.0, 0.011538, 0.015625, False, 5]], [[[3.31, 5.08], -0.33, 2.0, 40.0, 0.03125, 3.0, 0.5, 0.3, 0.0625, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.949044, 1.456539, -9.9e-05, 0.0, False, -1]], [[[0.08, -0.01], 0.0, 0.5, 5.0, 0.03125, 8.0, 0.5, 1.0, 0.09375, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, -1.5], [0, 0, -1.5], [0, 0, 1.5], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.09375, True, 8]], [[[-0.07, 0.04], 0.0, 2.0, 0.5, 0.03125, 8.0, 0.5, 0.3, 0.09375, [[0, 0, 0], [0, 0, 1.5], [0, 0, 0], [0, 0, 0], [0, 0, -1.5], [0, 0, 0], [0, 0, -1.5], [0, 0, 0]]], [-0.043099, 0.024628, -1.518273, 0.0, False, -1]], [[[4.65, -4.7], -0.73, 20.0, 0.5, 0.0625, 3.0, 2.0, 1.0, 0.1875, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0.5]]], [0.0, 0.0, 0.484848, 0.0625, False, 3]]], [[[[4.92, 4.59], 0.62, 20.0, 0.5, 0.0625, 3.0, 0.5, 1.0, 0.1875, [[0, 0, 0], [0, 8, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [-2, 0, 0.5]]], [-0.888889, 0.0, 0.484848, 0.0, False, 6]], [[[-5.56, 0.39], -1.79, 2.0, 40.0, 0.03125, 3.0, 0.5, 1.0, 0.0625, [[-2, 8, 0.5], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [1, 1, 0.5], [5, -3, 0.5], [0, 0, 0]]], [2.80594, -0.31467, 0.141788, 0.0, False, -1]], [[[-0.02, 0.03], 0.27, 2.0, 40.0, 0.03125, 3.0, 0.5, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.03125, True, 0]], [[[-0.03, 0.05], -1.01, 80.0, 0.5, 0.03125, 8.0, 2.0, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0.5], [0, 0, 0], [0, 0, 0], [5, 0, 2], [0, 0, 0], [0, 0, 0]]], [0.116618, 0.0, 1.909105, 0.0, False, 3]], [[[4.25, 3.24], 1.04, 2.0, 0.5, 0.015625, 3.0, 2.0, 1.0, 0.015625, [[0, 0, 0], [0, 0, 0], [1, 8, -1], [0, 0, 0]]], [0.934883, 2.754778, 0.023569, 0.0, False, -1]], [[[-0.05, 0.02], 0.0, 0.5, 5.0, 0.015625, 8.0, 0.5, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0.5], [0, 0, -0.5], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.03125, True, 3]], [[[5.93, 2.95], -1.5, 2.0, 0.5, 0.03125, 8.0, 0.5, 0.3, 0.09375, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [4.379353, 2.178599, -1.388111, 0.0, False, -1]], [[[-0.04, -0.04], 0.45, 20.0, 40.0, 0.0625, 3.0, 0.5, 0.3, 0.0625, [[0, 1, -1], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.0625, True, 0]]], [[[[-4.0, -0.28], -1.66, 20.0, 0.5, 0.0625, 8.0, 0.5, 1.0, 0.125, [[-2, 8, 2], [0, 0, 0], [-2, 0, 2], [0, 0, 0], [0, 0, 0]]], [-0.279632, 0.133877, 2.11515, 0.0, False, -1]], [[[0.05, -0.01], 0.0, 0.5, 0.5, 0.0625, 8.0, 0.5, 1.0, 0.1875, [[0, 0, 0.5], [0, 0, -0.5], [0, 0, -0.5], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.1875, True, 2]], [[[0.18, -1.7], -1.08, 80.0, 0.5, 0.0625, 3.0, 2.0, 1.0, 0.1875, [[0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.000833, -0.00787, -0.984763, 0.0625, False, -1]], [[[-0.01, 0.03], -0.14, 0.5, 0.5, 0.0625, 3.0, 0.5, 1.0, 0.0625, [[0, 0, 0], [1, 1, -1], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0.5], [0, 0, 0]]], [0.806218, 0.806218, -0.336061, 0.0, False, 0]], [[[-4.85, -4.08], 0.8, 2.0, 0.5, 0.03125, 3.0, 2.0, 0.3, 0.0625, [[0, 0, 0], [0, 0, 0], [5, 0, 2], [0, 0, 0]]], [2.378, -1.522313, 2.690829, 0.0, False, -1]], [[[-0.03, -0.03], 0.71, 80.0, 40.0, 0.0625, 3.0, 0.5, 0.3, 0.1875, [[0, 0, 0], [0, 0, -1], [0, 0, 0], [0, 0, 0], [-2, 0, 0.5]]], [-0.333333, 0.0, 0.142857, 0.0625, False, 2]], [[[-0.02, 0.02], 1.56, 0.5, 40.0, 0.0625, 3.0, 2.0, 0.3, 0.1875, [[1, 0, 0.5], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.1875, True, 3]], [[[-0.08, 0.04], 0.0, 0.5, 0.5, 0.03125, 8.0, 0.5, 1.0, 0.0625, [[0, 0, -3.0], [0, 0, 0], [0, 0, 3.0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.0625, True, 3]]]]
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 fixtureActualExpectedOutcome
case 0[-1.818298, 7.273193, 0.0, 0.0, False, 1][-1.823636, 7.294543, 0.0, 0.0, False, 1]Failed
case 1[0.36358, 2.977887, 1.230769, 0.0, False, 0][0.363645, 2.977879, 1.230769, 0.0, False, 0]Failed
case 2[0.0, 0.0, 0.0, 0.03125, True, 3][0.0, 0.0, 0.0, 0.03125, True, 3]Passed
case 3[0.0, 0.0, 1.780327, 0.0, False, -1][0.007331, -0.000411, 1.780327, 0.0, False, -1]Failed
case 4[0.0, 0.0, 0.806428, 0.0, False, 1][0.0, 0.0, 0.806428, 0.0, False, 1]Passed
case 5[0.0, -0.038462, -1.442578, 0.0, False, -1][0.0, -0.038473, -1.442578, 0.0, False, -1]Failed
case 6[0.0, 0.0, 0.0, 0.046875, True, 5][0.0, 0.0, 0.0, 0.046875, True, 5]Passed
case 7[-0.249045, 0.845626, 0.682904, 0.0, False, -1][-0.374853, 1.272803, 0.682904, 0.0, False, -1]Failed

SHA-256 / 23080f7401f4d8ec33de02ddac8dc97b424ef0902ab4f9e79a21870c27331072

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(v, omega, lin_damp, ang_damp, dt, max_speed, sleep_lin, sleep_ang, sleep_time, kicks):
    vx, vy = v
    w = omega
    timer = 0.0
    asleep = False
    slept_at = -1
    for f, (ax, ay, aw) in enumerate(kicks):
        if asleep:
            if ax or ay or aw:
                asleep = False
                timer = 0.0
            else:
                continue
        vx += ax
        vy += ay
        w += aw
        dl = 1.0 / (1.0 + dt * lin_damp)
        vx *= dl
        vy *= dl
        w *= 1.0 / (1.0 + dt * ang_damp)
        sp = math.hypot(vx, vy)
        if sp > max_speed:
            s = max_speed / sp
            vx *= s
            vy *= s
        if math.hypot(vx, vy) < sleep_lin and abs(w) < sleep_ang:
            timer += dt
        else:
            timer = 0.0
        if timer >= sleep_time:
            asleep = True
            slept_at = f
            vx = vy = w = 0.0
    return [round(vx, 6), round(vy, 6), round(w, 6), round(timer, 6), asleep, slept_at]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[[-0.0, 0.0], 0.99, 2.0, 0.5, 0.015625, 8.0, 2.0, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [-2, 8, 0], [0, 0, 0], [0, 0, 0]]], [-1.823636, 7.294543, 0.0, 0.0, False, 1]], [[[-0.01, -0.01], 1.26, 0.5, 40.0, 0.015625, 3.0, 0.5, 1.0, 0.015625, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [1, 0, 0], [0, 0, 0], [0, 0, 0], [0, 8, 2]]], [0.363645, 2.977879, 1.230769, 0.0, False, 0]], [[[0.02, 0.01], 0.0, 0.5, 0.5, 0.015625, 8.0, 0.5, 1.0, 0.03125, [[0, 0, -0.5], [0, 0, 0], [0, 0, 0.5], [0, 0, -0.5], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.03125, True, 3]], [[[2.14, -0.12], 1.88, 80.0, 0.5, 0.015625, 8.0, 0.5, 0.3, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.007331, -0.000411, 1.780327, 0.0, False, -1]], [[[-0.02, 0.07], 0.0, 2.0, 5.0, 0.03125, 8.0, 0.5, 0.3, 0.0625, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0.5], [0, 0, 0.5]]], [0.0, 0.0, 0.806428, 0.0, False, 1]], [[[0.0, -0.04], 0.0, 0.5, 0.5, 0.015625, 8.0, 0.5, 0.3, 0.03125, [[0, 0, 0], [0, 0, -1.5], [0, 0, -1.5], [0, 0, 1.5], [0, 0, 0]]], [0.0, -0.038473, -1.442578, 0.0, False, -1]], [[[0.0, -0.02], -0.16, 20.0, 40.0, 0.015625, 8.0, 2.0, 1.0, 0.046875, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0.5], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.046875, True, 5]], [[[-3.19, -0.03], 1.71, 20.0, 0.5, 0.015625, 3.0, 0.5, 1.0, 0.015625, [[0, 8, -1], [0, 1, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [-0.374853, 1.272803, 0.682904, 0.0, False, -1]]], [[[[0.02, 0.02], 1.76, 80.0, 40.0, 0.03125, 8.0, 0.5, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.03125, True, 0]], [[[0.06, -0.1], 0.0, 2.0, 0.5, 0.0625, 8.0, 0.5, 0.3, 0.1875, [[0, 0, 0], [0, 0, -1.5], [0, 0, 0], [0, 0, 0], [0, 0, -1.5], [0, 0, -1.5], [0, 0, 0], [0, 0, 1.5]]], [0.023385, -0.038974, -2.448788, 0.0, False, -1]], [[[1.54, 3.78], -0.99, 20.0, 5.0, 0.03125, 8.0, 0.5, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.03125, True, 4]], [[[0.07, 0.04], 0.0, 2.0, 0.5, 0.0625, 8.0, 0.5, 0.3, 0.1875, [[0, 0, 0], [0, 0, 1.5], [0, 0, 0], [0, 0, 1.5]]], [0.043701, 0.024972, 2.822272, 0.0, False, -1]], [[[-0.04, -0.09], 0.0, 2.0, 0.5, 0.03125, 8.0, 0.5, 1.0, 0.0625, [[0, 0, -1.5], [0, 0, -1.5], [0, 0, 0], [0, 0, -1.5], [0, 0, -1.5]]], [-0.02954, -0.066466, -5.729036, 0.0, False, -1]], [[[-0.02, -0.0], 1.5, 0.5, 5.0, 0.03125, 3.0, 0.5, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 8, 0.5]]], [0.0, 3.0, 0.432432, 0.0, False, 2]], [[[0.04, 0.05], -1.81, 20.0, 40.0, 0.0625, 3.0, 2.0, 1.0, 0.1875, [[5, 0, 0.5], [0, 0, 0], [1, -3, -1], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [1, 1, 0], [0, 8, 0]]], [0.157676, 2.995853, 0.0, 0.0, False, 3]], [[[0.63, 0.72], -1.08, 20.0, 0.5, 0.0625, 3.0, 2.0, 1.0, 0.1875, [[0, 0, 0], [0, 0, 0], [5, 0, 2], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0.5], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.1875, True, 8]]], [[[[-0.0, -0.04], 1.8, 0.5, 40.0, 0.03125, 8.0, 2.0, 0.3, 0.0625, [[0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, -0.038182, 0.158025, 0.03125, False, -1]], [[[0.09, 0.02], 0.0, 0.5, 5.0, 0.03125, 8.0, 0.5, 0.3, 0.0625, [[0, 0, 1.5], [0, 0, -1.5], [0, 0, -1.5], [0, 0, 1.5], [0, 0, 0], [0, 0, 1.5]]], [0.0, 0.0, 1.297297, 0.0, False, 4]], [[[-1.31, 0.47], 0.1, 80.0, 5.0, 0.0625, 8.0, 2.0, 0.3, 0.125, [[0, 0, 0], [-2, 8, -1], [0, 0, 0], [0, 0, 0], [1, 0, 0.5], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.125, True, 5]], [[[0.05, -0.02], 0.0, 2.0, 0.5, 0.015625, 8.0, 0.5, 1.0, 0.046875, [[0, 0, -1.5], [0, 0, 1.5], [0, 0, -1.5], [0, 0, 1.5], [0, 0, 0], [0, 0, 0], [0, 0, -1.5], [0, 0, 1.5]]], [0.0, 0.0, 0.011538, 0.015625, False, 5]], [[[3.31, 5.08], -0.33, 2.0, 40.0, 0.03125, 3.0, 0.5, 0.3, 0.0625, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.949044, 1.456539, -9.9e-05, 0.0, False, -1]], [[[0.08, -0.01], 0.0, 0.5, 5.0, 0.03125, 8.0, 0.5, 1.0, 0.09375, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, -1.5], [0, 0, -1.5], [0, 0, 1.5], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.09375, True, 8]], [[[-0.07, 0.04], 0.0, 2.0, 0.5, 0.03125, 8.0, 0.5, 0.3, 0.09375, [[0, 0, 0], [0, 0, 1.5], [0, 0, 0], [0, 0, 0], [0, 0, -1.5], [0, 0, 0], [0, 0, -1.5], [0, 0, 0]]], [-0.043099, 0.024628, -1.518273, 0.0, False, -1]], [[[4.65, -4.7], -0.73, 20.0, 0.5, 0.0625, 3.0, 2.0, 1.0, 0.1875, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0.5]]], [0.0, 0.0, 0.484848, 0.0625, False, 3]]], [[[[4.92, 4.59], 0.62, 20.0, 0.5, 0.0625, 3.0, 0.5, 1.0, 0.1875, [[0, 0, 0], [0, 8, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [-2, 0, 0.5]]], [-0.888889, 0.0, 0.484848, 0.0, False, 6]], [[[-5.56, 0.39], -1.79, 2.0, 40.0, 0.03125, 3.0, 0.5, 1.0, 0.0625, [[-2, 8, 0.5], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [1, 1, 0.5], [5, -3, 0.5], [0, 0, 0]]], [2.80594, -0.31467, 0.141788, 0.0, False, -1]], [[[-0.02, 0.03], 0.27, 2.0, 40.0, 0.03125, 3.0, 0.5, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.03125, True, 0]], [[[-0.03, 0.05], -1.01, 80.0, 0.5, 0.03125, 8.0, 2.0, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0.5], [0, 0, 0], [0, 0, 0], [5, 0, 2], [0, 0, 0], [0, 0, 0]]], [0.116618, 0.0, 1.909105, 0.0, False, 3]], [[[4.25, 3.24], 1.04, 2.0, 0.5, 0.015625, 3.0, 2.0, 1.0, 0.015625, [[0, 0, 0], [0, 0, 0], [1, 8, -1], [0, 0, 0]]], [0.934883, 2.754778, 0.023569, 0.0, False, -1]], [[[-0.05, 0.02], 0.0, 0.5, 5.0, 0.015625, 8.0, 0.5, 1.0, 0.03125, [[0, 0, 0], [0, 0, 0], [0, 0, 0.5], [0, 0, -0.5], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.03125, True, 3]], [[[5.93, 2.95], -1.5, 2.0, 0.5, 0.03125, 8.0, 0.5, 0.3, 0.09375, [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [4.379353, 2.178599, -1.388111, 0.0, False, -1]], [[[-0.04, -0.04], 0.45, 20.0, 40.0, 0.0625, 3.0, 0.5, 0.3, 0.0625, [[0, 1, -1], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.0625, True, 0]]], [[[[-4.0, -0.28], -1.66, 20.0, 0.5, 0.0625, 8.0, 0.5, 1.0, 0.125, [[-2, 8, 2], [0, 0, 0], [-2, 0, 2], [0, 0, 0], [0, 0, 0]]], [-0.279632, 0.133877, 2.11515, 0.0, False, -1]], [[[0.05, -0.01], 0.0, 0.5, 0.5, 0.0625, 8.0, 0.5, 1.0, 0.1875, [[0, 0, 0.5], [0, 0, -0.5], [0, 0, -0.5], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.1875, True, 2]], [[[0.18, -1.7], -1.08, 80.0, 0.5, 0.0625, 3.0, 2.0, 1.0, 0.1875, [[0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.000833, -0.00787, -0.984763, 0.0625, False, -1]], [[[-0.01, 0.03], -0.14, 0.5, 0.5, 0.0625, 3.0, 0.5, 1.0, 0.0625, [[0, 0, 0], [1, 1, -1], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0.5], [0, 0, 0]]], [0.806218, 0.806218, -0.336061, 0.0, False, 0]], [[[-4.85, -4.08], 0.8, 2.0, 0.5, 0.03125, 3.0, 2.0, 0.3, 0.0625, [[0, 0, 0], [0, 0, 0], [5, 0, 2], [0, 0, 0]]], [2.378, -1.522313, 2.690829, 0.0, False, -1]], [[[-0.03, -0.03], 0.71, 80.0, 40.0, 0.0625, 3.0, 0.5, 0.3, 0.1875, [[0, 0, 0], [0, 0, -1], [0, 0, 0], [0, 0, 0], [-2, 0, 0.5]]], [-0.333333, 0.0, 0.142857, 0.0625, False, 2]], [[[-0.02, 0.02], 1.56, 0.5, 40.0, 0.0625, 3.0, 2.0, 0.3, 0.1875, [[1, 0, 0.5], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.1875, True, 3]], [[[-0.08, 0.04], 0.0, 0.5, 0.5, 0.03125, 8.0, 0.5, 1.0, 0.0625, [[0, 0, -3.0], [0, 0, 0], [0, 0, 3.0], [0, 0, 0]]], [0.0, 0.0, 0.0, 0.0625, True, 3]]]]
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 fixtureActualExpectedOutcome
case 0[-1.823636, 7.294543, 0.0, 0.0, False, 1][-1.823636, 7.294543, 0.0, 0.0, False, 1]Passed
case 1[0.363645, 2.977879, 1.230769, 0.0, False, 0][0.363645, 2.977879, 1.230769, 0.0, False, 0]Passed
case 2[0.0, 0.0, 0.0, 0.03125, True, 3][0.0, 0.0, 0.0, 0.03125, True, 3]Passed
case 3[0.007331, -0.000411, 1.780327, 0.0, False, -1][0.007331, -0.000411, 1.780327, 0.0, False, -1]Passed
case 4[0.0, 0.0, 0.806428, 0.0, False, 1][0.0, 0.0, 0.806428, 0.0, False, 1]Passed
case 5[0.0, -0.038473, -1.442578, 0.0, False, -1][0.0, -0.038473, -1.442578, 0.0, False, -1]Passed
case 6[0.0, 0.0, 0.0, 0.046875, True, 5][0.0, 0.0, 0.0, 0.046875, True, 5]Passed
case 7[-0.374853, 1.272803, 0.682904, 0.0, False, -1][-0.374853, 1.272803, 0.682904, 0.0, False, -1]Passed

SHA-256 / 5b9fb85854962b27000bbdeb289db03f397e0bf80e84944663236ded1e04577d

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

Case digest / 0b5eea8fff5b499be7c3c980136fad5232832908e46eaf172de678c730ea8167