perf(PauliMatrices): evaluate Levi-Civita components as a product of signs - #1664
Conversation
|
Thank you for this pull-request (PR). If this is your first PR, welcome to the community! Below is what will happen next. Please read carefully if you are not familiar with the process. You may open other PRs while this one is being reviewed, and can stack PRs on top of each other, so don't let these steps slow you down.
Tip: The easiest way to get have a fast review is to submit a PR that is small and self-contained, and has clear documentation explaining why things are the way they are in your chages. If you have any problems or questions, please reach out to the community on the Zulip. |
|
Highlighting the following: this PR will conflict will the version bump in #1661, and the current changes are based on the proposed change there. Either order of merging works, but I think merging this first helps with performance (I forked the #1661 branch and it takes painfully long to build the file) |
…i identities The three-Pauli identities (2.26) and (2.27) are proved by `decide +kernel` over all tensor components. The components of `ε4ℂ` were given by `generalizedKroneckerDelta`, a 4x4 determinant, which the kernel evaluated 1024 times per lemma as a sum over permutations with `Equiv.Perm.sign`. - Add `leviCivitaSymbolProd`, the product over pairs `i < j` of the sign of `g j - g i`, and `leviCivitaSymbol_eq_leviCivitaSymbolProd` (any `Fin n`, via `Equiv.Perm.sign_eq_prod_prod_Ioi`). - Add `leviCivita_eq_ofRat_prod` stating the components of `ε4ℂ` with it, and use it in the two identities. - In the two identities rewrite with `I_mul_toComplexNum` only inside the last summand instead of across the whole goal. Identity (2.27) was at the default `maxHeartbeats` limit. Kernel `decide`: 289M -> 73M and 301M -> 78M heartbeats. No statement changed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…auliDual The component proof of `leviCivita_mul_pauliDual` (#1661) evaluates `ε4ℂ` 2048 times under `decide +kernel`. With `leviCivita_eq_ofRat` each evaluation is a 4x4 determinant; `leviCivita_eq_ofRat_prod` makes it a product of signs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ut a definition Remove the definition `leviCivitaSymbolProd`. The closed form is now the right-hand side of `leviCivitaSymbol_eq_prod_prod_Ioi` (renamed from `leviCivitaSymbol_eq_leviCivitaSymbolProd`), and `leviCivita_eq_ofRat_prod` states the components of `ε4ℂ` with the product written out. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1b2f70a to
75672b4
Compare
|
After the version bump my 16GB RAM PC simply cannot build Relativity/PauliMatrices/Relations.lean on master (stuck at the decide steps), so I think this change is a massive performance improvement. A related question: is there any reason why you introduced |
|
I think if Mathlib GaussianInt works, then we should use that instead of RatComplexNum. Is this up to date with the bump? If so, I'll approve it, and I'll leave you to merge it. |
In a heartbeat profile of all 585 files on master, the three most expensive files are
WickContraction/TimeCond.lean(1,756k),WickContraction/Join.lean(1,241k) andPauliMatrices/Relations.lean(1,185k). The next file is at 705k, and a typical file is at 3k–40k. They also sit at the ends of the two longest import chains, so they bound the parallel build time. #1662 deals with the two Wick files; this PR deals withRelations.lean.The three-Pauli identities are proved by
decide +kernelover all components.leviCivita_eq_ofRatgives the components ofε4ℂas ageneralizedKroneckerDelta, i.e. a 4×4 determinant, which the kernel evaluates through permutation sums. This PR adds the closed form∏_{i<j} sign (g j - g i)for the Levi-Civita symbol onFin nand uses it for the components instead. Evaluating all 256 components ofε4ℂcosts the kernel 40.3M heartbeats in the determinant form and 4.3M in the product form. The PR also restricts tworws that traversed the whole goal to the summand they apply to.Added:
leviCivitaSymbolProd(def) andleviCivitaSymbol_eq_leviCivitaSymbolProd, inMathematics/LeviCivita/Basic.leanleviCivita_eq_ofRat_prod, inTensors/LeviCivita/Complex.leanNothing is removed and no statement changes. Three proofs change:
pauliContr_mul_pauliContrDown_mul_pauliContr,pauliContrDown_mul_pauliContr_mul_pauliContrDownandleviCivita_mul_pauliDual.Relations.lean, thousand heartbeatspauliContr_mul_pauliContrDown_mul_pauliContrpauliContrDown_mul_pauliContr_mul_pauliContrDownleviCivita_mul_pauliDualRelation to #1661. The current proof of
leviCivita_mul_pauliDualhits a kernel timeout on v4.34, and #1661 (commit 191842c) replaces it with a proof bydecide +kernelover components, usingleviCivita_eq_ofRat. That proof evaluatesε4ℂ2048 times (256 components × the contracted index × both sides), and every evaluation is a determinant: by the figures above, about 320M heartbeats of kernel work forε4ℂalone, which would make this small lemma as expensive as one of the three-Pauli identities before this PR. This PR takes the same proof and states it withleviCivita_eq_ofRat_prod, which brings that part down to about 34M; the whole lemma then measures 100,824k. That is the last row of the table. It is a regression against the present proof, accepted because the present proof does not survive v4.34. I have checked that this branch builds on v4.34 when merged onto #1661. The two PRs will conflict in this one proof; the resolution is to keep theleviCivita_eq_ofRat_prodversion, after which 191842c is no longer needed.Disclaimer: I instructed Claude to investigate and find opportunities to speed up build times; the changes look reasonable to me.
🤖 Generated with Claude Code