{"data":{"kind":"file","path":"README.md","version_id":"csktvohw7gbdzahnd029o4k9","entry":{"name":"README.md","path":"README.md","is_directory":false,"size":5888,"modified_at":"2026-08-20T04:10:04.124000","content_hash":"f2982d330a03c209e4474d957160aa9ae41ed27ac6bd9a8c54ca23e4eef935f5"},"entries":[],"content":"# numpy-scipy-exact\n\nA verifiable RL environment / eval for the exact mathematical values behind classic\nnumpy/scipy linear-algebra calls. numpy returns float approximations; the model must\nreturn the exact value.\n\n**Task types** (integer matrices, n = 4..6, entries in [-9, 9]; each instance names the\nnumpy/scipy call it mirrors):\n\n| type | mirrors | exact answer |\n|---|---|---|\n| `charpoly` | `np.poly(A)` | the n+1 integer coefficients of det(xI - A), monic, descending |\n| `inv_entry` | `np.linalg.inv(A)[i][j]`, `scipy.linalg.inv` | one entry of the inverse as a fraction [num, den] |\n| `power_trace` | `np.trace(np.linalg.matrix_power(A, k))`, k = 3..5 | a single large integer |\n| `solve_entry` | `np.linalg.solve(A, b)[i]`, `scipy.linalg.solve` | one solution entry as a fraction [num, den] |\n\n**Why this environment is trustworthy.**\n- **Recomputed rewards, no answer key.** The reward recomputes every ground truth from\n  the instance matrix at verify time using stdlib exact arithmetic (big ints +\n  `fractions.Fraction`; no floats anywhere in the grading path) and compares exactly.\n  Stored labels are never trusted; label fields are stripped from the dataset's `info`\n  column entirely. The grader never raises: malformed answers score 0.0.\n- **Cross-certified labels, two algorithms per task type.** Faddeev-LeVerrier vs\n  Lagrange interpolation of Bareiss determinants (charpoly); Cramer cofactor/det vs\n  exact-RREF solve (inv_entry); direct integer matrix power vs Newton's identities on\n  the characteristic polynomial (power_trace); exact RREF vs Cramer determinant ratio\n  (solve_entry). Minting fails loudly on any disagreement, and a property test\n  re-checks all four pairs on random matrices. A further test cross-checks minted\n  labels against numpy itself (skipped if numpy is absent).\n- **Guess-resistant by construction.** Minting enforces floors: |constant charpoly\n  coefficient| >= 10^(n-1); |trace(A^k)| >= 10^(k+1) >= 10^4; fraction answers have\n  reduced denominator >= 1000 (so NO fraction with denominator < 1000 can equal one -\n  a reduced form has the minimal denominator). Small/trivial answers are impossible,\n  not just unlikely; fractions are compared by value, so unreduced forms of the true\n  answer still score 1.0.\n- **Deterministic, seed-honest minting.** Per-instance RNG seeds are derived as\n  (seed << 64) + i, so no two (seed, index) pairs ever reuse a seed value; shared\n  instances across seeds would additionally require a random.Random stream collision\n  (astronomically unlikely; adjacent-seed disjointness is tested). Minting is\n  deterministic in\n  the seed: fresh=True (or count beyond the bundle) recomputes instances rather than\n  loading the bundle, and reproduces the bundled instances when the seed is the\n  default. To get instances disjoint from the public split, pass a NON-DEFAULT seed.\n\n**Measured numbers** (default bundle: seed 20260819, 48 instances, 12 per task type):\n\n| quantity | measured |\n|---|---|\n| charpoly: |constant coefficient| | min 1,444 / max 788,460 |\n| inv_entry: reduced denominator | min 1,025 / max 116,902 |\n| power_trace: |trace| | min 102,895 / max 3,705,318 |\n| solve_entry: reduced denominator | min 1,505 / max 136,365 |\n| random attack (type-appropriate guesses: monic int vectors, wide-range ints, random fractions) | **0 / 240,000** |\n| exhaustive small-answer attack (all ints |g| <= 9999; all fractions |num| <= 99, den <= 99) | **0 / 712,812** (guaranteed 0 by the mint floors) |\n| mint 48 instances | 0.032 s |\n| verify one answer (incl. ground-truth recompute) | ~0.21 ms |\n\nEvery number above is reproduced by `python scripts_baseline.py` (stdlib only, fixed\nattack RNG seed). The test suite (`tests/test_env.py`, 20 tests) runs smaller, faster\nvariants of the same attacks on fresh seeds (80,000 random guesses; a fully exhaustive\n|g| <= 9999 integer sweep; an exhaustive small-fraction sweep) plus: true answers for\nevery type, per-coefficient perturbation rejection,\noff-by-one/sign-flip rejection, unreduced-fraction acceptance, garbage/float/oversized\nanswer rejection (incl. a >4300-digit crash regression), cross-algorithm agreement,\nknown charpoly values, mint floors, determinism, adjacent-seed disjointness, seed/count\nhonesty, bundle reproducibility, prompt-leak regression (labels absent from both the\nprompt and the info column), non-ASCII digit rejection, numpy integer-scalar\nacceptance, small-n mint guards, a numpy cross-check, and end-to-end scoring through\nthe real verifiers rubric pipeline.\n\n**Contamination note (read before benchmarking).** The default split (seed 20260819)\nis public by design - it ships in this package with its labels, and the mint stream\nfor the default seed is reproducible by anyone. Treat it as a train/demo split: a\nmodel that has seen this package can score 1.0 on it by memorization. For\nuncontaminated evaluation, mint a private split with your own seed:\n`load_environment(seed=<private>, count=..., fresh=True)`. Distinct seeds use\ndisjoint per-instance RNG seed values by construction, so a shared instance would\nrequire an RNG stream collision - astronomically unlikely.\n\n**Usage.**\n```python\nfrom numpy_scipy_exact import load_environment\nenv = load_environment()                      # bundled 48 instances\nenv = load_environment(seed=7, count=100, fresh=True)   # private split, disjoint from the bundle\n```\nAnswer formats are stated in each prompt (a JSON integer array, a JSON [num, den]\npair, or a single integer; ASCII digits). The parser takes the last well-formed\ncandidate in the completion, so models may reason freely before answering.\n\n**Graded signal.** Binary 1.0 / 0.0 by design: exact answers only. Nearly-right\nvalues (one coefficient off, an off-by-one trace) indicate a wrong computation, not\npartial understanding.\n\nBuilt by Half Ounce Research (halfounce.io) - certified computation, published record.\n","encoding":"utf-8","truncated":false,"total_bytes":5888},"status":null}