{"abstract":"Heavy bodies are classified with the eigenvalues of a unit-mass system.","category":"Physics integrator stability","checks":8,"contract":"solve(k, m, c, dt): classify explicit Euler on x'=v, v'=(-k*x-c*v)/m. Eigenvalues are the roots of s^2+(c/m)s+k/m; amplification is max |1+dt*lambda|. Return [\"marginal\" if |amp-1|<=1e-9, else \"stable\" if amp<1, else \"unstable\", amp rounded to 6].","evaluation_group":"w2-physics_integrator_stability-explicit-euler-stability","failed_approach":"Using 2*k/m instead of 4*k/m misplaces the critical-damping boundary.","family":"w2-physics_integrator_stability-explicit-euler-stability-discriminant-stiffness-scaling","id":"FA-86906","implementations":{"attempt":{"sha256":"b2ab26a57b254a62fdc0b8026fccb4d9cda73b5e5301fb1334756af1339bfb0b","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(k, m, c, dt):\n    a = c / m\n    b = k / m\n    disc = a * a - 2 * b\n    if disc >= 0:\n        r = math.sqrt(disc)\n        lams = [complex((-a + r) / 2, 0), complex((-a - r) / 2, 0)]\n    else:\n        r = math.sqrt(-disc)\n        lams = [complex(-a / 2, r / 2), complex(-a / 2, -r / 2)]\n    amp = max(abs(1 + dt * lam) for lam in lams)\n    if abs(amp - 1) <= 1e-9:\n        label = 'marginal'\n    elif amp < 1:\n        label = 'stable'\n    else:\n        label = 'unstable'\n    return [label, round(amp, 6)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[[[48.787, 2.932, 7.285, 0.05], ['stable', 0.957792]], [[0.0, 1.0, 1.0, 0.5], ['marginal', 1.0]], [[39.354, 3.167, 6.495, 0.4], ['unstable', 1.472368]], [[39.672, 0.379, 2.933, 1.0], ['unstable', 9.896296]], [[46.563, 1.397, 1.187, 0.01], ['stable', 0.997415]], [[0.0, 3.279, 2.912, 0.2], ['marginal', 1.0]], [[42.742, 0.3, 1.248, 1.0], ['unstable', 11.803107]], [[0.0, 1.0, 2.0008, 1.0], ['unstable', 1.0008]]], [[[34.159, 0.297, 5.802, 0.2], ['unstable', 1.301333]], [[47.405, 3.962, 4.696, 0.05], ['stable', 0.985215]], [[0.0, 1.357, 2.319, 0.4], ['marginal', 1.0]], [[7.047, 1.493, 0.783, 0.8], ['unstable', 1.897698]], [[0.0, 1.0, 1.0, 0.5], ['marginal', 1.0]], [[25.383, 3.183, 5.311, 0.2], ['stable', 0.992609]], [[28.131, 2.644, 5.026, 0.2], ['unstable', 1.022448]], [[0.0, 1.0, 2.0008, 1.0], ['unstable', 1.0008]]], [[[0.0, 1.0, 1.0, 0.5], ['marginal', 1.0]], [[33.332, 2.078, 0.851, 0.05], ['unstable', 1.009765]], [[0.0, 0.563, 2.488, 0.01], ['marginal', 1.0]], [[8.52, 3.836, 5.13, 0.4], ['stable', 0.90578]], [[15.636, 2.616, 6.979, 0.8], ['unstable', 1.640448]], [[34.687, 1.578, 6.074, 0.2], ['unstable', 1.053295]], [[0.0, 1.0, 2.0008, 1.0], ['unstable', 1.0008]], [[17.304, 2.161, 0.31, 0.4], ['unstable', 1.491242]]], [[[21.305, 1.348, 3.845, 0.2], ['unstable', 1.030398]], [[5.291, 2.418, 3.167, 0.01], ['stable', 0.99354]], [[0.0, 1.0, 2.0008, 1.0], ['unstable', 1.0008]], [[0.0, 1.0, 1.0, 0.5], ['marginal', 1.0]], [[9.84, 2.992, 6.533, 0.4], ['stable', 0.807965]], [[0.0, 2.391, 6.417, 0.01], ['marginal', 1.0]], [[55.105, 1.329, 4.732, 0.8], ['unstable', 4.968721]], [[15.373, 0.488, 0.687, 0.8], ['unstable', 4.476057]]], [[[1.0, 1.0, 3.0, 0.1], ['stable', 0.961803]], [[41.507, 2.269, 5.919, 0.8], ['unstable', 3.258936]], [[0.0, 0.76, 4.988, 1.0], ['unstable', 5.563158]], [[48.542, 2.726, 7.357, 0.8], ['unstable', 3.199601]], [[0.0, 1.0, 2.0008, 1.0], ['unstable', 1.0008]], [[0.0, 1.0, 1.0, 0.5], ['marginal', 1.0]], [[36.647, 2.751, 2.545, 0.01], ['stable', 0.996033]], [[14.174, 2.424, 0.649, 0.8], ['unstable', 2.127938]]]]\nfor i, (args, expected) in enumerate(fixtures[N-1]):\n    check(\"case %d\" % i, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"81dda2acaf59cabd5af09c7168d8bb8a671d1392ef82c9b982d5ee8907198821","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(k, m, c, dt):\n    a = c / m\n    b = k / m\n    disc = a * a - 4 * k\n    if disc >= 0:\n        r = math.sqrt(disc)\n        lams = [complex((-a + r) / 2, 0), complex((-a - r) / 2, 0)]\n    else:\n        r = math.sqrt(-disc)\n        lams = [complex(-a / 2, r / 2), complex(-a / 2, -r / 2)]\n    amp = max(abs(1 + dt * lam) for lam in lams)\n    if abs(amp - 1) <= 1e-9:\n        label = 'marginal'\n    elif amp < 1:\n        label = 'stable'\n    else:\n        label = 'unstable'\n    return [label, round(amp, 6)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[[[48.787, 2.932, 7.285, 0.05], ['stable', 0.957792]], [[0.0, 1.0, 1.0, 0.5], ['marginal', 1.0]], [[39.354, 3.167, 6.495, 0.4], ['unstable', 1.472368]], [[39.672, 0.379, 2.933, 1.0], ['unstable', 9.896296]], [[46.563, 1.397, 1.187, 0.01], ['stable', 0.997415]], [[0.0, 3.279, 2.912, 0.2], ['marginal', 1.0]], [[42.742, 0.3, 1.248, 1.0], ['unstable', 11.803107]], [[0.0, 1.0, 2.0008, 1.0], ['unstable', 1.0008]]], [[[34.159, 0.297, 5.802, 0.2], ['unstable', 1.301333]], [[47.405, 3.962, 4.696, 0.05], ['stable', 0.985215]], [[0.0, 1.357, 2.319, 0.4], ['marginal', 1.0]], [[7.047, 1.493, 0.783, 0.8], ['unstable', 1.897698]], [[0.0, 1.0, 1.0, 0.5], ['marginal', 1.0]], [[25.383, 3.183, 5.311, 0.2], ['stable', 0.992609]], [[28.131, 2.644, 5.026, 0.2], ['unstable', 1.022448]], [[0.0, 1.0, 2.0008, 1.0], ['unstable', 1.0008]]], [[[0.0, 1.0, 1.0, 0.5], ['marginal', 1.0]], [[33.332, 2.078, 0.851, 0.05], ['unstable', 1.009765]], [[0.0, 0.563, 2.488, 0.01], ['marginal', 1.0]], [[8.52, 3.836, 5.13, 0.4], ['stable', 0.90578]], [[15.636, 2.616, 6.979, 0.8], ['unstable', 1.640448]], [[34.687, 1.578, 6.074, 0.2], ['unstable', 1.053295]], [[0.0, 1.0, 2.0008, 1.0], ['unstable', 1.0008]], [[17.304, 2.161, 0.31, 0.4], ['unstable', 1.491242]]], [[[21.305, 1.348, 3.845, 0.2], ['unstable', 1.030398]], [[5.291, 2.418, 3.167, 0.01], ['stable', 0.99354]], [[0.0, 1.0, 2.0008, 1.0], ['unstable', 1.0008]], [[0.0, 1.0, 1.0, 0.5], ['marginal', 1.0]], [[9.84, 2.992, 6.533, 0.4], ['stable', 0.807965]], [[0.0, 2.391, 6.417, 0.01], ['marginal', 1.0]], [[55.105, 1.329, 4.732, 0.8], ['unstable', 4.968721]], [[15.373, 0.488, 0.687, 0.8], ['unstable', 4.476057]]], [[[1.0, 1.0, 3.0, 0.1], ['stable', 0.961803]], [[41.507, 2.269, 5.919, 0.8], ['unstable', 3.258936]], [[0.0, 0.76, 4.988, 1.0], ['unstable', 5.563158]], [[48.542, 2.726, 7.357, 0.8], ['unstable', 3.199601]], [[0.0, 1.0, 2.0008, 1.0], ['unstable', 1.0008]], [[0.0, 1.0, 1.0, 0.5], ['marginal', 1.0]], [[36.647, 2.751, 2.545, 0.01], ['stable', 0.996033]], [[14.174, 2.424, 0.649, 0.8], ['unstable', 2.127938]]]]\nfor i, (args, expected) in enumerate(fixtures[N-1]):\n    check(\"case %d\" % i, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"fixed":{"sha256":"891153dd6f7b7c2b2080b6795e7b090072aa4e6d7eaa89773efb5c90f02fbe37","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(k, m, c, dt):\n    a = c / m\n    b = k / m\n    disc = a * a - 4 * b\n    if disc >= 0:\n        r = math.sqrt(disc)\n        lams = [complex((-a + r) / 2, 0), complex((-a - r) / 2, 0)]\n    else:\n        r = math.sqrt(-disc)\n        lams = [complex(-a / 2, r / 2), complex(-a / 2, -r / 2)]\n    amp = max(abs(1 + dt * lam) for lam in lams)\n    if abs(amp - 1) <= 1e-9:\n        label = 'marginal'\n    elif amp < 1:\n        label = 'stable'\n    else:\n        label = 'unstable'\n    return [label, round(amp, 6)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[[[48.787, 2.932, 7.285, 0.05], ['stable', 0.957792]], [[0.0, 1.0, 1.0, 0.5], ['marginal', 1.0]], [[39.354, 3.167, 6.495, 0.4], ['unstable', 1.472368]], [[39.672, 0.379, 2.933, 1.0], ['unstable', 9.896296]], [[46.563, 1.397, 1.187, 0.01], ['stable', 0.997415]], [[0.0, 3.279, 2.912, 0.2], ['marginal', 1.0]], [[42.742, 0.3, 1.248, 1.0], ['unstable', 11.803107]], [[0.0, 1.0, 2.0008, 1.0], ['unstable', 1.0008]]], [[[34.159, 0.297, 5.802, 0.2], ['unstable', 1.301333]], [[47.405, 3.962, 4.696, 0.05], ['stable', 0.985215]], [[0.0, 1.357, 2.319, 0.4], ['marginal', 1.0]], [[7.047, 1.493, 0.783, 0.8], ['unstable', 1.897698]], [[0.0, 1.0, 1.0, 0.5], ['marginal', 1.0]], [[25.383, 3.183, 5.311, 0.2], ['stable', 0.992609]], [[28.131, 2.644, 5.026, 0.2], ['unstable', 1.022448]], [[0.0, 1.0, 2.0008, 1.0], ['unstable', 1.0008]]], [[[0.0, 1.0, 1.0, 0.5], ['marginal', 1.0]], [[33.332, 2.078, 0.851, 0.05], ['unstable', 1.009765]], [[0.0, 0.563, 2.488, 0.01], ['marginal', 1.0]], [[8.52, 3.836, 5.13, 0.4], ['stable', 0.90578]], [[15.636, 2.616, 6.979, 0.8], ['unstable', 1.640448]], [[34.687, 1.578, 6.074, 0.2], ['unstable', 1.053295]], [[0.0, 1.0, 2.0008, 1.0], ['unstable', 1.0008]], [[17.304, 2.161, 0.31, 0.4], ['unstable', 1.491242]]], [[[21.305, 1.348, 3.845, 0.2], ['unstable', 1.030398]], [[5.291, 2.418, 3.167, 0.01], ['stable', 0.99354]], [[0.0, 1.0, 2.0008, 1.0], ['unstable', 1.0008]], [[0.0, 1.0, 1.0, 0.5], ['marginal', 1.0]], [[9.84, 2.992, 6.533, 0.4], ['stable', 0.807965]], [[0.0, 2.391, 6.417, 0.01], ['marginal', 1.0]], [[55.105, 1.329, 4.732, 0.8], ['unstable', 4.968721]], [[15.373, 0.488, 0.687, 0.8], ['unstable', 4.476057]]], [[[1.0, 1.0, 3.0, 0.1], ['stable', 0.961803]], [[41.507, 2.269, 5.919, 0.8], ['unstable', 3.258936]], [[0.0, 0.76, 4.988, 1.0], ['unstable', 5.563158]], [[48.542, 2.726, 7.357, 0.8], ['unstable', 3.199601]], [[0.0, 1.0, 2.0008, 1.0], ['unstable', 1.0008]], [[0.0, 1.0, 1.0, 0.5], ['marginal', 1.0]], [[36.647, 2.751, 2.545, 0.01], ['stable', 0.996033]], [[14.174, 2.424, 0.649, 0.8], ['unstable', 2.127938]]]]\nfor i, (args, expected) in enumerate(fixtures[N-1]):\n    check(\"case %d\" % i, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"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.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-physics_integrator_stability-explicit-euler-stability-discriminant-stiffness-scaling","generated_at":"2026-09-29T14:50:53.875683+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"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.","repair":"Normalize stiffness by mass before forming the characteristic polynomial.","root_cause":"The discriminant is (c/m)^2 - 4k instead of (c/m)^2 - 4k/m.","sha256":"d7732dcee4048383a1fd4d4e07b27892b2b50ce43e5b546ad5f0cc5351dacb18","title":"Stability discriminant uses raw stiffness instead of k over m · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":41.497,"exit_code":1,"observations":[{"actual":["stable",0.946872],"check":"case 0","expected":["stable",0.957792],"passed":false},{"actual":["marginal",1.0],"check":"case 1","expected":["marginal",1.0],"passed":true},{"actual":["unstable",1.083405],"check":"case 2","expected":["unstable",1.472368],"passed":false},{"actual":["unstable",6.752699],"check":"case 3","expected":["unstable",9.896296],"passed":false},{"actual":["stable",0.996579],"check":"case 4","expected":["stable",0.997415],"passed":false},{"actual":["marginal",1.0],"check":"case 5","expected":["marginal",1.0],"passed":true},{"actual":["unstable",8.250859],"check":"case 6","expected":["unstable",11.803107],"passed":false},{"actual":["unstable",1.0008],"check":"case 7","expected":["unstable",1.0008],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"case 0\", \"actual\": [\"stable\", 0.946872], \"expected\": [\"stable\", 0.957792], \"passed\": false}, {\"check\": \"case 1\", \"actual\": [\"marginal\", 1.0], \"expected\": [\"marginal\", 1.0], \"passed\": true}, {\"check\": \"case 2\", \"actual\": [\"unstable\", 1.083405], \"expected\": [\"unstable\", 1.472368], \"passed\": false}, {\"check\": \"case 3\", \"actual\": [\"unstable\", 6.752699], \"expected\": [\"unstable\", 9.896296], \"passed\": false}, {\"check\": \"case 4\", \"actual\": [\"stable\", 0.996579], \"expected\": [\"stable\", 0.997415], \"passed\": false}, {\"check\": \"case 5\", \"actual\": [\"marginal\", 1.0], \"expected\": [\"marginal\", 1.0], \"passed\": true}, {\"check\": \"case 6\", \"actual\": [\"unstable\", 8.250859], \"expected\": [\"unstable\", 11.803107], \"passed\": false}, {\"check\": \"case 7\", \"actual\": [\"unstable\", 1.0008], \"expected\": [\"unstable\", 1.0008], \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":38.913,"exit_code":1,"observations":[{"actual":["stable",0.998867],"check":"case 0","expected":["stable",0.957792],"passed":false},{"actual":["marginal",1.0],"check":"case 1","expected":["marginal",1.0],"passed":true},{"actual":["unstable",2.544859],"check":"case 2","expected":["unstable",1.472368],"passed":false},{"actual":["unstable",5.738747],"check":"case 3","expected":["unstable",9.896296],"passed":false},{"actual":["stable",0.998078],"check":"case 4","expected":["stable",0.997415],"passed":false},{"actual":["marginal",1.0],"check":"case 5","expected":["marginal",1.0],"passed":true},{"actual":["unstable",6.291423],"check":"case 6","expected":["unstable",11.803107],"passed":false},{"actual":["unstable",1.0008],"check":"case 7","expected":["unstable",1.0008],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"case 0\", \"actual\": [\"stable\", 0.998867], \"expected\": [\"stable\", 0.957792], \"passed\": false}, {\"check\": \"case 1\", \"actual\": [\"marginal\", 1.0], \"expected\": [\"marginal\", 1.0], \"passed\": true}, {\"check\": \"case 2\", \"actual\": [\"unstable\", 2.544859], \"expected\": [\"unstable\", 1.472368], \"passed\": false}, {\"check\": \"case 3\", \"actual\": [\"unstable\", 5.738747], \"expected\": [\"unstable\", 9.896296], \"passed\": false}, {\"check\": \"case 4\", \"actual\": [\"stable\", 0.998078], \"expected\": [\"stable\", 0.997415], \"passed\": false}, {\"check\": \"case 5\", \"actual\": [\"marginal\", 1.0], \"expected\": [\"marginal\", 1.0], \"passed\": true}, {\"check\": \"case 6\", \"actual\": [\"unstable\", 6.291423], \"expected\": [\"unstable\", 11.803107], \"passed\": false}, {\"check\": \"case 7\", \"actual\": [\"unstable\", 1.0008], \"expected\": [\"unstable\", 1.0008], \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":40.43,"exit_code":0,"observations":[{"actual":["stable",0.957792],"check":"case 0","expected":["stable",0.957792],"passed":true},{"actual":["marginal",1.0],"check":"case 1","expected":["marginal",1.0],"passed":true},{"actual":["unstable",1.472368],"check":"case 2","expected":["unstable",1.472368],"passed":true},{"actual":["unstable",9.896296],"check":"case 3","expected":["unstable",9.896296],"passed":true},{"actual":["stable",0.997415],"check":"case 4","expected":["stable",0.997415],"passed":true},{"actual":["marginal",1.0],"check":"case 5","expected":["marginal",1.0],"passed":true},{"actual":["unstable",11.803107],"check":"case 6","expected":["unstable",11.803107],"passed":true},{"actual":["unstable",1.0008],"check":"case 7","expected":["unstable",1.0008],"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"case 0\", \"actual\": [\"stable\", 0.957792], \"expected\": [\"stable\", 0.957792], \"passed\": true}, {\"check\": \"case 1\", \"actual\": [\"marginal\", 1.0], \"expected\": [\"marginal\", 1.0], \"passed\": true}, {\"check\": \"case 2\", \"actual\": [\"unstable\", 1.472368], \"expected\": [\"unstable\", 1.472368], \"passed\": true}, {\"check\": \"case 3\", \"actual\": [\"unstable\", 9.896296], \"expected\": [\"unstable\", 9.896296], \"passed\": true}, {\"check\": \"case 4\", \"actual\": [\"stable\", 0.997415], \"expected\": [\"stable\", 0.997415], \"passed\": true}, {\"check\": \"case 5\", \"actual\": [\"marginal\", 1.0], \"expected\": [\"marginal\", 1.0], \"passed\": true}, {\"check\": \"case 6\", \"actual\": [\"unstable\", 11.803107], \"expected\": [\"unstable\", 11.803107], \"passed\": true}, {\"check\": \"case 7\", \"actual\": [\"unstable\", 1.0008], \"expected\": [\"unstable\", 1.0008], \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}