ppvm_tableau/lib.rs
1// SPDX-FileCopyrightText: 2026 The PPVM Authors
2// SPDX-License-Identifier: Apache-2.0
3
4//! Generalized stabilizer-tableau simulator built on top of the ppvm core
5//! crates (`ppvm-traits` and `ppvm-pauli-word`).
6//!
7//! Provides a forward-evolving state representation using the stabilizer
8//! formalism, extended to non-Clifford gates by tracking a sparse vector
9//! of coefficients indexed over bitstrings. The two top-level types are
10//! [`data::Tableau`] (pure Clifford) and [`data::GeneralizedTableau`]
11//! (Clifford + non-Clifford with sparse coefficient tracking).
12//!
13//! # Quick example
14//!
15//! Prepare a Bell pair and verify the two measurements are perfectly
16//! correlated:
17//!
18//! ```
19//! use ppvm_tableau::prelude::*;
20//! use ppvm_pauli_sum::config::fxhash::ByteF64;
21//!
22//! let mut tab: GeneralizedTableau<ByteF64<1>> =
23//! GeneralizedTableau::new_with_seed(2, 1e-12, 0);
24//! tab.h(0);
25//! tab.cnot(0, 1);
26//!
27//! let r0 = LossyMeasure::measure(&mut tab, 0);
28//! let r1 = LossyMeasure::measure(&mut tab, 1);
29//! assert_eq!(r0, r1);
30//! ```
31//!
32//! ## Data-parallel / GPU-offloadable surface
33//!
34//! A handful of primitives in this crate operate on whole contiguous arrays
35//! at once, with no per-element host closures — the shape a thread pool or a
36//! CUDA kernel would want:
37//!
38//! - Every tableau row ([`PhasedPauliWord`](ppvm_pauli_word::phase::PhasedPauliWord))
39//! stores its Pauli word as fixed-size `bytemuck::Pod` integer bit-planes
40//! (`xbits`/`zbits`, backed by `[u8; N]` or `[u64; N]`), reachable as
41//! contiguous raw integer slices via `as_raw_slice`/`as_raw_mut_slice` —
42//! plain-old-data, not a bit-addressed abstraction.
43//! - The single-gate Clifford path
44//! (`crates/ppvm-tableau/src/gates/clifford.rs`) has one shared
45//! implementation per gate that loops over rows operating directly on
46//! those raw integer slices with a hoisted word-index/bit/mask, bypassing
47//! `bitvec`'s per-bit bounds checks inside the loop. Both
48//! [`data::Tableau`] and [`data::GeneralizedTableau`] (via the
49//! `impl_generalized_tableau_clifford*` macros) funnel through it.
50//! - The batch path does **not** share that implementation. The
51//! [`CliffordBatch`](ppvm_traits::traits::CliffordBatch) methods (`x_many`,
52//! `cz_many`, …) each carry their own raw-plane loop that fuses many gates
53//! into a single pass over the rows, and `Tableau` and
54//! `GeneralizedTableau` have separate `CliffordBatch` impls (the latter
55//! via the `impl_gen_tableau_batch_*` macros). Anyone porting the Clifford
56//! layer to a thread pool or a CUDA kernel has to cover both the
57//! single-gate implementation and these batch bodies.
58//! - The batch methods take arbitrary index lists (`&[usize]`,
59//! `&[(usize, usize)]`). [`data::GeneralizedTableau::cz_block`] /
60//! `cz_block_pairs` / `cz_block_pairs_cross_word` are the
61//! contiguous-block variants: they apply CZ to a whole contiguous range
62//! of qubits as bulk masked slice operations, which is the layout a
63//! kernel can address without an index indirection.
64//! - `GeneralizedTableau::branch_with_coefficients` (crate-private) transforms
65//! the whole coefficient array in one pass. Its `#[cfg(feature = "rayon")]`
66//! path (`branch_coefficients_parallel`, gated by `RAYON_COEFF_THRESHOLD`)
67//! computes the per-entry branch/non-branch coefficient math in parallel,
68//! with no shared mutable state — the accumulation of those results into
69//! the coefficient map afterwards remains sequential.
70
71/// Core [`Tableau`](data::Tableau) and
72/// [`GeneralizedTableau`](data::GeneralizedTableau) types.
73pub mod data;
74/// `Display` implementations for tableau types.
75pub mod display;
76/// Pauli-string expectation values and pattern traces.
77pub mod expectation;
78/// Gate implementations (Clifford, T, rotations).
79pub mod gates;
80/// Z-basis measurement, including loss-aware variants.
81pub mod measure;
82/// Per-qubit [`QubitStatus`](qubit_status::QubitStatus) relative to the
83/// computational subspace.
84pub mod qubit_status;
85
86pub mod measure_all;
87
88/// Noise channels: depolarizing, Pauli error, loss.
89pub mod noise;
90/// [`SparseVector`](sparsevec::SparseVector) trait and implementations.
91pub mod sparsevec;
92/// [`TableauIndex`](tableau_index::TableauIndex) — abstraction over
93/// the bitstring index type (`usize`, `u128`, `U256`, …).
94pub mod tableau_index;
95/// [`TableauLike`](tableau_like::TableauLike) — shared trait for
96/// stabilizer-tableau backends.
97pub mod tableau_like;
98
99/// Convenience re-exports for downstream code.
100pub mod prelude {
101 pub use crate::data::{GeneralizedTableau, Tableau};
102 pub use crate::qubit_status::QubitStatus;
103 pub use crate::sparsevec::SparseVector;
104 pub use crate::tableau_index::TableauIndex;
105 pub use crate::tableau_like::TableauLike;
106 pub use ppvm_pauli_sum::prelude::*;
107}