|
1 | 1 | """Synthetic evidence must never become publication or live capability authority.""" |
2 | 2 |
|
3 | 3 | import copy |
| 4 | +import decimal |
4 | 5 | import json |
5 | 6 | import unittest |
6 | 7 | from pathlib import Path |
@@ -291,3 +292,62 @@ def cancel(stop=stop): |
291 | 292 |
|
292 | 293 | with self.subTest(stop=stop), self.assertRaises(InterruptedError): |
293 | 294 | evaluate(fixture(), check_cancel=cancel) |
| 295 | + |
| 296 | + def test_gate_decisions_ignore_ambient_decimal_context(self): |
| 297 | + accepted = fixture() |
| 298 | + for report in accepted["reports"].values(): |
| 299 | + report["metrics"]["accuracy"]["uncertainty"] = 0 |
| 300 | + accepted["reports"]["candidate"]["metrics"]["accuracy"]["value"] = 0.85 |
| 301 | + rejected = copy.deepcopy(accepted) |
| 302 | + rejected["reports"]["candidate"]["metrics"]["accuracy"]["value"] = 0.849 |
| 303 | + rounded_up = fixture() |
| 304 | + rounded_up["reports"]["candidate"]["metrics"]["accuracy"]["value"] = 0.84 |
| 305 | + cases = [accepted, rejected, rounded_up] |
| 306 | + for uncertainty in (1e-30, 5e-324): |
| 307 | + tiny = copy.deepcopy(accepted) |
| 308 | + tiny["reports"]["candidate"]["metrics"]["accuracy"]["uncertainty"] = ( |
| 309 | + uncertainty |
| 310 | + ) |
| 311 | + self.assertIn("insufficient_gain", evaluate(tiny).reasons) |
| 312 | + cases.append(tiny) |
| 313 | + classified = copy.deepcopy(cases[3]) |
| 314 | + classified["policy"]["metrics"][0]["gain"] = 0.04 |
| 315 | + classified["taxonomy"]["rules"][0]["minimum"] = 0.85 |
| 316 | + retax(classified) |
| 317 | + self.assertEqual(evaluate(classified).status, "unclassified") |
| 318 | + resource = copy.deepcopy(cases[3]) |
| 319 | + resource["policy"]["metrics"][0].update(gain=0.04, maximum=0.85) |
| 320 | + self.assertIn("resource_or_uncertainty", evaluate(resource).reasons) |
| 321 | + regression = copy.deepcopy(accepted) |
| 322 | + regression["reports"]["candidate"]["metrics"]["memory"].update( |
| 323 | + value=1024, uncertainty=1e-30 |
| 324 | + ) |
| 325 | + regression["policy"]["metrics"][1]["uncertainty"] = 1 |
| 326 | + self.assertIn("regression", evaluate(regression).reasons) |
| 327 | + cases.extend((classified, resource, regression)) |
| 328 | + expected = tuple(evaluate(case) for case in cases) |
| 329 | + self.assertEqual(expected[0].status, "eligible") |
| 330 | + self.assertIn("insufficient_gain", expected[1].reasons) |
| 331 | + self.assertIn("insufficient_gain", expected[2].reasons) |
| 332 | + for precision in (1, 2, 28, 100, 350): |
| 333 | + for rounding in ( |
| 334 | + decimal.ROUND_DOWN, |
| 335 | + decimal.ROUND_UP, |
| 336 | + decimal.ROUND_HALF_EVEN, |
| 337 | + decimal.ROUND_FLOOR, |
| 338 | + decimal.ROUND_CEILING, |
| 339 | + ): |
| 340 | + with ( |
| 341 | + self.subTest(precision=precision, rounding=rounding), |
| 342 | + decimal.localcontext() as context, |
| 343 | + ): |
| 344 | + context.prec = precision |
| 345 | + context.rounding = rounding |
| 346 | + context.Emax = 1 |
| 347 | + context.Emin = -1 |
| 348 | + for signal in context.traps: |
| 349 | + context.traps[signal] = True |
| 350 | + self.assertEqual(tuple(evaluate(case) for case in cases), expected) |
| 351 | + self.assertFalse(any(context.flags.values())) |
| 352 | + with self.assertRaises(ValueError): |
| 353 | + naming._number(10**12 + 1) |
0 commit comments