FA-87216 / Physics integrator stability / Open access
Friction limit uses this iteration normal correction instead of the accumulated normal impulse · case 01
Friction vanishes on resting contacts once the normal impulse has converged.
ROOT CAUSE
lim is mu times the normal delta implied by current vn.
VERIFIED REPAIR
Bound friction by mu times the accumulated normal impulse of the same point.
Unsuccessful approach: Using the total normal impulse of all points over-allows friction per point.
Case contract
solve(vn0, vt0, w, mu, iterations, cached, warm): several contact points share one relative normal and tangent velocity with inverse mass w. Warm start each point with warm*cached [jn, jt] and apply it to the velocities. Each iteration visits points in order: friction first (accumulated jt clamped to |jt|<=mu*jn), then normal (accumulated jn clamped >=0). Return [jn list, jt list, vn, vt] rounded to 6.
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(vn0, vt0, w, mu, iterations, cached, warm):
vn, vt = vn0, vt0
jn = [p[0] * warm for p in cached]
jt = [p[1] * warm for p in cached]
for i in range(len(cached)):
vn += jn[i] * w
vt += jt[i] * w
for _ in range(iterations):
for i in range(len(cached)):
d = -vt / w
old = jt[i]
lim = mu * max(0.0, -vn / w)
jt[i] = max(-lim, min(lim, old + d))
vt += (jt[i] - old) * w
d = -vn / w
old = jn[i]
jn[i] = max(0.0, old + d)
vn += (jn[i] - old) * w
return [[round(a, 6) for a in jn], [round(b, 6) for b in jt], round(vn, 6), round(vt, 6)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[-2.209, 1.975, 1.417, 0.675, 3, [[0.929, -0.36]], 0.0], [[1.558927], [-1.052276], 0.0, 0.483925]], [[-3.127, -2.902, 1.619, 0.582, 1, [[1.877, -0.518], [1.138, -0.685], [1.496, -0.263]], 0.8], [[0.0, 0.734639, 1.1968], [0.873931, 0.529853, 0.38868], -0.0, 0.0]], [[0.947, 1.031, 0.325, 0.552, 1, [[0.694, 0.484]], 0.0], [[0.0], [-0.0], 0.947, 1.031]], [[-2.972, 0.049, 0.405, 0.199, 3, [[1.938, 0.409], [0.746, 0.957], [1.714, -0.847]], 1.0], [[4.878272, 0.746, 1.714], [-0.230988, 0.148454, -0.038454], 0.0, 0.0]], [[-1.32, 2.008, 0.841, 0.221, 3, [[1.718, 0.031], [1.019, 0.732], [1.693, 0.707]], 0.5], [[0.21356, 0.5095, 0.8465], [-0.047197, -0.112599, -0.187077], 0.0, 1.71628]], [[0.685, -1.149, 1.581, 0.319, 3, [[1.639, 0.089], [0.704, 0.468], [1.459, 0.87]], 0.5], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.685, -1.149]], [[0.518, 1.079, 1.366, 0.571, 2, [[1.023, 0.026], [0.737, -0.544], [1.445, 0.496]], 1.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.518, 1.079]], [[-3.653, 1.12, 0.99, 0.893, 2, [[1.682, 0.186], [0.139, -0.492], [1.474, -0.788]], 1.0], [[2.076899, 0.139, 1.474], [0.148687, -0.124127, -1.155873], -0.0, -0.0]]], [[[-1.042, 2.295, 0.922, 0.86, 2, [[0.11, -0.905]], 1.0], [[1.130152], [-0.971931], -0.0, 1.39888]], [[-3.903, -0.953, 0.987, 0.656, 2, [[1.967, 0.024], [1.697, 0.748]], 0.8], [[2.596807, 1.3576], [0.367152, 0.5984], 0.0, 0.0]], [[-3.108, 2.921, 1.142, 0.923, 4, [[0.023, -0.195]], 0.8], [[2.721541], [-2.511982], 0.0, 0.052316]], [[-1.5, 0.461, 1.602, 0.795, 3, [[0.381, -0.102], [0.711, 0.701]], 0.0], [[0.93633, 0.0], [-0.287765, -0.0], 0.0, 0.0]], [[-0.349, 0.709, 1.805, 0.199, 2, [[1.996, 0.558], [0.968, -0.267], [0.402, -0.027]], 0.5], [[0.0, 0.0, 0.193352], [-0.0, -0.0, -0.038477], 0.0, 0.639549]], [[0.578, 0.29, 0.728, 0.942, 1, [[1.136, 0.902], [1.554, -0.352], [0.349, 0.603]], 0.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.578, 0.29]], [[0.115, 2.189, 0.872, 0.83, 4, [[0.286, 0.523], [1.66, 0.383], [0.531, 0.396]], 1.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.115, 2.189]], [[0.339, 2.047, 0.841, 0.892, 3, [[1.24, -0.237], [1.4, 0.513], [0.522, -0.064]], 0.5], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.339, 2.047]]], [[[-3.945, 0.313, 0.579, 0.007, 4, [[1.858, 0.554]], 1.0], [[6.813472], [-0.047694], 0.0, 0.285385]], [[-1.741, 2.952, 1.183, 0.686, 2, [[1.377, 0.722], [1.534, 0.263], [1.218, -0.431]], 0.8], [[0.0, 0.497282, 0.9744], [-0.0, -0.341136, -0.668438], 0.0, 1.757674]], [[-1.484, 2.237, 1.419, 0.156, 4, [[0.79, 0.429], [0.858, -0.626], [0.763, -0.269]], 0.0], [[1.045807, 0.0, 0.0], [-0.163146, -0.0, -0.0], 0.0, 2.005496]], [[-1.764, 0.95, 0.746, 0.826, 2, [[1.55, -0.124], [0.697, 0.933]], 0.5], [[2.016111, 0.3485], [-0.985597, -0.287861], -0.0, 0.0]], [[-3.539, -1.577, 1.815, 0.162, 3, [[0.659, -0.744], [0.674, -0.151], [0.214, -0.889]], 1.0], [[1.061862, 0.674, 0.214], [0.172022, 0.109188, 0.034668], 0.0, -1.003682]], [[0.81, 1.686, 0.505, 0.8, 3, [[0.886, 0.111], [0.617, -0.26], [1.685, 0.3]], 0.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.81, 1.686]], [[0.797, 2.472, 0.745, 0.449, 4, [[1.334, -0.607], [0.876, -0.826], [1.821, -0.196]], 0.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.797, 2.472]], [[0.972, 0.928, 1.615, 0.496, 4, [[0.104, -0.383]], 1.0], [[0.0], [-0.0], 0.972, 0.928]]], [[[-0.826, -2.129, 0.465, 0.979, 2, [[1.549, 0.328], [1.647, -0.412], [0.839, 0.41]], 1.0], [[0.0, 0.937344, 0.839], [-0.0, 0.91766, 0.821381], 0.0, -1.320346]], [[0.283, -1.445, 1.89, 0.821, 2, [[0.105, 0.547], [1.407, -0.066], [1.234, -0.397]], 0.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.283, -1.445]], [[0.637, -1.0, 1.022, 0.209, 3, [[1.878, 0.795]], 0.8], [[0.0], [-0.0], 0.637, -1.0]], [[0.692, 2.967, 1.501, 0.343, 2, [[1.011, -0.54], [0.619, -0.035]], 0.8], [[0.0, 0.0], [-0.0, -0.0], 0.692, 2.967]], [[-2.512, 1.891, 0.52, 0.913, 2, [[1.264, -0.192], [0.561, -0.801], [0.108, 0.906]], 1.0], [[4.161769, 0.561, 0.108], [-3.025741, -0.512193, -0.098604], 0.0, 0.0]], [[-3.466, 0.995, 0.812, 0.415, 2, [[0.997, -0.849], [0.672, -0.628], [0.553, 0.014]], 1.0], [[3.043473, 0.672, 0.553], [-0.716994, -0.27888, -0.229495], 0.0, 0.0]], [[-1.42, -2.766, 1.952, 0.672, 1, [[0.763, -0.712], [0.115, 0.007], [1.727, -0.475]], 0.8], [[0.0, 0.0, 0.727459], [0.410189, 0.061824, 0.928435], 0.0, -0.032326]], [[-3.141, -2.995, 1.861, 0.53, 2, [[1.266, 0.367], [0.624, -0.269]], 0.8], [[1.188602, 0.4992], [0.629959, 0.264576], 0.0, -1.33027]]], [[[-2.623, 2.49, 1.773, 0.603, 3, [[0.479, 0.054], [0.432, -0.331]], 0.0], [[1.479413, 0.0], [-0.892086, -0.0], 0.0, 0.908331]], [[0.993, -2.098, 0.238, 0.722, 3, [[0.661, -0.519]], 0.8], [[0.0], [-0.0], 0.993, -2.098]], [[-1.205, 1.89, 1.248, 0.416, 2, [[0.822, 0.038], [1.749, 0.597], [0.205, 0.7]], 0.8], [[0.0, 0.801545, 0.164], [-0.0, -0.333443, -0.068224], 0.0, 1.38872]], [[-0.236, -1.26, 1.507, 0.291, 1, [[0.089, 0.562], [0.695, 0.022], [1.181, 0.137]], 0.8], [[0.0, 0.0, 0.156603], [0.020719, 0.161796, 0.274937], 0.0, -0.57062]], [[0.279, 2.509, 0.761, 0.718, 4, [[1.705, 0.192], [1.344, 0.852], [1.905, 0.4]], 0.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.279, 2.509]], [[-2.733, 1.917, 1.443, 0.478, 3, [[1.98, 0.607], [1.891, 0.286]], 1.0], [[0.002971, 1.891], [-0.00142, -0.903898], 0.0, 0.610626]], [[-0.82, -0.785, 1.427, 0.454, 2, [[0.351, 0.839], [1.268, -0.155], [1.231, -0.702]], 0.8], [[0.0, 0.0, 0.574632], [-0.0, -0.0, 0.260883], -0.0, -0.41272]], [[0.963, 1.55, 1.235, 1.0, 2, [[1.265, 0.517], [1.674, -0.353], [1.159, -0.86]], 0.5], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.963, 1.55]]]]
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.558927], [-0.0], 0.0, 1.975] | [[1.558927], [-1.052276], 0.0, 0.483925] | Failed |
| case 1 | [[0.0, 0.734639, 1.1968], [-0.0, -0.0, 0.0], -0.0, -2.902] | [[0.0, 0.734639, 1.1968], [0.873931, 0.529853, 0.38868], -0.0, 0.0] | Failed |
| case 2 | [[0.0], [-0.0], 0.947, 1.031] | [[0.0], [-0.0], 0.947, 1.031] | Passed |
| case 3 | [[4.878272, 0.746, 1.714], [-0.0, -0.0, -0.0], 0.0, 0.049] | [[4.878272, 0.746, 1.714], [-0.230988, 0.148454, -0.038454], 0.0, 0.0] | Failed |
| case 4 | [[0.21356, 0.5095, 0.8465], [-0.0, -0.0, -0.0], 0.0, 2.008] | [[0.21356, 0.5095, 0.8465], [-0.047197, -0.112599, -0.187077], 0.0, 1.71628] | Failed |
| case 5 | [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.685, -1.149] | [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.685, -1.149] | Passed |
| case 6 | [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.518, 1.079] | [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.518, 1.079] | Passed |
| case 7 | [[2.076899, 0.139, 1.474], [-0.0, -0.0, -0.0], -0.0, 1.12] | [[2.076899, 0.139, 1.474], [0.148687, -0.124127, -1.155873], -0.0, -0.0] | Failed |
SHA-256 / 7f9702b00e3371dd0b3920aba9762583a2634e44b449f9a5c5a054220559ab9f
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(vn0, vt0, w, mu, iterations, cached, warm):
vn, vt = vn0, vt0
jn = [p[0] * warm for p in cached]
jt = [p[1] * warm for p in cached]
for i in range(len(cached)):
vn += jn[i] * w
vt += jt[i] * w
for _ in range(iterations):
for i in range(len(cached)):
d = -vt / w
old = jt[i]
lim = mu * sum(jn)
jt[i] = max(-lim, min(lim, old + d))
vt += (jt[i] - old) * w
d = -vn / w
old = jn[i]
jn[i] = max(0.0, old + d)
vn += (jn[i] - old) * w
return [[round(a, 6) for a in jn], [round(b, 6) for b in jt], round(vn, 6), round(vt, 6)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[-2.209, 1.975, 1.417, 0.675, 3, [[0.929, -0.36]], 0.0], [[1.558927], [-1.052276], 0.0, 0.483925]], [[-3.127, -2.902, 1.619, 0.582, 1, [[1.877, -0.518], [1.138, -0.685], [1.496, -0.263]], 0.8], [[0.0, 0.734639, 1.1968], [0.873931, 0.529853, 0.38868], -0.0, 0.0]], [[0.947, 1.031, 0.325, 0.552, 1, [[0.694, 0.484]], 0.0], [[0.0], [-0.0], 0.947, 1.031]], [[-2.972, 0.049, 0.405, 0.199, 3, [[1.938, 0.409], [0.746, 0.957], [1.714, -0.847]], 1.0], [[4.878272, 0.746, 1.714], [-0.230988, 0.148454, -0.038454], 0.0, 0.0]], [[-1.32, 2.008, 0.841, 0.221, 3, [[1.718, 0.031], [1.019, 0.732], [1.693, 0.707]], 0.5], [[0.21356, 0.5095, 0.8465], [-0.047197, -0.112599, -0.187077], 0.0, 1.71628]], [[0.685, -1.149, 1.581, 0.319, 3, [[1.639, 0.089], [0.704, 0.468], [1.459, 0.87]], 0.5], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.685, -1.149]], [[0.518, 1.079, 1.366, 0.571, 2, [[1.023, 0.026], [0.737, -0.544], [1.445, 0.496]], 1.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.518, 1.079]], [[-3.653, 1.12, 0.99, 0.893, 2, [[1.682, 0.186], [0.139, -0.492], [1.474, -0.788]], 1.0], [[2.076899, 0.139, 1.474], [0.148687, -0.124127, -1.155873], -0.0, -0.0]]], [[[-1.042, 2.295, 0.922, 0.86, 2, [[0.11, -0.905]], 1.0], [[1.130152], [-0.971931], -0.0, 1.39888]], [[-3.903, -0.953, 0.987, 0.656, 2, [[1.967, 0.024], [1.697, 0.748]], 0.8], [[2.596807, 1.3576], [0.367152, 0.5984], 0.0, 0.0]], [[-3.108, 2.921, 1.142, 0.923, 4, [[0.023, -0.195]], 0.8], [[2.721541], [-2.511982], 0.0, 0.052316]], [[-1.5, 0.461, 1.602, 0.795, 3, [[0.381, -0.102], [0.711, 0.701]], 0.0], [[0.93633, 0.0], [-0.287765, -0.0], 0.0, 0.0]], [[-0.349, 0.709, 1.805, 0.199, 2, [[1.996, 0.558], [0.968, -0.267], [0.402, -0.027]], 0.5], [[0.0, 0.0, 0.193352], [-0.0, -0.0, -0.038477], 0.0, 0.639549]], [[0.578, 0.29, 0.728, 0.942, 1, [[1.136, 0.902], [1.554, -0.352], [0.349, 0.603]], 0.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.578, 0.29]], [[0.115, 2.189, 0.872, 0.83, 4, [[0.286, 0.523], [1.66, 0.383], [0.531, 0.396]], 1.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.115, 2.189]], [[0.339, 2.047, 0.841, 0.892, 3, [[1.24, -0.237], [1.4, 0.513], [0.522, -0.064]], 0.5], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.339, 2.047]]], [[[-3.945, 0.313, 0.579, 0.007, 4, [[1.858, 0.554]], 1.0], [[6.813472], [-0.047694], 0.0, 0.285385]], [[-1.741, 2.952, 1.183, 0.686, 2, [[1.377, 0.722], [1.534, 0.263], [1.218, -0.431]], 0.8], [[0.0, 0.497282, 0.9744], [-0.0, -0.341136, -0.668438], 0.0, 1.757674]], [[-1.484, 2.237, 1.419, 0.156, 4, [[0.79, 0.429], [0.858, -0.626], [0.763, -0.269]], 0.0], [[1.045807, 0.0, 0.0], [-0.163146, -0.0, -0.0], 0.0, 2.005496]], [[-1.764, 0.95, 0.746, 0.826, 2, [[1.55, -0.124], [0.697, 0.933]], 0.5], [[2.016111, 0.3485], [-0.985597, -0.287861], -0.0, 0.0]], [[-3.539, -1.577, 1.815, 0.162, 3, [[0.659, -0.744], [0.674, -0.151], [0.214, -0.889]], 1.0], [[1.061862, 0.674, 0.214], [0.172022, 0.109188, 0.034668], 0.0, -1.003682]], [[0.81, 1.686, 0.505, 0.8, 3, [[0.886, 0.111], [0.617, -0.26], [1.685, 0.3]], 0.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.81, 1.686]], [[0.797, 2.472, 0.745, 0.449, 4, [[1.334, -0.607], [0.876, -0.826], [1.821, -0.196]], 0.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.797, 2.472]], [[0.972, 0.928, 1.615, 0.496, 4, [[0.104, -0.383]], 1.0], [[0.0], [-0.0], 0.972, 0.928]]], [[[-0.826, -2.129, 0.465, 0.979, 2, [[1.549, 0.328], [1.647, -0.412], [0.839, 0.41]], 1.0], [[0.0, 0.937344, 0.839], [-0.0, 0.91766, 0.821381], 0.0, -1.320346]], [[0.283, -1.445, 1.89, 0.821, 2, [[0.105, 0.547], [1.407, -0.066], [1.234, -0.397]], 0.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.283, -1.445]], [[0.637, -1.0, 1.022, 0.209, 3, [[1.878, 0.795]], 0.8], [[0.0], [-0.0], 0.637, -1.0]], [[0.692, 2.967, 1.501, 0.343, 2, [[1.011, -0.54], [0.619, -0.035]], 0.8], [[0.0, 0.0], [-0.0, -0.0], 0.692, 2.967]], [[-2.512, 1.891, 0.52, 0.913, 2, [[1.264, -0.192], [0.561, -0.801], [0.108, 0.906]], 1.0], [[4.161769, 0.561, 0.108], [-3.025741, -0.512193, -0.098604], 0.0, 0.0]], [[-3.466, 0.995, 0.812, 0.415, 2, [[0.997, -0.849], [0.672, -0.628], [0.553, 0.014]], 1.0], [[3.043473, 0.672, 0.553], [-0.716994, -0.27888, -0.229495], 0.0, 0.0]], [[-1.42, -2.766, 1.952, 0.672, 1, [[0.763, -0.712], [0.115, 0.007], [1.727, -0.475]], 0.8], [[0.0, 0.0, 0.727459], [0.410189, 0.061824, 0.928435], 0.0, -0.032326]], [[-3.141, -2.995, 1.861, 0.53, 2, [[1.266, 0.367], [0.624, -0.269]], 0.8], [[1.188602, 0.4992], [0.629959, 0.264576], 0.0, -1.33027]]], [[[-2.623, 2.49, 1.773, 0.603, 3, [[0.479, 0.054], [0.432, -0.331]], 0.0], [[1.479413, 0.0], [-0.892086, -0.0], 0.0, 0.908331]], [[0.993, -2.098, 0.238, 0.722, 3, [[0.661, -0.519]], 0.8], [[0.0], [-0.0], 0.993, -2.098]], [[-1.205, 1.89, 1.248, 0.416, 2, [[0.822, 0.038], [1.749, 0.597], [0.205, 0.7]], 0.8], [[0.0, 0.801545, 0.164], [-0.0, -0.333443, -0.068224], 0.0, 1.38872]], [[-0.236, -1.26, 1.507, 0.291, 1, [[0.089, 0.562], [0.695, 0.022], [1.181, 0.137]], 0.8], [[0.0, 0.0, 0.156603], [0.020719, 0.161796, 0.274937], 0.0, -0.57062]], [[0.279, 2.509, 0.761, 0.718, 4, [[1.705, 0.192], [1.344, 0.852], [1.905, 0.4]], 0.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.279, 2.509]], [[-2.733, 1.917, 1.443, 0.478, 3, [[1.98, 0.607], [1.891, 0.286]], 1.0], [[0.002971, 1.891], [-0.00142, -0.903898], 0.0, 0.610626]], [[-0.82, -0.785, 1.427, 0.454, 2, [[0.351, 0.839], [1.268, -0.155], [1.231, -0.702]], 0.8], [[0.0, 0.0, 0.574632], [-0.0, -0.0, 0.260883], -0.0, -0.41272]], [[0.963, 1.55, 1.235, 1.0, 2, [[1.265, 0.517], [1.674, -0.353], [1.159, -0.86]], 0.5], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.963, 1.55]]]]
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.558927], [-1.052276], 0.0, 0.483925] | [[1.558927], [-1.052276], 0.0, 0.483925] | Passed |
| case 1 | [[0.0, 0.734639, 1.1968], [2.100322, -0.097457, -0.2104], -0.0, 0.0] | [[0.0, 0.734639, 1.1968], [0.873931, 0.529853, 0.38868], -0.0, 0.0] | Failed |
| case 2 | [[0.0], [-0.0], 0.947, 1.031] | [[0.0], [-0.0], 0.947, 1.031] | Passed |
| case 3 | [[4.878272, 0.746, 1.714], [-0.230988, 0.957, -0.847], 0.0, 0.0] | [[4.878272, 0.746, 1.714], [-0.230988, 0.148454, -0.038454], 0.0, 0.0] | Failed |
| case 4 | [[0.21356, 0.5095, 0.8465], [-0.346873, -0.346873, -0.346873], 0.0, 1.13284] | [[0.21356, 0.5095, 0.8465], [-0.047197, -0.112599, -0.187077], 0.0, 1.71628] | Failed |
| case 5 | [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.685, -1.149] | [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.685, -1.149] | Passed |
| case 6 | [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.518, 1.079] | [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.518, 1.079] | Passed |
| case 7 | [[2.076899, 0.139, 1.474], [0.148687, -0.492, -0.788], -0.0, 0.0] | [[2.076899, 0.139, 1.474], [0.148687, -0.124127, -1.155873], -0.0, -0.0] | Failed |
SHA-256 / 4a469ee413796284c0ace3fb758032e832c9b2d567fe22c19f63b058de798f70
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(vn0, vt0, w, mu, iterations, cached, warm):
vn, vt = vn0, vt0
jn = [p[0] * warm for p in cached]
jt = [p[1] * warm for p in cached]
for i in range(len(cached)):
vn += jn[i] * w
vt += jt[i] * w
for _ in range(iterations):
for i in range(len(cached)):
d = -vt / w
old = jt[i]
lim = mu * jn[i]
jt[i] = max(-lim, min(lim, old + d))
vt += (jt[i] - old) * w
d = -vn / w
old = jn[i]
jn[i] = max(0.0, old + d)
vn += (jn[i] - old) * w
return [[round(a, 6) for a in jn], [round(b, 6) for b in jt], round(vn, 6), round(vt, 6)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[-2.209, 1.975, 1.417, 0.675, 3, [[0.929, -0.36]], 0.0], [[1.558927], [-1.052276], 0.0, 0.483925]], [[-3.127, -2.902, 1.619, 0.582, 1, [[1.877, -0.518], [1.138, -0.685], [1.496, -0.263]], 0.8], [[0.0, 0.734639, 1.1968], [0.873931, 0.529853, 0.38868], -0.0, 0.0]], [[0.947, 1.031, 0.325, 0.552, 1, [[0.694, 0.484]], 0.0], [[0.0], [-0.0], 0.947, 1.031]], [[-2.972, 0.049, 0.405, 0.199, 3, [[1.938, 0.409], [0.746, 0.957], [1.714, -0.847]], 1.0], [[4.878272, 0.746, 1.714], [-0.230988, 0.148454, -0.038454], 0.0, 0.0]], [[-1.32, 2.008, 0.841, 0.221, 3, [[1.718, 0.031], [1.019, 0.732], [1.693, 0.707]], 0.5], [[0.21356, 0.5095, 0.8465], [-0.047197, -0.112599, -0.187077], 0.0, 1.71628]], [[0.685, -1.149, 1.581, 0.319, 3, [[1.639, 0.089], [0.704, 0.468], [1.459, 0.87]], 0.5], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.685, -1.149]], [[0.518, 1.079, 1.366, 0.571, 2, [[1.023, 0.026], [0.737, -0.544], [1.445, 0.496]], 1.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.518, 1.079]], [[-3.653, 1.12, 0.99, 0.893, 2, [[1.682, 0.186], [0.139, -0.492], [1.474, -0.788]], 1.0], [[2.076899, 0.139, 1.474], [0.148687, -0.124127, -1.155873], -0.0, -0.0]]], [[[-1.042, 2.295, 0.922, 0.86, 2, [[0.11, -0.905]], 1.0], [[1.130152], [-0.971931], -0.0, 1.39888]], [[-3.903, -0.953, 0.987, 0.656, 2, [[1.967, 0.024], [1.697, 0.748]], 0.8], [[2.596807, 1.3576], [0.367152, 0.5984], 0.0, 0.0]], [[-3.108, 2.921, 1.142, 0.923, 4, [[0.023, -0.195]], 0.8], [[2.721541], [-2.511982], 0.0, 0.052316]], [[-1.5, 0.461, 1.602, 0.795, 3, [[0.381, -0.102], [0.711, 0.701]], 0.0], [[0.93633, 0.0], [-0.287765, -0.0], 0.0, 0.0]], [[-0.349, 0.709, 1.805, 0.199, 2, [[1.996, 0.558], [0.968, -0.267], [0.402, -0.027]], 0.5], [[0.0, 0.0, 0.193352], [-0.0, -0.0, -0.038477], 0.0, 0.639549]], [[0.578, 0.29, 0.728, 0.942, 1, [[1.136, 0.902], [1.554, -0.352], [0.349, 0.603]], 0.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.578, 0.29]], [[0.115, 2.189, 0.872, 0.83, 4, [[0.286, 0.523], [1.66, 0.383], [0.531, 0.396]], 1.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.115, 2.189]], [[0.339, 2.047, 0.841, 0.892, 3, [[1.24, -0.237], [1.4, 0.513], [0.522, -0.064]], 0.5], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.339, 2.047]]], [[[-3.945, 0.313, 0.579, 0.007, 4, [[1.858, 0.554]], 1.0], [[6.813472], [-0.047694], 0.0, 0.285385]], [[-1.741, 2.952, 1.183, 0.686, 2, [[1.377, 0.722], [1.534, 0.263], [1.218, -0.431]], 0.8], [[0.0, 0.497282, 0.9744], [-0.0, -0.341136, -0.668438], 0.0, 1.757674]], [[-1.484, 2.237, 1.419, 0.156, 4, [[0.79, 0.429], [0.858, -0.626], [0.763, -0.269]], 0.0], [[1.045807, 0.0, 0.0], [-0.163146, -0.0, -0.0], 0.0, 2.005496]], [[-1.764, 0.95, 0.746, 0.826, 2, [[1.55, -0.124], [0.697, 0.933]], 0.5], [[2.016111, 0.3485], [-0.985597, -0.287861], -0.0, 0.0]], [[-3.539, -1.577, 1.815, 0.162, 3, [[0.659, -0.744], [0.674, -0.151], [0.214, -0.889]], 1.0], [[1.061862, 0.674, 0.214], [0.172022, 0.109188, 0.034668], 0.0, -1.003682]], [[0.81, 1.686, 0.505, 0.8, 3, [[0.886, 0.111], [0.617, -0.26], [1.685, 0.3]], 0.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.81, 1.686]], [[0.797, 2.472, 0.745, 0.449, 4, [[1.334, -0.607], [0.876, -0.826], [1.821, -0.196]], 0.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.797, 2.472]], [[0.972, 0.928, 1.615, 0.496, 4, [[0.104, -0.383]], 1.0], [[0.0], [-0.0], 0.972, 0.928]]], [[[-0.826, -2.129, 0.465, 0.979, 2, [[1.549, 0.328], [1.647, -0.412], [0.839, 0.41]], 1.0], [[0.0, 0.937344, 0.839], [-0.0, 0.91766, 0.821381], 0.0, -1.320346]], [[0.283, -1.445, 1.89, 0.821, 2, [[0.105, 0.547], [1.407, -0.066], [1.234, -0.397]], 0.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.283, -1.445]], [[0.637, -1.0, 1.022, 0.209, 3, [[1.878, 0.795]], 0.8], [[0.0], [-0.0], 0.637, -1.0]], [[0.692, 2.967, 1.501, 0.343, 2, [[1.011, -0.54], [0.619, -0.035]], 0.8], [[0.0, 0.0], [-0.0, -0.0], 0.692, 2.967]], [[-2.512, 1.891, 0.52, 0.913, 2, [[1.264, -0.192], [0.561, -0.801], [0.108, 0.906]], 1.0], [[4.161769, 0.561, 0.108], [-3.025741, -0.512193, -0.098604], 0.0, 0.0]], [[-3.466, 0.995, 0.812, 0.415, 2, [[0.997, -0.849], [0.672, -0.628], [0.553, 0.014]], 1.0], [[3.043473, 0.672, 0.553], [-0.716994, -0.27888, -0.229495], 0.0, 0.0]], [[-1.42, -2.766, 1.952, 0.672, 1, [[0.763, -0.712], [0.115, 0.007], [1.727, -0.475]], 0.8], [[0.0, 0.0, 0.727459], [0.410189, 0.061824, 0.928435], 0.0, -0.032326]], [[-3.141, -2.995, 1.861, 0.53, 2, [[1.266, 0.367], [0.624, -0.269]], 0.8], [[1.188602, 0.4992], [0.629959, 0.264576], 0.0, -1.33027]]], [[[-2.623, 2.49, 1.773, 0.603, 3, [[0.479, 0.054], [0.432, -0.331]], 0.0], [[1.479413, 0.0], [-0.892086, -0.0], 0.0, 0.908331]], [[0.993, -2.098, 0.238, 0.722, 3, [[0.661, -0.519]], 0.8], [[0.0], [-0.0], 0.993, -2.098]], [[-1.205, 1.89, 1.248, 0.416, 2, [[0.822, 0.038], [1.749, 0.597], [0.205, 0.7]], 0.8], [[0.0, 0.801545, 0.164], [-0.0, -0.333443, -0.068224], 0.0, 1.38872]], [[-0.236, -1.26, 1.507, 0.291, 1, [[0.089, 0.562], [0.695, 0.022], [1.181, 0.137]], 0.8], [[0.0, 0.0, 0.156603], [0.020719, 0.161796, 0.274937], 0.0, -0.57062]], [[0.279, 2.509, 0.761, 0.718, 4, [[1.705, 0.192], [1.344, 0.852], [1.905, 0.4]], 0.0], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.279, 2.509]], [[-2.733, 1.917, 1.443, 0.478, 3, [[1.98, 0.607], [1.891, 0.286]], 1.0], [[0.002971, 1.891], [-0.00142, -0.903898], 0.0, 0.610626]], [[-0.82, -0.785, 1.427, 0.454, 2, [[0.351, 0.839], [1.268, -0.155], [1.231, -0.702]], 0.8], [[0.0, 0.0, 0.574632], [-0.0, -0.0, 0.260883], -0.0, -0.41272]], [[0.963, 1.55, 1.235, 1.0, 2, [[1.265, 0.517], [1.674, -0.353], [1.159, -0.86]], 0.5], [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.963, 1.55]]]]
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.558927], [-1.052276], 0.0, 0.483925] | [[1.558927], [-1.052276], 0.0, 0.483925] | Passed |
| case 1 | [[0.0, 0.734639, 1.1968], [0.873931, 0.529853, 0.38868], -0.0, 0.0] | [[0.0, 0.734639, 1.1968], [0.873931, 0.529853, 0.38868], -0.0, 0.0] | Passed |
| case 2 | [[0.0], [-0.0], 0.947, 1.031] | [[0.0], [-0.0], 0.947, 1.031] | Passed |
| case 3 | [[4.878272, 0.746, 1.714], [-0.230988, 0.148454, -0.038454], 0.0, 0.0] | [[4.878272, 0.746, 1.714], [-0.230988, 0.148454, -0.038454], 0.0, 0.0] | Passed |
| case 4 | [[0.21356, 0.5095, 0.8465], [-0.047197, -0.112599, -0.187077], 0.0, 1.71628] | [[0.21356, 0.5095, 0.8465], [-0.047197, -0.112599, -0.187077], 0.0, 1.71628] | Passed |
| case 5 | [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.685, -1.149] | [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.685, -1.149] | Passed |
| case 6 | [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.518, 1.079] | [[0.0, 0.0, 0.0], [-0.0, -0.0, -0.0], 0.518, 1.079] | Passed |
| case 7 | [[2.076899, 0.139, 1.474], [0.148687, -0.124127, -1.155873], -0.0, -0.0] | [[2.076899, 0.139, 1.474], [0.148687, -0.124127, -1.155873], -0.0, -0.0] | Passed |
SHA-256 / 728d56720b98e680d9240da0a39eb78db71c1afedab056b71f8a183d7c2f5693
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.647384+00:00.
Case digest / 337586b8793240decf58b4d656837a0b2e77f8708bccb1d7de0f10bed64a4a28