FAILURE MAP
← Case archive

FA-86861 / Physics integrator stability / Open access

Every substep advances by the whole frame length · case 01

Frames split into several substeps advance simulated time by a multiple of dt.

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

ROOT CAUSE

The substep length h is set to dt instead of dt/n_sub.

VERIFIED REPAIR

Divide the frame length evenly across substeps.

Unsuccessful approach: Dividing by n_sub+1 leaves the frame short of its duration.

Case contract

solve(x0, v0, k, m, c, dt, steps): damped spring a=(-k*x-c*v)/m integrated with semi-implicit Euler (velocity first, then position with the new velocity). Each frame of length dt is split into ceil(dt/0.05) equal substeps (at least one). Return [x, v] rounded to 6 decimals after steps frames.

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(x0, v0, k, m, c, dt, steps):
    n_sub = max(1, math.ceil(dt / 0.05 - 1e-12))
    h = dt
    x, v = x0, v0
    for _ in range(steps):
        for _ in range(n_sub):
            a = (-k * x - c * v) / m
            v = v + a * h
            x = x + v * h
    return [round(x, 6), round(v, 6)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[1.0, 0.0, 10.0, 1.0, 0.0, 0.05, 0], [1.0, 0.0]], [[-1.377, 0.559, 2.87, 2.898, 1.015, 0.2, 0], [-1.377, 0.559]], [[-1.603, 0.842, 17.725, 1.501, 1.753, 0.13, 8], [0.763682, -1.657161]], [[-1.013, 1.855, 30.403, 2.18, 1.879, 0.2, 4], [0.749953, -0.924042]], [[-1.958, -0.179, 8.425, 1.714, 0.601, 0.02, 4], [-1.933886, 0.586176]], [[-1.207, -0.911, 29.131, 2.012, 1.076, 0.13, 7], [0.947903, -0.524986]], [[0.74, 0.59, 14.503, 1.723, 1.698, 0.02, 7], [0.748209, -0.324535]], [[0.428, -0.176, 18.564, 2.203, 1.454, 0.07, 2], [0.36285, -0.625106]]], [[[-1.649, 0.086, 31.392, 1.332, 1.338, 0.01, 4], [-1.607327, 1.603607]], [[-0.452, 1.476, 16.398, 1.596, 0.594, 0.02, 3], [-0.354179, 1.70039]], [[1.977, -1.825, 23.244, 1.921, 0.273, 0.2, 11], [-0.250219, -6.198924]], [[-1.526, 0.873, 6.362, 1.828, 1.137, 0.13, 0], [-1.526, 0.873]], [[1.257, -0.388, 13.634, 2.716, 1.36, 0.1, 12], [-0.866531, -0.655162]], [[-1.424, 1.186, 13.033, 1.768, 1.477, 0.01, 9], [-1.276677, 1.974655]], [[0.797, 1.866, 22.936, 2.437, 1.974, 0.07, 10], [0.09425, -2.420966]], [[1.0, 0.0, 10.0, 1.0, 0.0, 0.05, 0], [1.0, 0.0]]], [[[0.634, -1.094, 26.057, 2.654, 0.419, 0.1, 3], [0.061963, -2.252004]], [[1.0, 0.0, 10.0, 1.0, 0.0, 0.05, 0], [1.0, 0.0]], [[1.379, 0.616, 8.923, 2.136, 0.586, 0.2, 6], [-0.73245, -1.93096]], [[-1.933, -0.041, 34.51, 1.593, 0.382, 0.04, 7], [-0.371615, 8.446595]], [[1.917, -0.356, 37.204, 0.914, 1.124, 0.05, 1], [1.705218, -4.235646]], [[0.784, -0.426, 6.875, 0.731, 0.044, 0.1, 14], [-0.132405, 2.308875]], [[-1.712, -1.9, 9.139, 0.693, 0.61, 0.05, 13], [0.624756, 4.351887]], [[0.116, -1.998, 11.275, 2.342, 1.481, 0.1, 12], [-0.366142, 1.157058]]], [[[1.974, -1.489, 34.073, 1.218, 1.372, 0.05, 10], [-1.429284, -2.634338]], [[-0.35, 0.424, 29.342, 2.686, 0.717, 0.1, 17], [-0.290817, -0.295428]], [[1.0, 0.0, 10.0, 1.0, 0.0, 0.05, 0], [1.0, 0.0]], [[1.909, 0.002, 19.499, 0.727, 0.055, 0.07, 1], [1.723198, -3.518566]], [[-0.232, -0.896, 22.107, 2.288, 0.298, 0.05, 13], [-0.138779, 0.957068]], [[0.365, -1.083, 14.951, 2.014, 1.412, 0.1, 6], [-0.316376, -0.70557]], [[1.14, -1.811, 37.1, 2.271, 0.543, 0.1, 3], [-0.098331, -4.928458]], [[-1.139, -1.668, 38.055, 1.696, 0.596, 0.04, 15], [0.910047, 2.799705]]], [[[0.494, 0.825, 29.084, 1.543, 0.219, 0.13, 11], [0.437707, 0.851286]], [[1.0, 0.0, 10.0, 1.0, 0.0, 0.05, 0], [1.0, 0.0]], [[1.873, -0.51, 29.384, 1.99, 0.411, 0.2, 16], [1.352031, 0.801221]], [[-1.86, -0.316, 22.084, 0.67, 1.741, 0.04, 12], [0.841343, 2.344066]], [[1.804, -0.317, 3.677, 1.295, 1.017, 0.07, 2], [1.702225, -0.959409]], [[-0.078, -0.863, 3.994, 2.622, 1.462, 0.1, 0], [-0.078, -0.863]], [[0.36, -1.513, 9.018, 1.848, 0.394, 0.05, 8], [-0.288846, -1.518381]], [[0.336, -1.099, 12.993, 2.616, 1.417, 0.05, 19], [-0.440588, -0.012857]]]]
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.0, 0.0][1.0, 0.0]Passed
case 1[-1.377, 0.559][-1.377, 0.559]Passed
case 2[-0.065958, -0.821698][0.763682, -1.657161]Failed
case 3[-0.183218, 0.621084][0.749953, -0.924042]Failed
case 4[-1.933886, 0.586176][-1.933886, 0.586176]Passed
case 5[0.188727, -1.934185][0.947903, -0.524986]Failed
case 6[0.748209, -0.324535][0.748209, -0.324535]Passed
case 7[0.230263, -0.95298][0.36285, -0.625106]Failed

SHA-256 / 39bb42b3a14a53abc51b0705e6b631680048fc828e0db06a1f172b55c22f270b

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x0, v0, k, m, c, dt, steps):
    n_sub = max(1, math.ceil(dt / 0.05 - 1e-12))
    h = dt / (n_sub + 1)
    x, v = x0, v0
    for _ in range(steps):
        for _ in range(n_sub):
            a = (-k * x - c * v) / m
            v = v + a * h
            x = x + v * h
    return [round(x, 6), round(v, 6)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[1.0, 0.0, 10.0, 1.0, 0.0, 0.05, 0], [1.0, 0.0]], [[-1.377, 0.559, 2.87, 2.898, 1.015, 0.2, 0], [-1.377, 0.559]], [[-1.603, 0.842, 17.725, 1.501, 1.753, 0.13, 8], [0.763682, -1.657161]], [[-1.013, 1.855, 30.403, 2.18, 1.879, 0.2, 4], [0.749953, -0.924042]], [[-1.958, -0.179, 8.425, 1.714, 0.601, 0.02, 4], [-1.933886, 0.586176]], [[-1.207, -0.911, 29.131, 2.012, 1.076, 0.13, 7], [0.947903, -0.524986]], [[0.74, 0.59, 14.503, 1.723, 1.698, 0.02, 7], [0.748209, -0.324535]], [[0.428, -0.176, 18.564, 2.203, 1.454, 0.07, 2], [0.36285, -0.625106]]], [[[-1.649, 0.086, 31.392, 1.332, 1.338, 0.01, 4], [-1.607327, 1.603607]], [[-0.452, 1.476, 16.398, 1.596, 0.594, 0.02, 3], [-0.354179, 1.70039]], [[1.977, -1.825, 23.244, 1.921, 0.273, 0.2, 11], [-0.250219, -6.198924]], [[-1.526, 0.873, 6.362, 1.828, 1.137, 0.13, 0], [-1.526, 0.873]], [[1.257, -0.388, 13.634, 2.716, 1.36, 0.1, 12], [-0.866531, -0.655162]], [[-1.424, 1.186, 13.033, 1.768, 1.477, 0.01, 9], [-1.276677, 1.974655]], [[0.797, 1.866, 22.936, 2.437, 1.974, 0.07, 10], [0.09425, -2.420966]], [[1.0, 0.0, 10.0, 1.0, 0.0, 0.05, 0], [1.0, 0.0]]], [[[0.634, -1.094, 26.057, 2.654, 0.419, 0.1, 3], [0.061963, -2.252004]], [[1.0, 0.0, 10.0, 1.0, 0.0, 0.05, 0], [1.0, 0.0]], [[1.379, 0.616, 8.923, 2.136, 0.586, 0.2, 6], [-0.73245, -1.93096]], [[-1.933, -0.041, 34.51, 1.593, 0.382, 0.04, 7], [-0.371615, 8.446595]], [[1.917, -0.356, 37.204, 0.914, 1.124, 0.05, 1], [1.705218, -4.235646]], [[0.784, -0.426, 6.875, 0.731, 0.044, 0.1, 14], [-0.132405, 2.308875]], [[-1.712, -1.9, 9.139, 0.693, 0.61, 0.05, 13], [0.624756, 4.351887]], [[0.116, -1.998, 11.275, 2.342, 1.481, 0.1, 12], [-0.366142, 1.157058]]], [[[1.974, -1.489, 34.073, 1.218, 1.372, 0.05, 10], [-1.429284, -2.634338]], [[-0.35, 0.424, 29.342, 2.686, 0.717, 0.1, 17], [-0.290817, -0.295428]], [[1.0, 0.0, 10.0, 1.0, 0.0, 0.05, 0], [1.0, 0.0]], [[1.909, 0.002, 19.499, 0.727, 0.055, 0.07, 1], [1.723198, -3.518566]], [[-0.232, -0.896, 22.107, 2.288, 0.298, 0.05, 13], [-0.138779, 0.957068]], [[0.365, -1.083, 14.951, 2.014, 1.412, 0.1, 6], [-0.316376, -0.70557]], [[1.14, -1.811, 37.1, 2.271, 0.543, 0.1, 3], [-0.098331, -4.928458]], [[-1.139, -1.668, 38.055, 1.696, 0.596, 0.04, 15], [0.910047, 2.799705]]], [[[0.494, 0.825, 29.084, 1.543, 0.219, 0.13, 11], [0.437707, 0.851286]], [[1.0, 0.0, 10.0, 1.0, 0.0, 0.05, 0], [1.0, 0.0]], [[1.873, -0.51, 29.384, 1.99, 0.411, 0.2, 16], [1.352031, 0.801221]], [[-1.86, -0.316, 22.084, 0.67, 1.741, 0.04, 12], [0.841343, 2.344066]], [[1.804, -0.317, 3.677, 1.295, 1.017, 0.07, 2], [1.702225, -0.959409]], [[-0.078, -0.863, 3.994, 2.622, 1.462, 0.1, 0], [-0.078, -0.863]], [[0.36, -1.513, 9.018, 1.848, 0.394, 0.05, 8], [-0.288846, -1.518381]], [[0.336, -1.099, 12.993, 2.616, 1.417, 0.05, 19], [-0.440588, -0.012857]]]]
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.0, 0.0][1.0, 0.0]Passed
case 1[-1.377, 0.559][-1.377, 0.559]Passed
case 2[0.912076, 1.122804][0.763682, -1.657161]Failed
case 3[0.791137, 0.902664][0.749953, -0.924042]Failed
case 4[-1.955505, 0.206504][-1.933886, 0.586176]Failed
case 5[0.756622, 2.629225][0.947903, -0.524986]Failed
case 6[0.762399, 0.120043][0.748209, -0.324535]Failed
case 7[0.393175, -0.485882][0.36285, -0.625106]Failed

SHA-256 / a5b86410ef018a4cc9205e32ff9a20f8c4620c9767105db44b9d153a85af0512

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x0, v0, k, m, c, dt, steps):
    n_sub = max(1, math.ceil(dt / 0.05 - 1e-12))
    h = dt / n_sub
    x, v = x0, v0
    for _ in range(steps):
        for _ in range(n_sub):
            a = (-k * x - c * v) / m
            v = v + a * h
            x = x + v * h
    return [round(x, 6), round(v, 6)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[1.0, 0.0, 10.0, 1.0, 0.0, 0.05, 0], [1.0, 0.0]], [[-1.377, 0.559, 2.87, 2.898, 1.015, 0.2, 0], [-1.377, 0.559]], [[-1.603, 0.842, 17.725, 1.501, 1.753, 0.13, 8], [0.763682, -1.657161]], [[-1.013, 1.855, 30.403, 2.18, 1.879, 0.2, 4], [0.749953, -0.924042]], [[-1.958, -0.179, 8.425, 1.714, 0.601, 0.02, 4], [-1.933886, 0.586176]], [[-1.207, -0.911, 29.131, 2.012, 1.076, 0.13, 7], [0.947903, -0.524986]], [[0.74, 0.59, 14.503, 1.723, 1.698, 0.02, 7], [0.748209, -0.324535]], [[0.428, -0.176, 18.564, 2.203, 1.454, 0.07, 2], [0.36285, -0.625106]]], [[[-1.649, 0.086, 31.392, 1.332, 1.338, 0.01, 4], [-1.607327, 1.603607]], [[-0.452, 1.476, 16.398, 1.596, 0.594, 0.02, 3], [-0.354179, 1.70039]], [[1.977, -1.825, 23.244, 1.921, 0.273, 0.2, 11], [-0.250219, -6.198924]], [[-1.526, 0.873, 6.362, 1.828, 1.137, 0.13, 0], [-1.526, 0.873]], [[1.257, -0.388, 13.634, 2.716, 1.36, 0.1, 12], [-0.866531, -0.655162]], [[-1.424, 1.186, 13.033, 1.768, 1.477, 0.01, 9], [-1.276677, 1.974655]], [[0.797, 1.866, 22.936, 2.437, 1.974, 0.07, 10], [0.09425, -2.420966]], [[1.0, 0.0, 10.0, 1.0, 0.0, 0.05, 0], [1.0, 0.0]]], [[[0.634, -1.094, 26.057, 2.654, 0.419, 0.1, 3], [0.061963, -2.252004]], [[1.0, 0.0, 10.0, 1.0, 0.0, 0.05, 0], [1.0, 0.0]], [[1.379, 0.616, 8.923, 2.136, 0.586, 0.2, 6], [-0.73245, -1.93096]], [[-1.933, -0.041, 34.51, 1.593, 0.382, 0.04, 7], [-0.371615, 8.446595]], [[1.917, -0.356, 37.204, 0.914, 1.124, 0.05, 1], [1.705218, -4.235646]], [[0.784, -0.426, 6.875, 0.731, 0.044, 0.1, 14], [-0.132405, 2.308875]], [[-1.712, -1.9, 9.139, 0.693, 0.61, 0.05, 13], [0.624756, 4.351887]], [[0.116, -1.998, 11.275, 2.342, 1.481, 0.1, 12], [-0.366142, 1.157058]]], [[[1.974, -1.489, 34.073, 1.218, 1.372, 0.05, 10], [-1.429284, -2.634338]], [[-0.35, 0.424, 29.342, 2.686, 0.717, 0.1, 17], [-0.290817, -0.295428]], [[1.0, 0.0, 10.0, 1.0, 0.0, 0.05, 0], [1.0, 0.0]], [[1.909, 0.002, 19.499, 0.727, 0.055, 0.07, 1], [1.723198, -3.518566]], [[-0.232, -0.896, 22.107, 2.288, 0.298, 0.05, 13], [-0.138779, 0.957068]], [[0.365, -1.083, 14.951, 2.014, 1.412, 0.1, 6], [-0.316376, -0.70557]], [[1.14, -1.811, 37.1, 2.271, 0.543, 0.1, 3], [-0.098331, -4.928458]], [[-1.139, -1.668, 38.055, 1.696, 0.596, 0.04, 15], [0.910047, 2.799705]]], [[[0.494, 0.825, 29.084, 1.543, 0.219, 0.13, 11], [0.437707, 0.851286]], [[1.0, 0.0, 10.0, 1.0, 0.0, 0.05, 0], [1.0, 0.0]], [[1.873, -0.51, 29.384, 1.99, 0.411, 0.2, 16], [1.352031, 0.801221]], [[-1.86, -0.316, 22.084, 0.67, 1.741, 0.04, 12], [0.841343, 2.344066]], [[1.804, -0.317, 3.677, 1.295, 1.017, 0.07, 2], [1.702225, -0.959409]], [[-0.078, -0.863, 3.994, 2.622, 1.462, 0.1, 0], [-0.078, -0.863]], [[0.36, -1.513, 9.018, 1.848, 0.394, 0.05, 8], [-0.288846, -1.518381]], [[0.336, -1.099, 12.993, 2.616, 1.417, 0.05, 19], [-0.440588, -0.012857]]]]
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.0, 0.0][1.0, 0.0]Passed
case 1[-1.377, 0.559][-1.377, 0.559]Passed
case 2[0.763682, -1.657161][0.763682, -1.657161]Passed
case 3[0.749953, -0.924042][0.749953, -0.924042]Passed
case 4[-1.933886, 0.586176][-1.933886, 0.586176]Passed
case 5[0.947903, -0.524986][0.947903, -0.524986]Passed
case 6[0.748209, -0.324535][0.748209, -0.324535]Passed
case 7[0.36285, -0.625106][0.36285, -0.625106]Passed

SHA-256 / 1fb4202258a82c2e4d87d6434182ad340ae6ea58753c31af51c375062bac3985

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

Case digest / 053dbc2a8ef790f1c5289b50909c4daf40854c1211b97d2217604b6379a8c35e