Translation symmetry: TranslationGroup + orbit-representative Pauli-sum merging#180
Open
AlexSchuckert wants to merge 2 commits into
Open
Translation symmetry: TranslationGroup + orbit-representative Pauli-sum merging#180AlexSchuckert wants to merge 2 commits into
AlexSchuckert wants to merge 2 commits into
Conversation
…erging TranslationGroup (finite abelian permutation groups: 1D chains, 2D/3D tori, multi-leg ladders, arbitrary generators) with lex-min orbit canonicalization, shift counters, and momentum-sector characters. Pauli-sum merging in both sectors: canonicalize_pauli_sum / symmetry_merge_pauli_sum (k=0, real coefficients) and canonicalize_pauli_sum_complex (k≠0, character-weighted projection, 1/|G| normalization), plus check_momentum_sector to validate an input before projecting. Following Teng, Chang, Rudolph & Holmes (arXiv:2512.12094). Split 1/4 of the CTPP work (see PR body for the stack); full development history on branch continuous-time-pauli-propagation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new Rust-only symmetry layer to ppvm-pauli-sum for translation-invariant (and momentum-resolved) Pauli-sum canonicalization/merging, intended to support upcoming continuous-time Pauli propagation work (#178 split).
Changes:
- Introduces
ppvm_pauli_sum::symmetrywithTranslationGroupplus orbit-canonicalization utilities. - Adds real (
k=0) and complex/momentum-sector merging/canonicalization helpers, along with momentum-sector validation. - Exposes the new module from
ppvm-pauli-sum’s public API and adds a comprehensive test suite for canonicalization/merge behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| crates/ppvm-pauli-sum/src/symmetry.rs | New symmetry module: translation group model, orbit canonicalization, (momentum) merging, and tests. |
| crates/ppvm-pauli-sum/src/lib.rs | Exposes the new symmetry module publicly. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+125
to
+129
| Self { | ||
| n_qubits, | ||
| perms, | ||
| orders, | ||
| } |
Comment on lines
+220
to
+223
| /// Total group order: `Π orders[g]`. | ||
| pub fn order(&self) -> usize { | ||
| self.orders.iter().map(|&o| o as usize).product() | ||
| } |
Comment on lines
+495
to
+503
| let inv_g: f64 = 1.0 / (group.order() as f64); | ||
| let mut merged: FxHashMap<PauliWord<A, S, R>, Complex<f64>> = | ||
| FxHashMap::with_capacity_and_hasher(basis.len(), Default::default()); | ||
| for (w, &c) in basis.iter().zip(coeffs.iter()) { | ||
| let (rep, cnt) = group.canonicalize_with_shift(w); | ||
| let chi = group.character(k_modes, &cnt); | ||
| let contrib = inv_g * chi * c; | ||
| *merged.entry(rep).or_insert(Complex::new(0.0, 0.0)) += contrib; | ||
| } |
Comment on lines
+475
to
+477
| /// For the `k_modes = [0, 0, …]` (trivial) sector this reduces to plain | ||
| /// [`canonicalize_pauli_sum`] (real coefficients work, but on complex | ||
| /// input the result is complex with vanishing imaginary part). |
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment on lines
+130
to
+133
| pub fn chain_1d(n: usize) -> Self { | ||
| let perm: Vec<u32> = (0..n).map(|q| ((q + 1) % n) as u32).collect(); | ||
| Self::from_generators(n, vec![perm], vec![n as u32]) | ||
| } |
Comment on lines
+137
to
+138
| pub fn torus_2d(lx: usize, ly: usize) -> Self { | ||
| let n = lx * ly; |
Comment on lines
+156
to
+157
| pub fn torus_3d(lx: usize, ly: usize, lz: usize) -> Self { | ||
| let n = lx * ly * lz; |
Comment on lines
+194
to
+195
| pub fn ladder(l: usize, n_legs: usize) -> Self { | ||
| let n = l * n_legs; |
Comment on lines
+297
to
+300
| for &o in &self.orders { | ||
| counters.push((rem as u32) % o); | ||
| rem /= o as usize; | ||
| } |
Comment on lines
+347
to
+350
| for &o in &self.orders { | ||
| counter.push((rem as u32) % o); | ||
| rem /= o as usize; | ||
| } |
Comment on lines
+407
to
+409
| for (g, &o) in self.orders.iter().enumerate() { | ||
| let c = (rem as u32) % o; | ||
| rem /= o as usize; |
Comment on lines
+472
to
+474
| /// For the `k_modes = [0, 0, …]` (trivial) sector this reduces to plain | ||
| /// [`canonicalize_pauli_sum`] (real coefficients work, but on complex | ||
| /// input the result is complex with vanishing imaginary part). |
Comment on lines
+101
to
+125
| for (g, perm) in perms.iter().enumerate() { | ||
| assert_eq!( | ||
| perm.len(), | ||
| n_qubits, | ||
| "generator {g} permutation has length {} != n_qubits {n_qubits}", | ||
| perm.len() | ||
| ); | ||
| let mut seen = vec![false; n_qubits]; | ||
| for &p in perm { | ||
| assert!( | ||
| (p as usize) < n_qubits, | ||
| "generator {g} maps to out-of-range position {p}" | ||
| ); | ||
| assert!( | ||
| !seen[p as usize], | ||
| "generator {g} is not a permutation (duplicate target {p})" | ||
| ); | ||
| seen[p as usize] = true; | ||
| } | ||
| } | ||
| Self { | ||
| n_qubits, | ||
| perms, | ||
| orders, | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR 1 of 4 splitting #178 into reviewable chunks (this → CTPP core → symmetry-merged evolution → ledgers). Full development history: branch
continuous-time-pauli-propagation.Adds
ppvm_pauli_sum::symmetry(pure Rust, no new dependencies):TranslationGroup: finite abelian permutation groups — 1D chains, 2D/3D tori, multi-leg ladders, or arbitrary generator lists — with lex-min orbit canonicalization, shift counters, and momentum-sector charactersχ_k(g).canonicalize_pauli_sum(Vec-pair form used by the upcoming adaptive evolution) andsymmetry_merge_pauli_sum(PauliSumform). Preserves all G-invariant expectation values for G-commuting dynamics (Theorem 1 of Teng, Chang, Rudolph & Holmes, arXiv:2512.12094).canonicalize_pauli_sum_complex(character-weighted projection with 1/|G| normalization) andcheck_momentum_sectorto validate inputs before projecting (silent projection discards physics).Tests: canonicalization/orbit properties on chains, tori, ladders; merge correctness; momentum-eigenstate round trips; a Trotter end-to-end check that per-step merging matches merge-at-end in the dt → 0 limit.
🤖 Generated with Claude Code