Repository navigation
facts.py, Facts.lean and the audit read a product of two constants and a product atom times a constant alike - #185
Conversation
…d a product atom times a constant alike
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ddec270dfc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| return ZERO, j * k | ||
| name, n = (x, k) if y == ZERO and x and not j else (y, j) if x == ZERO and y and not k else ("", 0) | ||
| return (f"{name}*{n}", 0) if name and n > 0 else None | ||
| return (f"{name}*{n}", 0) if name and "*" not in name and n > 0 else None |
There was a problem hiding this comment.
Preserve lane windows that use nested product atoms
When a lane is guarded by b * 4 <= (b * 4) * 2 && (b * 4) * 2 < b * 4 + 4 plus the normal extent check, the parent compiler uses the b*4*2 term and those facts to show that out[(b * 4) * 2] lies in lane b's stride-4 block. Filtering the term here leaves facts.window without that lower bound, so this previously accepted, race-free write is now refused with E-PARALLEL-RACE. This is an accepted-program change despite the compatibility claim; preserve a representation for lane-window reasoning or add the required language-change coverage and documentation.
AGENTS.md reference: AGENTS.md:L128-L136
Useful? React with 👍 / 👎.
Summary
compiler/check/facts.py,proofs/Cairn/Facts.leanand the audit inverify/elision.pynow read a product the same way: two constants multiply on all three sides, and a product atom times a constant names nothing on any. Every guard the facts propose to leave out over such a product is now one Lean proves and the audit accepts, where before the audit refused those proposals and kept the guard. The Lean differential generates both shapes, and asks a ninth decision that only the two sides' exact terms decide.Motivation
Part of #2, following #171. The work behind #181, which timed #171 and #173 on the GH200, found that
facts.py:timesfolds a constant times a constant (2 * 3is 6) and names a product atom times a constant ((k * 4) * 2as the atomk*4*2), whileFacts.lean'sexactreturns nothing for either, andtools/checks/differential_facts.pynever generated either shape, so the comparison that ties the proof to the Python could not see the gap.No wrong guard reached emitted code: the audit's own
exactagreed with Lean, so it refused every proposal resting on either shape and kept the guard. But each such proposal became a refusal that the receipt counted underrefused_discharges(x[2 * 3]in a view of 8,let q = n / (2 * 4)abovex[k * 8], andif k * 4 * 2 < n { return x[k * 4 * 2]; }each had one), and the Python rule was claimed to be what Lean proves when it was not.I extended Lean for the first shape and narrowed Python for the second. Folding two constants is sound and used beyond guards (
check/places.pycompares part bounds made of constants throughfacts.exact), so dropping it from Python would change which parts leases see as equal. Naming(k * 4) * 2as the one atomk*8would also be sound, and I tried it first, but the same term feeds the lane rule'swindow, which would then placeout[b * 4 * 2 + j]in laneb's block. It refuses that today (E-PARALLEL-RACE), so accepting it is a language change and belongs in a change of its own.Changes
compiler/check/facts.py):timesgives no term for a product atom times a constant; two constants still multiply.verify/elision.py): the audit'sexactmultiplies two constants, asfacts.pyandFacts.leando; it already gave no term for a product atom times a constant.proofs/Cairn/Facts.lean):exactmultiplies two constants, andexact_soundandexact_mul, hencemul_sound, cover the case. No theorem statement changes; the certificates are unaffected (export_lean_certificates.py --check: up to date).tools/checks/differential_facts.py): products of two constants and products of a product atom among the generated expressions and as the sides of a*; the quotient's multiplex5 * Cwritten four ways; a ninth decision, a product minus itself.tools/checks/differential_guards.py): divisors(2 * 4)and(2 * 128), and a multiple below a quotient sometimes writtenj * 1 * C.test_differential_facts.pyplants the two old readings intimesand requires the comparison to report each;test_elision.pyrequires the three programs above to have no refused discharge, and plants two slips intimesthat must reach no emitted program;test_established.pypins the guardsx[2 * 3]and the nested product keep.docs/verification.md): the guard-elision section says how a product is read, and cites the new differential run.evidence/v1_2/facts/): the Lean differential, the emission identity and the guard differential of this change, in a new section of the README.Behaviour and compatibility
No program is accepted or refused differently, and no diagnostic changes.
tools/checks/emission_identity.py --normalize guardsover 2,289 programs, against the compiler of fd64dd2 on the same programs: none changed otherwise, none emits more guards, and 4 emit fewer (16,071 guards in all to 16,066). Three are the tests added here; the fourth, intests/language/test_layouts.py, loses the guard on16 * 18 - 2. No example,stdmodule or docs block changed. A program that writes(k * 4) * 2gets no fact from it, as before in effect, since the audit refused every proposal that rested on one.Testing
All on the GH200 host (aarch64, Ubuntu 22.04, clang++ 14, g++ 11.4, Lean 4.34.0), shared with other agents' suites. The six failures are the g++ ThreadSanitizer tests that fail on this machine at main (GCC 11's libtsan fails a CHECK on this kernel). The guard differential agreed on 1,869 functions and 179,424 cases per compiler, clang++ and g++ both under AddressSanitizer and UndefinedBehaviorSanitizer. After merging main (4d495bf), lint and the touched test files (335 tests) passed again. The new tests fail against main's compiler where they should: the three programs above each have a refused discharge there, and
x[2 * 3]keeps its index guard. Nothing ran on the GPU.Evidence and claims
exact_sound,exact_mulandmul_soundover the model with two constants multiplied. The model is still transliterated, not extracted, and the differential samples the agreement: 20,000 inputs agreed (facts_differential_products.json), and the two old readings are each reported within 300.guards_differential_products.json).Performance
Not measured. Five guards go from the four programs above: three over constants, which the C++ compiler folds anyway, and in a test the multiply and the index of
x[k * 8]belowlet q = n / (2 * 4).Checklist
make editors,make docs): nothing they generate from changed