{"data":{"kind":"file","path":"README.md","version_id":"rxtghpura98f0m2ifjesjwy5","entry":{"name":"README.md","path":"README.md","is_directory":false,"size":7039,"modified_at":"2026-08-09T16:37:52.788000","content_hash":"d87e247755a03f60274c222c50b9678bf59f464b10184aa4689f898fcb79f30f"},"entries":[],"content":"# bishop-env\n\nRL environment for **exact pattern recognition** on the topics of *Pattern Recognition and\nMachine Learning* (Bishop): probability and Bayes, information theory, linear regression and\nridge, naive Bayes, Bernoulli mixtures and EM, k-means, conjugate priors, and d-separation in\ndirected graphical models.\n\n- **Tasks:** 43 across 7 categories\n- **Dataset:** [`bishop-tasks-v1`](https://huggingface.co/datasets/eltociear/bishop-tasks-v1)\n- **Reward:** binary, from an exact comparison. No LLM judge, no network, no clock.\n- **Dependencies in the sandbox:** none, and numpy is deliberately absent.\n\n```bash\nprime env install eltociear/bishop-env\n```\n\n## What makes this environment exact\n\nEvery answer is an integer or an exact rational returned as `[numerator, denominator]`. There\nis not a float anywhere, and `numpy` is not installed in the sandbox on purpose. A\nresponsibility, a posterior and a mutual information are all ratios of small numbers; grading\nthem with a tolerance lets a wrong derivation that happens to land nearby score full marks.\n\n**The trap the environment is built around.** An entropy is exact only if every probability it\ntouches is a power of two — *including the marginals, which you did not choose*. It is easy to\nwrite down a joint whose cells are all dyadic and not notice that a marginal came out 5/8, at\nwhich point `log2` is irrational and the whole exactness argument has quietly collapsed on\nthat one task. A sibling environment in this series shipped precisely that defect.\n\nSo the joint here is constructed so that every marginal and every conditional is dyadic too:\n\n|       | Y=0 | Y=1 | P(X) |\n|---|---|---|---|\n| **X=0** | 1/4 | 1/4 | 1/2 |\n| **X=1** | 1/4 | 0   | 1/4 |\n| **X=2** | 0   | 1/4 | 1/4 |\n| **P(Y)** | 1/2 | 1/2 | |\n\nDependent (P(Y=0 | X=1) = 1, not 1/2), every cell dyadic, both marginals dyadic, therefore\nevery conditional dyadic. H(X) = 3/2, H(Y) = 1, H(X,Y) = 2, I(X;Y) = 1/2 — all exact. And\n`log2_exact` in the builder *refuses* any argument that is not a power of two, so the dataset\ncannot be built if that ever stops being true.\n\n## Categories\n\n| category | tasks | what it asks for |\n|---|---|---|\n| `probability` | 6 | marginals, conditionals, independence, Bayes on a diagnostic test |\n| `information-theory` | 6 | entropy, conditional entropy both ways, mutual information, KL in both directions, both cross entropies |\n| `regression` | 7 | normal equations, residuals and their orthogonality, ridge, an exact quadratic fit |\n| `classification` | 5 | naive Bayes with Laplace smoothing: priors, likelihoods, posteriors, the decision and the odds |\n| `bayesian-inference` | 6 | Beta–Bernoulli, Dirichlet–multinomial, and a Gaussian with known variance |\n| `mixtures-em` | 8 | Bernoulli-mixture responsibilities, a full M-step, and k-means with its distortion |\n| `graphical-models` | 5 | d-separation, descendants, Markov blanket, and the parameter count a factorisation buys |\n\n## How the answer keys are built\n\nEvery task is `(deterministic inputs, instruction, reference solution)`, and the expected\noutput is **computed by executing the reference** — never written by hand. `--verify` then\nre-checks every task independently: it runs, is deterministic across two fresh executions,\nreturns JSON-safe integers only (no floats, no bools, no strings), survives the serialisation\nround-trip, repeats no row inside its own answer, and does not duplicate another task's answer.\n\nWherever a second independent route to a number exists, the builder computes it both ways and\n**refuses to build if they disagree**:\n\n- the chain rule `H(X,Y) = H(X) + H(Y|X)` and `= H(Y) + H(X|Y)`, with the conditional\n  entropies computed as averages rather than as differences\n- all three forms of mutual information\n- Bayes' theorem in both directions\n- the least-squares residual against orthogonality to every column of the design matrix\n- the ridge solution against its own normal equations\n- the quadratic fit against exact interpolation\n- the Beta posterior predictive against the posterior mean\n- two different textbook formulas for the Gaussian posterior mean\n- Lloyd's algorithm never increasing its distortion\n- **d-separation answered twice, by path enumeration *and* by moralising the ancestral\n  subgraph** — two unrelated algorithms that are provably equivalent, which is the right check\n  for a collider rule that is easy to state and easy to implement backwards\n\n## What the verifier actually caught\n\nSeven real defects, in this file, before publication — and every one of them was found by\n*dumping the answer keys and reading them*, not by any check that existed at the time. They are\nall the same shape: **a task that asks for two quantities which are provably equal gives away\nhalf of its own answer, and nothing about it looks wrong from the outside.**\n\n| where | what it was |\n|---|---|\n| entropy of P and Q | with four dyadic outcomes there are only two possible multisets of probabilities, so any non-uniform Q is a **permutation** of P — and H(P) = H(Q). Five outcomes breaks it |\n| the two cross entropies | asked for `-Σ P log Q` and for `H(P) + KL(P‖Q)`, which are the same number by definition |\n| the chain rule task | asked for `H(X,Y)` and for `H(X) + H(Y|X)` — one number, twice |\n| Beta–Bernoulli | asked for the posterior mean and the posterior predictive, which are identically equal for this conjugate pair |\n| the mixture data | two of the three \"data points\" had the same number of ones, and a Bernoulli likelihood over iid bits depends only on that count — so they were one point, and their responsibilities came out identical |\n| k-means | the point set was symmetric about `y = x`, so every centroid had equal coordinates and half of each answer was free |\n| factorisation task | duplicated the node and edge counts already asked for by the task before it |\n\nEach is now an assertion in `_self_check`, so none can silently return; and `--verify` gained a\nrule that no answer may repeat a row inside itself, which is how the duplicated data point hid.\n\n## Provenance\n\n**Original problems, not the book's exercises.** Nothing is copied. The distributions, design\nmatrices, counts and graph are invented here. That matters in this subject: Bishop's worked\nexamples and figures are reproduced in thousands of lecture notes and course solution sets, so\ntheir numbers are memorisable rather than computable.\n\n## Known limitation, stated rather than buried\n\nThe Docker **sandbox rollout has not been executed** — that needs a Docker runtime and an\ninference provider key, neither available where this was authored. The environment mirrors the\nstructure of `polars_env`, which this program has already accepted, and imports cleanly against\n`verifiers`. What **is** fully verified is the dataset, the exact comparator and the grading\npath. What remains unexercised is the sandbox transport itself: `docker run`, and the model's\ncode executing inside it.\n\n```bash\npython environments/bishop_env/build_tasks.py --verify\n```\n","encoding":"utf-8","truncated":false,"total_bytes":7039},"status":null}