ppvm / Pauli propagation & tableau simulation
API contents

Python — ppvm

Rust

ppvm-sym
Generated reference

API Reference

Python items 116 Rust items 110 Generated

Python ppvm

Pythonic wrapper around the native Rust runtime. All items below live under the ppvm top-level module.

generalized_tableau

class GeneralizedTableau ppvm.generalized_tableau.GeneralizedTableau
class GeneralizedTableau

Generalized stabilizer tableau for quantum circuit simulation.

Full docstring

Generalized stabilizer tableau for quantum circuit simulation.

Represents an arbitrary quantum state in the basis spanned by the stabilizer tableau. It supports Clifford gates, arbitrary single- and two-qubit rotations, noise channels, and mid-circuit measurement. The coefficient vector grows exponentially with the number of non-Clifford operations applied.

class MeasurementResult ppvm.generalized_tableau.MeasurementResult
class MeasurementResult

A measurement outcome, which accounts for a qubit being potentially lost.

function sample_stim ppvm.generalized_tableau.sample_stim
def sample_stim(prog: StimProgram, n_qubits: int, min_abs_coeff: float = 1e-10, num_shots: int = 1, seed = None)

Multi-shot sampling — module-level alias for GeneralizedTableau.sample.

Full docstring

Multi-shot sampling — module-level alias for GeneralizedTableau.sample.

Shots are sampled in parallel across CPU cores with the GIL released; see GeneralizedTableau.sample for seeding and RAYON_NUM_THREADS.

method asymmetric_loss_channel ppvm.generalized_tableau.GeneralizedTableau.asymmetric_loss_channel
asymmetric_loss_channel(addr0: int, p0: float, p1: float) -> None

Apply a state-dependent ("asymmetric") loss channel to a qubit.

Full docstring

Apply a state-dependent ("asymmetric") loss channel to a qubit.

The qubit is lost from |0> with probability p0 and from |1> with probability p1, so the total loss probability depends on the current populations: p_tot = p0 * (1 + <Z>)/2 + p1 * (1 - <Z>)/2.

.. note:: This is the trajectory approximation of the loss channel. It is exact for the loss statistics and in the symmetric limit p0 == p1 (where it matches loss_channel), but it does not apply the survival back-action, so for p0 != p1 the surviving qubit's state is left unchanged. See issue #39.

Parameters
addr0 int

The index of the target qubit.

p0 float

The loss probability from the |0> state.

p1 float

The loss probability from the |1> state.

method coefficients ppvm.generalized_tableau.GeneralizedTableau.coefficients
coefficients()

Return a snapshot of the sparse coefficient vector.

Full docstring

Return a snapshot of the sparse coefficient vector.

The tableau represents the state as a sparse superposition over the basis states of its stabilizer frame. This returns that vector as a mapping from basis-state index to complex amplitude.

The returned dict is a copy: mutating it does not affect the tableau's internal state.

Returns

A dict mapping each populated basis-state index to its complex amplitude.

method current_measurement_record ppvm.generalized_tableau.GeneralizedTableau.current_measurement_record
current_measurement_record()

Return all measurement outcomes recorded so far.

Full docstring

Return all measurement outcomes recorded so far.

Returns

A list of MeasurementResult outcomes in measurement order.

method fork ppvm.generalized_tableau.GeneralizedTableau.fork
fork(seed = None) -> GeneralizedTableau

Fork this tableau into an independent simulation branch.

Full docstring

Fork this tableau into an independent simulation branch.

Clones all quantum state but reinitializes the RNG, so the returned tableau evolves independently from this one. If seed is provided the new RNG is seeded deterministically; otherwise it is seeded from OS entropy.

Use this when branching a simulation into independent trajectories. To preserve the RNG state exactly (e.g. for checkpointing), use copy.copy() or copy.deepcopy() instead.

Parameters
seed

Optional integer seed for the forked RNG.

Returns
GeneralizedTableau

A new GeneralizedTableau with the same quantum state but an independent RNG.

method is_lost ppvm.generalized_tableau.GeneralizedTableau.is_lost
is_lost(addr0: int) -> bool

Check whether a qubit has been lost.

Full docstring

Check whether a qubit has been lost.

Parameters
addr0 int

The index of the qubit.

Returns
bool

True if the qubit is lost, False otherwise.

method loss_values ppvm.generalized_tableau.GeneralizedTableau.loss_values
loss_values()

Return the loss state of all qubits.

Full docstring

Return the loss state of all qubits.

Returns

A list of booleans of length n_qubits, where each entry is True if the corresponding qubit is lost and False otherwise.

method measure ppvm.generalized_tableau.GeneralizedTableau.measure
measure(addr0: int) -> MeasurementResult

Measure the specified qubit in the Z basis.

Full docstring

Measure the specified qubit in the Z basis.

Parameters
addr0 int

The index of the target qubit.

Returns
MeasurementResult

The measurement outcome as a MeasurementResult, which is LOST if the qubit has been lost, ZERO or ONE otherwise.

method measure_many ppvm.generalized_tableau.GeneralizedTableau.measure_many
measure_many(targets = ())

Measure several qubits in the Z basis.

Full docstring

Measure several qubits in the Z basis.

Parameters
*targets

The indices of the target qubits.

Returns

A list of MeasurementResult outcomes, one per target.

method num_coefficients ppvm.generalized_tableau.GeneralizedTableau.num_coefficients
num_coefficients() -> int

Return the number of branches in the coefficient vector.

Full docstring

Return the number of branches in the coefficient vector.

This is the number of entries in the dict returned by coefficients, computed without materializing it.

Returns
int

The count of populated entries in the sparse coefficient vector.

method reset ppvm.generalized_tableau.GeneralizedTableau.reset
reset(targets = ()) -> None

Reset each target qubit to the |0> state.

Full docstring

Reset each target qubit to the |0> state.

Parameters
*targets

The indices of the target qubits.

method reset_loss_channel ppvm.generalized_tableau.GeneralizedTableau.reset_loss_channel
reset_loss_channel(addr0: int) -> None

Reset a lost qubit to being active again.

Full docstring

Reset a lost qubit to being active again.

Parameters
addr0 int

The index of the target qubit.

method reset_x ppvm.generalized_tableau.GeneralizedTableau.reset_x
reset_x(targets = ()) -> None

Reset each target qubit to the |+> state.

Full docstring

Reset each target qubit to the |+> state.

Parameters
*targets

The indices of the target qubits.

method reset_y ppvm.generalized_tableau.GeneralizedTableau.reset_y
reset_y(targets = ()) -> None

Reset each target qubit to the |+i> state.

Full docstring

Reset each target qubit to the |+i> state.

Parameters
*targets

The indices of the target qubits.

method reset_z ppvm.generalized_tableau.GeneralizedTableau.reset_z
reset_z(targets = ()) -> None

Reset each target qubit to the |0> state.

Full docstring

Reset each target qubit to the |0> state.

Parameters
*targets

The indices of the target qubits.

method run ppvm.generalized_tableau.GeneralizedTableau.run
run(prog: StimProgram)

Execute a parsed Stim program against this tableau (single shot).

Full docstring

Execute a parsed Stim program against this tableau (single shot).

.. note:: This mutates the tableau in place. For independent shots use fork or ppvm.sample_stim / sample helpers (which build a fresh tableau per shot).

method sample ppvm.generalized_tableau.GeneralizedTableau.sample
sample(cls, prog: StimProgram, n_qubits: int, min_abs_coeff: float = 1e-10, num_shots: int = 1, seed = None)

Run num_shots shots of prog and return all measurement results.

Full docstring

Run num_shots shots of prog and return all measurement results.

Each shot starts from a fresh tableau, so this is the right entry point for multi-shot sampling.

Shots run in parallel across CPU cores (the GIL is released during sampling), with a serial fallback for small batches. When seed is given (it must fit in an unsigned 64-bit integer), shot i uses (seed + i) % 2**64 (wrapping u64 arithmetic), so results are reproducible and independent of the number of threads. Set the RAYON_NUM_THREADS environment variable before the first call to control the pool size (it defaults to the number of logical cores).

method t ppvm.generalized_tableau.GeneralizedTableau.t
t(targets = ()) -> None

Apply a T gate (π/8 rotation) to each target qubit.

Full docstring

Apply a T gate (π/8 rotation) to each target qubit.

Parameters
*targets

The indices of the target qubits.

method t_dag ppvm.generalized_tableau.GeneralizedTableau.t_dag
t_dag(targets = ()) -> None

Apply a T adjoint gate (negative π/8 rotation) to each target qubit.

Full docstring

Apply a T adjoint gate (negative π/8 rotation) to each target qubit.

Parameters
*targets

The indices of the target qubits.

method u3 ppvm.generalized_tableau.GeneralizedTableau.u3
u3(addr0: int, theta: float, phi: float, lam: float)

Apply the U3 gate to the specified qubit.

Full docstring

Apply the U3 gate to the specified qubit.

U3(θ, φ, λ) = RZ(φ) · RY(θ) · RZ(λ)

The corresponding unitary matrix is:

[ cos(θ/2)            -e^(iλ)·sin(θ/2)       ]
[ e^(iφ)·sin(θ/2)     e^(i(φ+λ))·cos(θ/2)   ]
Parameters
addr0 int

The address of the qubit to apply the gate to.

theta float

Rotation angle θ (in radians) for the RY component.

phi float

Rotation angle φ (in radians) for the first RZ component.

lam float

Rotation angle λ (in radians) for the second RZ component.

attribute MAX_N_QUBITS ppvm.generalized_tableau.MAX_N_QUBITS
MAX_N_QUBITS

Maximum number of qubits supported by the Python bindings.

Full docstring

Maximum number of qubits supported by the Python bindings.

The native module pre-compiles a fixed set of tableau interfaces; beyond this limit, use the Rust crate directly.

generalized_tableau_sum

class GeneralizedTableauSum ppvm.generalized_tableau_sum.GeneralizedTableauSum
class GeneralizedTableauSum

A sum over generalized tableaus, representing a density matrix that is a weighted sum over pure state projectors (classical mixture). Each projector is represented by a generalized tableau. The respective weights are the probabilities wi…

Full docstring

A sum over generalized tableaus, representing a density matrix that is a weighted sum over pure state projectors (classical mixture). Each projector is represented by a generalized tableau. The respective weights are the probabilities with which the system is in the corresponding state.

class TableauSumSampler ppvm.generalized_tableau_sum.TableauSumSampler
class TableauSumSampler

Sample a GeneralizedTableauSum.

Full docstring

Sample a GeneralizedTableauSum.

Construct via GeneralizedTableauSum.sampler().

method measure ppvm.generalized_tableau_sum.GeneralizedTableauSum.measure
measure(addr0: int)

Branch on a mid-circuit Z measurement and return outcome probabilities.

Full docstring

Branch on a mid-circuit Z measurement and return outcome probabilities.

Parameters
addr0 int

The index of the target qubit.

Returns

A mapping from MeasurementResult (ZERO, ONE, LOST) to the corresponding outcome probability.

method reset ppvm.generalized_tableau_sum.GeneralizedTableauSum.reset
reset(targets = ()) -> None

Reset each target qubit to the |0> state.

Full docstring

Reset each target qubit to the |0> state.

Parameters
*targets

The indices of the target qubits.

method reset_loss_channel ppvm.generalized_tableau_sum.GeneralizedTableauSum.reset_loss_channel
reset_loss_channel(addr0: int) -> None

Reset a lost qubit to being active again.

Full docstring

Reset a lost qubit to being active again.

Parameters
addr0 int

The index of the target qubit.

method sampler ppvm.generalized_tableau_sum.GeneralizedTableauSum.sampler
sampler() -> TableauSumSampler

Compile a sampler over a snapshot of the current state.

Full docstring

Compile a sampler over a snapshot of the current state.

The sampler holds its own RNG and a copy of the sum's branches, so further gates applied to this tableau do not affect it.

Returns
TableauSumSampler

A sampler drawing shots from the current state.

method t ppvm.generalized_tableau_sum.GeneralizedTableauSum.t
t(targets = ()) -> None

Apply a T gate (π/8 rotation) to each target qubit.

Full docstring

Apply a T gate (π/8 rotation) to each target qubit.

Parameters
*targets

The indices of the target qubits.

method t_dag ppvm.generalized_tableau_sum.GeneralizedTableauSum.t_dag
t_dag(targets = ()) -> None

Apply a T adjoint gate (negative π/8 rotation) to each target qubit.

Full docstring

Apply a T adjoint gate (negative π/8 rotation) to each target qubit.

Parameters
*targets

The indices of the target qubits.

method u3 ppvm.generalized_tableau_sum.GeneralizedTableauSum.u3
u3(addr0: int, theta: float, phi: float, lam: float)

Apply the U3 gate to the specified qubit.

Full docstring

Apply the U3 gate to the specified qubit.

U3(θ, φ, λ) = RZ(φ) · RY(θ) · RZ(λ)

The corresponding unitary matrix is:

[ cos(θ/2)            -e^(iλ)·sin(θ/2)       ]
[ e^(iφ)·sin(θ/2)     e^(i(φ+λ))·cos(θ/2)   ]
Parameters
addr0 int

The address of the qubit to apply the gate to.

theta float

Rotation angle θ (in radians) for the RY component.

phi float

Rotation angle φ (in radians) for the first RZ component.

lam float

Rotation angle λ (in radians) for the second RZ component.

method raw_sample ppvm.generalized_tableau_sum.TableauSumSampler.raw_sample
raw_sample()

Draw a single shot as raw integer codes (0/1/2 for |0>/|1>/lost).

Full docstring

Draw a single shot as raw integer codes (0/1/2 for |0>/|1>/lost).

Faster than sample, as it skips the MeasurementResult conversion.

Returns

Per-qubit integer outcome codes, indexed by qubit address.

method raw_shots ppvm.generalized_tableau_sum.TableauSumSampler.raw_shots
raw_shots(num_shots: int)

Draw num_shots shots as raw integer codes (0/1/2 for |0>/|1>/lost).

Full docstring

Draw num_shots shots as raw integer codes (0/1/2 for |0>/|1>/lost).

Faster than sample_shots, as it skips the MeasurementResult conversion.

Parameters
num_shots int

The number of shots to draw.

Returns

One list of per-qubit integer outcome codes per shot.

method sample ppvm.generalized_tableau_sum.TableauSumSampler.sample
sample()

Draw a single shot: one measurement outcome per qubit.

Full docstring

Draw a single shot: one measurement outcome per qubit.

Returns

Per-qubit outcomes, indexed by qubit address.

method sample_shots ppvm.generalized_tableau_sum.TableauSumSampler.sample_shots
sample_shots(num_shots: int)

Draw num_shots shots, each with one outcome per qubit.

Full docstring

Draw num_shots shots, each with one outcome per qubit.

Parameters
num_shots int

The number of shots to draw.

Returns

One list of per-qubit outcomes per shot.

mixins

class CliffordExtensionMixin ppvm.mixins.CliffordExtensionMixin
class CliffordExtensionMixin

Additional Clifford gates without per-gate truncation control.

class CliffordMixin ppvm.mixins.CliffordMixin
class CliffordMixin

Clifford gates without per-gate truncation control.

class LossMixin ppvm.mixins.LossMixin
class LossMixin

Loss channels without per-gate truncation control.

class NoiseMixin ppvm.mixins.NoiseMixin
class NoiseMixin

Noise channels without per-gate truncation control.

class RotationsMixin ppvm.mixins.RotationsMixin
class RotationsMixin

Rotation gates without per-gate truncation control.

class TruncatingCliffordExtensionMixin ppvm.mixins.TruncatingCliffordExtensionMixin
class TruncatingCliffordExtensionMixin

Additional Clifford gates with a per-gate truncate kwarg.

class TruncatingCliffordMixin ppvm.mixins.TruncatingCliffordMixin
class TruncatingCliffordMixin

Clifford gates with a per-gate truncate kwarg (used by PauliSum).

class TruncatingNoiseMixin ppvm.mixins.TruncatingNoiseMixin
class TruncatingNoiseMixin

Noise channels with a per-gate truncate kwarg (used by PauliSum).

Full docstring

Noise channels with a per-gate truncate kwarg (used by PauliSum).

two_qubit_pauli_error_probabilities is inherited unchanged from NoiseMixin.

class TruncatingRotationsMixin ppvm.mixins.TruncatingRotationsMixin
class TruncatingRotationsMixin

Rotation gates with a per-gate truncate kwarg (used by PauliSum).

method cy ppvm.mixins.CliffordExtensionMixin.cy
cy(targets = ()) -> None

Apply controlled-Y gates over consecutive control/target pairs.

Full docstring

Apply controlled-Y gates over consecutive control/target pairs.

Parameters
*targets

A flat list of qubit indices, broadcast as (control, target) pairs.

method s_dag ppvm.mixins.CliffordExtensionMixin.s_dag
s_dag(targets = ()) -> None

Apply an S adjoint gate (sqrt(Z) dagger) to each target qubit.

Full docstring

Apply an S adjoint gate (sqrt(Z) dagger) to each target qubit.

Parameters
*targets

The indices of the target qubits.

method sqrt_x ppvm.mixins.CliffordExtensionMixin.sqrt_x
sqrt_x(targets = ()) -> None

Apply a sqrt(X) gate to each target qubit.

Full docstring

Apply a sqrt(X) gate to each target qubit.

Parameters
*targets

The indices of the target qubits.

method sqrt_x_dag ppvm.mixins.CliffordExtensionMixin.sqrt_x_dag
sqrt_x_dag(targets = ()) -> None

Apply a sqrt(X) adjoint gate to each target qubit.

Full docstring

Apply a sqrt(X) adjoint gate to each target qubit.

Parameters
*targets

The indices of the target qubits.

method sqrt_y ppvm.mixins.CliffordExtensionMixin.sqrt_y
sqrt_y(targets = ()) -> None

Apply a sqrt(Y) gate to each target qubit.

Full docstring

Apply a sqrt(Y) gate to each target qubit.

Parameters
*targets

The indices of the target qubits.

method sqrt_y_dag ppvm.mixins.CliffordExtensionMixin.sqrt_y_dag
sqrt_y_dag(targets = ()) -> None

Apply a sqrt(Y) adjoint gate to each target qubit.

Full docstring

Apply a sqrt(Y) adjoint gate to each target qubit.

Parameters
*targets

The indices of the target qubits.

method cnot ppvm.mixins.CliffordMixin.cnot
cnot(targets = ()) -> None

Apply CNOT (controlled-X) gates over consecutive control/target pairs.

Full docstring

Apply CNOT (controlled-X) gates over consecutive control/target pairs.

Parameters
*targets

A flat list of qubit indices, broadcast as (control, target) pairs.

method cz ppvm.mixins.CliffordMixin.cz
cz(targets = ()) -> None

Apply CZ (controlled-Z) gates over consecutive qubit pairs.

Full docstring

Apply CZ (controlled-Z) gates over consecutive qubit pairs.

Parameters
*targets

A flat list of qubit indices, broadcast as pairs.

method h ppvm.mixins.CliffordMixin.h
h(targets = ()) -> None

Apply a Hadamard gate to each target qubit.

Full docstring

Apply a Hadamard gate to each target qubit.

Parameters
*targets

The indices of the target qubits.

method s ppvm.mixins.CliffordMixin.s
s(targets = ()) -> None

Apply an S gate (sqrt(Z)) to each target qubit.

Full docstring

Apply an S gate (sqrt(Z)) to each target qubit.

Parameters
*targets

The indices of the target qubits.

method x ppvm.mixins.CliffordMixin.x
x(targets = ()) -> None

Apply a Pauli X gate to each target qubit.

Full docstring

Apply a Pauli X gate to each target qubit.

Parameters
*targets

The indices of the target qubits.

method y ppvm.mixins.CliffordMixin.y
y(targets = ()) -> None

Apply a Pauli Y gate to each target qubit.

Full docstring

Apply a Pauli Y gate to each target qubit.

Parameters
*targets

The indices of the target qubits.

method z ppvm.mixins.CliffordMixin.z
z(targets = ()) -> None

Apply a Pauli Z gate to each target qubit.

Full docstring

Apply a Pauli Z gate to each target qubit.

Parameters
*targets

The indices of the target qubits.

method correlated_loss_channel ppvm.mixins.LossMixin.correlated_loss_channel
correlated_loss_channel(addr0: int, addr1: int, p) -> None

Apply a correlated loss channel to two qubits.

Full docstring

Apply a correlated loss channel to two qubits.

Parameters
addr0 int

The index of the first target qubit.

addr1 int

The index of the second target qubit.

p

A list of three probabilities:

  • p[0]: probability of losing both qubits simultaneously when both are in the qubit subspace.
  • p[1]: probability of losing exactly one qubit when both are in the qubit subspace (which qubit is lost is 50/50 random).
  • p[2]: probability of losing the remaining active qubit when the other has already been lost prior to this channel.
method loss_channel ppvm.mixins.LossMixin.loss_channel
loss_channel(addr0: int, p: float) -> None

Apply a loss channel to the specified qubit.

Full docstring

Apply a loss channel to the specified qubit.

Parameters
addr0 int

The index of the target qubit.

p float

The loss probability.

method depolarize1 ppvm.mixins.NoiseMixin.depolarize1
depolarize1(args: Any = (), p = None) -> None

Apply a single-qubit depolarizing channel to each target qubit.

Full docstring

Apply a single-qubit depolarizing channel to each target qubit.

Parameters
*targets

The indices of the target qubits.

p

The depolarizing probability.

method depolarize2 ppvm.mixins.NoiseMixin.depolarize2
depolarize2(args: Any = (), p = None) -> None

Apply a two-qubit depolarizing channel over consecutive qubit pairs.

Full docstring

Apply a two-qubit depolarizing channel over consecutive qubit pairs.

Parameters
*targets

A flat list of qubit indices, broadcast as pairs.

p

The depolarizing probability.

method pauli_error ppvm.mixins.NoiseMixin.pauli_error
pauli_error(args: Any = (), p = None) -> None

Apply a single-qubit Pauli error channel to each target qubit.

Full docstring

Apply a single-qubit Pauli error channel to each target qubit.

Parameters
*targets

The indices of the target qubits.

p

Error probabilities [p_x, p_y, p_z] for X, Y, Z errors. The identity probability is implicitly 1 - sum(p).

method two_qubit_pauli_error ppvm.mixins.NoiseMixin.two_qubit_pauli_error
two_qubit_pauli_error(args: Any = (), p = None) -> None

Apply a two-qubit Pauli error channel over consecutive qubit pairs.

Full docstring

Apply a two-qubit Pauli error channel over consecutive qubit pairs.

Parameters
*targets

A flat list of qubit indices, broadcast as pairs.

p

Error probabilities for the 15 non-identity two-qubit Pauli operators. Use two_qubit_pauli_error_probabilities to convert from a dictionary format.

method two_qubit_pauli_error_probabilities ppvm.mixins.NoiseMixin.two_qubit_pauli_error_probabilities
two_qubit_pauli_error_probabilities(error_probabilities)

Convert a dictionary of two-qubit Pauli error probabilities to a list.

Full docstring

Convert a dictionary of two-qubit Pauli error probabilities to a list.

Convenience method to convert a dictionary mapping two-qubit Pauli strings (e.g., "IX", "ZZ") to their probabilities into the ordered list format required by two_qubit_pauli_error.

Parameters
error_probabilities

Dictionary mapping two-qubit Pauli strings to their error probabilities. Missing keys default to 0.0.

Returns

A list of 15 probabilities in the canonical order (excludes "II").

method x_error ppvm.mixins.NoiseMixin.x_error
x_error(args: Any = (), p = None) -> None

Apply an X error channel to each target qubit.

Full docstring

Apply an X error channel to each target qubit.

Parameters
*targets

The indices of the target qubits.

p

The probability of applying an X error.

method y_error ppvm.mixins.NoiseMixin.y_error
y_error(args: Any = (), p = None) -> None

Apply a Y error channel to each target qubit.

Full docstring

Apply a Y error channel to each target qubit.

Parameters
*targets

The indices of the target qubits.

p

The probability of applying a Y error.

method z_error ppvm.mixins.NoiseMixin.z_error
z_error(args: Any = (), p = None) -> None

Apply a Z error channel to each target qubit.

Full docstring

Apply a Z error channel to each target qubit.

Parameters
*targets

The indices of the target qubits.

p

The probability of applying a Z error.

method rx ppvm.mixins.RotationsMixin.rx
rx(args: Any = (), theta = None) -> None

Apply an RX rotation gate to each target qubit.

Full docstring

Apply an RX rotation gate to each target qubit.

math R_X(\theta) = e^{-i \frac{\theta}{2} X} = \cos\frac{\theta}{2} I - i \sin\frac{\theta}{2} X

Parameters
*targets

The indices of the target qubits.

theta

The rotation angle in radians.

method rxx ppvm.mixins.RotationsMixin.rxx
rxx(args: Any = (), theta = None) -> None

Apply RXX (Ising XX) rotation gates over consecutive qubit pairs.

Full docstring

Apply RXX (Ising XX) rotation gates over consecutive qubit pairs.

math R_{XX}(\theta) = e^{-i \frac{\theta}{2} X \otimes X}

Parameters
*targets

A flat list of qubit indices, broadcast as pairs.

theta

The rotation angle in radians.

method ry ppvm.mixins.RotationsMixin.ry
ry(args: Any = (), theta = None) -> None

Apply an RY rotation gate to each target qubit.

Full docstring

Apply an RY rotation gate to each target qubit.

math R_Y(\theta) = e^{-i \frac{\theta}{2} Y} = \cos\frac{\theta}{2} I - i \sin\frac{\theta}{2} Y

Parameters
*targets

The indices of the target qubits.

theta

The rotation angle in radians.

method ryy ppvm.mixins.RotationsMixin.ryy
ryy(args: Any = (), theta = None) -> None

Apply RYY (Ising YY) rotation gates over consecutive qubit pairs.

Full docstring

Apply RYY (Ising YY) rotation gates over consecutive qubit pairs.

math R_{YY}(\theta) = e^{-i \frac{\theta}{2} Y \otimes Y}

Parameters
*targets

A flat list of qubit indices, broadcast as pairs.

theta

The rotation angle in radians.

method rz ppvm.mixins.RotationsMixin.rz
rz(args: Any = (), theta = None) -> None

Apply an RZ rotation gate to each target qubit.

Full docstring

Apply an RZ rotation gate to each target qubit.

math R_Z(\theta) = e^{-i \frac{\theta}{2} Z} = \cos\frac{\theta}{2} I - i \sin\frac{\theta}{2} Z

Parameters
*targets

The indices of the target qubits.

theta

The rotation angle in radians.

method rzz ppvm.mixins.RotationsMixin.rzz
rzz(args: Any = (), theta = None) -> None

Apply RZZ (Ising ZZ) rotation gates over consecutive qubit pairs.

Full docstring

Apply RZZ (Ising ZZ) rotation gates over consecutive qubit pairs.

math R_{ZZ}(\theta) = e^{-i \frac{\theta}{2} Z \otimes Z}

Parameters
*targets

A flat list of qubit indices, broadcast as pairs.

theta

The rotation angle in radians.

method cy ppvm.mixins.TruncatingCliffordExtensionMixin.cy
cy(targets = (), truncate: bool = True) -> None

Apply controlled-Y gates over consecutive control/target pairs.

Full docstring

Apply controlled-Y gates over consecutive control/target pairs.

Parameters
*targets

A flat list of qubit indices, broadcast as pairs.

truncate bool

See TruncatingCliffordMixin.x.

method s_dag ppvm.mixins.TruncatingCliffordExtensionMixin.s_dag
s_dag(targets = (), truncate: bool = True) -> None

Apply an S adjoint gate (sqrt(Z) dagger) to each target qubit.

Full docstring

Apply an S adjoint gate (sqrt(Z) dagger) to each target qubit.

Parameters
*targets

The indices of the target qubits.

truncate bool

See TruncatingCliffordMixin.x.

method sqrt_x ppvm.mixins.TruncatingCliffordExtensionMixin.sqrt_x
sqrt_x(targets = (), truncate: bool = True) -> None

Apply a sqrt(X) gate to each target qubit.

Full docstring

Apply a sqrt(X) gate to each target qubit.

Parameters
*targets

The indices of the target qubits.

truncate bool

See TruncatingCliffordMixin.x.

method sqrt_x_dag ppvm.mixins.TruncatingCliffordExtensionMixin.sqrt_x_dag
sqrt_x_dag(targets = (), truncate: bool = True) -> None

Apply a sqrt(X) adjoint gate to each target qubit.

Full docstring

Apply a sqrt(X) adjoint gate to each target qubit.

Parameters
*targets

The indices of the target qubits.

truncate bool

See TruncatingCliffordMixin.x.

method sqrt_y ppvm.mixins.TruncatingCliffordExtensionMixin.sqrt_y
sqrt_y(targets = (), truncate: bool = True) -> None

Apply a sqrt(Y) gate to each target qubit.

Full docstring

Apply a sqrt(Y) gate to each target qubit.

Parameters
*targets

The indices of the target qubits.

truncate bool

See TruncatingCliffordMixin.x.

method sqrt_y_dag ppvm.mixins.TruncatingCliffordExtensionMixin.sqrt_y_dag
sqrt_y_dag(targets = (), truncate: bool = True) -> None

Apply a sqrt(Y) adjoint gate to each target qubit.

Full docstring

Apply a sqrt(Y) adjoint gate to each target qubit.

Parameters
*targets

The indices of the target qubits.

truncate bool

See TruncatingCliffordMixin.x.

method cnot ppvm.mixins.TruncatingCliffordMixin.cnot
cnot(targets = (), truncate: bool = True) -> None

Apply CNOT (controlled-X) gates over consecutive control/target pairs.

Full docstring

Apply CNOT (controlled-X) gates over consecutive control/target pairs.

Parameters
*targets

A flat list of qubit indices, broadcast as pairs.

truncate bool

See x.

method cz ppvm.mixins.TruncatingCliffordMixin.cz
cz(targets = (), truncate: bool = True) -> None

Apply CZ (controlled-Z) gates over consecutive qubit pairs.

Full docstring

Apply CZ (controlled-Z) gates over consecutive qubit pairs.

Parameters
*targets

A flat list of qubit indices, broadcast as pairs.

truncate bool

See x.

method h ppvm.mixins.TruncatingCliffordMixin.h
h(targets = (), truncate: bool = True) -> None

Apply a Hadamard gate to each target qubit.

Full docstring

Apply a Hadamard gate to each target qubit.

Parameters
*targets

The indices of the target qubits.

truncate bool

See x.

method s ppvm.mixins.TruncatingCliffordMixin.s
s(targets = (), truncate: bool = True) -> None

Apply an S gate (sqrt(Z)) to each target qubit.

Full docstring

Apply an S gate (sqrt(Z)) to each target qubit.

Parameters
*targets

The indices of the target qubits.

truncate bool

See x.

method x ppvm.mixins.TruncatingCliffordMixin.x
x(targets = (), truncate: bool = True) -> None

Apply a Pauli X gate to each target qubit.

Full docstring

Apply a Pauli X gate to each target qubit.

Parameters
*targets

The indices of the target qubits.

truncate bool

If True (default), run the configured truncation strategy after the gate; if False, leave the map untruncated so the next gate sees the full unpruned state.

method y ppvm.mixins.TruncatingCliffordMixin.y
y(targets = (), truncate: bool = True) -> None

Apply a Pauli Y gate to each target qubit.

Full docstring

Apply a Pauli Y gate to each target qubit.

Parameters
*targets

The indices of the target qubits.

truncate bool

See x.

method z ppvm.mixins.TruncatingCliffordMixin.z
z(targets = (), truncate: bool = True) -> None

Apply a Pauli Z gate to each target qubit.

Full docstring

Apply a Pauli Z gate to each target qubit.

Parameters
*targets

The indices of the target qubits.

truncate bool

See x.

method depolarize1 ppvm.mixins.TruncatingNoiseMixin.depolarize1
depolarize1(args: Any = (), p = None, truncate: bool = True) -> None

Apply a single-qubit depolarizing channel to each target qubit.

Full docstring

Apply a single-qubit depolarizing channel to each target qubit.

Parameters
*targets

The indices of the target qubits.

p

The depolarizing probability.

truncate bool

See pauli_error.

method depolarize2 ppvm.mixins.TruncatingNoiseMixin.depolarize2
depolarize2(args: Any = (), p = None, truncate: bool = True) -> None

Apply a two-qubit depolarizing channel over consecutive qubit pairs.

Full docstring

Apply a two-qubit depolarizing channel over consecutive qubit pairs.

Parameters
*targets

A flat list of qubit indices, broadcast as pairs.

p

The depolarizing probability.

truncate bool

See pauli_error.

method pauli_error ppvm.mixins.TruncatingNoiseMixin.pauli_error
pauli_error(args: Any = (), p = None, truncate: bool = True) -> None

Apply a single-qubit Pauli error channel to each target qubit.

Full docstring

Apply a single-qubit Pauli error channel to each target qubit.

Parameters
*targets

The indices of the target qubits.

p

Error probabilities [p_x, p_y, p_z] for X, Y, Z errors. The identity probability is implicitly 1 - sum(p).

truncate bool

If True (default), run the configured truncation strategy after the channel; if False, defer it.

method two_qubit_pauli_error ppvm.mixins.TruncatingNoiseMixin.two_qubit_pauli_error
two_qubit_pauli_error(args: Any = (), p = None, truncate: bool = True) -> None

Apply a two-qubit Pauli error channel over consecutive qubit pairs.

Full docstring

Apply a two-qubit Pauli error channel over consecutive qubit pairs.

Parameters
*targets

A flat list of qubit indices, broadcast as pairs.

p

Error probabilities for the 15 non-identity two-qubit Pauli operators. Use two_qubit_pauli_error_probabilities to convert from a dictionary format.

truncate bool

See pauli_error.

method x_error ppvm.mixins.TruncatingNoiseMixin.x_error
x_error(args: Any = (), p = None, truncate: bool = True) -> None

Apply an X error channel to each target qubit.

Full docstring

Apply an X error channel to each target qubit.

Parameters
*targets

The indices of the target qubits.

p

The probability of applying an X error.

truncate bool

See pauli_error.

method y_error ppvm.mixins.TruncatingNoiseMixin.y_error
y_error(args: Any = (), p = None, truncate: bool = True) -> None

Apply a Y error channel to each target qubit.

Full docstring

Apply a Y error channel to each target qubit.

Parameters
*targets

The indices of the target qubits.

p

The probability of applying a Y error.

truncate bool

See pauli_error.

method z_error ppvm.mixins.TruncatingNoiseMixin.z_error
z_error(args: Any = (), p = None, truncate: bool = True) -> None

Apply a Z error channel to each target qubit.

Full docstring

Apply a Z error channel to each target qubit.

Parameters
*targets

The indices of the target qubits.

p

The probability of applying a Z error.

truncate bool

See pauli_error.

method rx ppvm.mixins.TruncatingRotationsMixin.rx
rx(args: Any = (), theta = None, truncate: bool = True) -> None

Apply an RX rotation gate to each target qubit.

Full docstring

Apply an RX rotation gate to each target qubit.

See RotationsMixin.rx for the gate definition.

Parameters
*targets

The indices of the target qubits.

theta

The rotation angle in radians.

truncate bool

If True (default), run the configured truncation strategy after the gate; if False, defer it.

method rxx ppvm.mixins.TruncatingRotationsMixin.rxx
rxx(args: Any = (), theta = None, truncate: bool = True) -> None

Apply RXX (Ising XX) rotation gates over consecutive qubit pairs.

Full docstring

Apply RXX (Ising XX) rotation gates over consecutive qubit pairs.

See RotationsMixin.rxx for the gate definition.

Parameters
*targets

A flat list of qubit indices, broadcast as pairs.

theta

The rotation angle in radians.

truncate bool

If True (default), run the configured truncation strategy after the gate. Set to False to compose a U(1)-conserving step like rxx + ryy on the same edge without dropping the conserved-charge component between them — then call PauliSum.truncate once at the end of the composition.

method ry ppvm.mixins.TruncatingRotationsMixin.ry
ry(args: Any = (), theta = None, truncate: bool = True) -> None

Apply an RY rotation gate to each target qubit.

Full docstring

Apply an RY rotation gate to each target qubit.

See RotationsMixin.ry for the gate definition.

Parameters
*targets

The indices of the target qubits.

theta

The rotation angle in radians.

truncate bool

See rx.

method ryy ppvm.mixins.TruncatingRotationsMixin.ryy
ryy(args: Any = (), theta = None, truncate: bool = True) -> None

Apply RYY (Ising YY) rotation gates over consecutive qubit pairs.

Full docstring

Apply RYY (Ising YY) rotation gates over consecutive qubit pairs.

See RotationsMixin.ryy for the gate definition.

Parameters
*targets

A flat list of qubit indices, broadcast as pairs.

theta

The rotation angle in radians.

truncate bool

See rxx.

method rz ppvm.mixins.TruncatingRotationsMixin.rz
rz(args: Any = (), theta = None, truncate: bool = True) -> None

Apply an RZ rotation gate to each target qubit.

Full docstring

Apply an RZ rotation gate to each target qubit.

See RotationsMixin.rz for the gate definition.

Parameters
*targets

The indices of the target qubits.

theta

The rotation angle in radians.

truncate bool

See rx.

method rzz ppvm.mixins.TruncatingRotationsMixin.rzz
rzz(args: Any = (), theta = None, truncate: bool = True) -> None

Apply RZZ (Ising ZZ) rotation gates over consecutive qubit pairs.

Full docstring

Apply RZZ (Ising ZZ) rotation gates over consecutive qubit pairs.

See RotationsMixin.rzz for the gate definition.

Parameters
*targets

A flat list of qubit indices, broadcast as pairs.

theta

The rotation angle in radians.

truncate bool

See rxx.

paulisum

class LossyPauliSum ppvm.paulisum.LossyPauliSum
class LossyPauliSum

A PauliSum that supports modelling qubit loss.

Full docstring

A PauliSum that supports modelling qubit loss.

This is achieved by extending the set of Pauli basis operators to include an addition operator {I, X, Y, Z, L}, where L is the projector on a third leakage state. This basis effectively allows simulating qutrits, where we neglect any coherences between the qubit subspace and the leakage state.

In addition to the new channels, there is also another truncation strategy: Since Pauli Strings that have an L at multiple positions contribute only minimally, these can get truncated by setting an appropriate max_loss_weight. The truncation is similar to how max_pauli_weight truncates strings, but only counting Ls.

class PauliSum ppvm.paulisum.PauliSum
class PauliSum

A weighted sum of Pauli strings for quantum simulation.

Full docstring

A weighted sum of Pauli strings for quantum simulation.

PauliSum represents a linear combination of Pauli operators, commonly used to represent quantum observables or Hamiltonians. It provides methods for applying quantum gates (Clifford operations and rotations) and computing expectation values via the trace operation.

method correlated_loss_channel ppvm.paulisum.LossyPauliSum.correlated_loss_channel
correlated_loss_channel(addr0: int, addr1: int, p, truncate: bool = True) -> None

Apply a correlated loss channel.

Full docstring

Apply a correlated loss channel.

This applies a correlated loss channel to the qubits at addr0 and addr1. The channel accepts 3 probabilities as argument: * p[0]: The probability of losing both qubits, when they are originally in the qubit subspace. * p[1]: The probability of losing a single qubit, when both qubits are originally in the qubit subspace. * p[2]: The probability of losing one qubit when the other one has already been lost prior to applying the channel. This is to account for the fact that when one qubit is missing during e.g. a controlled gate, the remaining qubit undergoes a different dynamic. We account for this difference with this distinct probability. truncate: If True (default), run the configured truncation strategy after the channel; if False, defer it.

method loss_channel ppvm.paulisum.LossyPauliSum.loss_channel
loss_channel(addr0: int, p: float, truncate: bool = True) -> None

Apply a single-qubit loss channel.

Full docstring

Apply a single-qubit loss channel.

Reduces the trace of qubit-subspace operators by (1 - p). Adds back population into I or Z if the Pauli string has an L at addr0. This can only occur if a reset channel has been applied before and accounts for the fact of falsely counting a lost qubit as 0 in a measurement.

Parameters
addr0 int

The index of the target qubit.

p float

Loss probability in [0, 1].

truncate bool

If True (default), run the configured truncation strategy after the channel; if False, defer it.

method reset_loss_channel ppvm.paulisum.LossyPauliSum.reset_loss_channel
reset_loss_channel(addr0: int, truncate: bool = True) -> None

Reset a lost qubit to the 0 state. Usually, you want to apply this channel at the end of the circuit, i.e. at the beginning when propagating backwards.

Full docstring

Reset a lost qubit to the 0 state. Usually, you want to apply this channel at the end of the circuit, i.e. at the beginning when propagating backwards.

NOTE: This channel causes exponential branching in I and Z. Make sure to set an appropriate max_loss_weight to truncate.

Parameters
addr0 int

The index of the qubit to reset.

truncate bool

If True (default), run the configured truncation strategy after the channel; if False, defer it.

method amplitude_damping ppvm.paulisum.PauliSum.amplitude_damping
amplitude_damping(addr0: int, gamma: float, truncate: bool = True)

Apply an amplitude-damping channel.

Full docstring

Apply an amplitude-damping channel.

Parameters
addr0 int

The index of the target qubit.

gamma float

The damping rate. X and Y are damped with sqrt(1 - gamma), whereas Z branches into gamma * I + (1 - gamma) * Z.

truncate bool

If True (default), run the configured truncation strategy after the channel; if False, defer it (use truncate to fire the cut later).

method copy ppvm.paulisum.PauliSum.copy
copy() -> Self

Create a copy of the PauliSum instance.

Full docstring

Create a copy of the PauliSum instance.

Returns
Self

A new PauliSum instance that is a copy of the current one.

method current_max_weight ppvm.paulisum.PauliSum.current_max_weight
current_max_weight() -> int

Get the current maximum weight of the Pauli sum.

Full docstring

Get the current maximum weight of the Pauli sum.

Returns
int

The weight as integer.

method new ppvm.paulisum.PauliSum.new
new(cls, n_qubits: int, terms, min_abs_coeff: float = 1e-10, max_pauli_weight = None, max_loss_weight = None, preserve_strings = None) -> Self

Create a PauliSum from one or more terms with flexible input formats.

Full docstring

Create a PauliSum from one or more terms with flexible input formats.

Parameters
n_qubits int

Number of qubits.

terms

A single term or list of terms. Each term is either:

  • A full Pauli string (e.g. "IX"), with coefficient 1.0.
  • A compact string "P{i}" (e.g. "X1"), placing Pauli P at 0-based qubit index i with coefficient 1.0.
  • A tuple (str, float) pairing either of the above with an explicit coefficient.
min_abs_coeff float

Terms with absolute coefficient below this threshold are dropped. Defaults to 1e-10.

max_pauli_weight

Maximum number of non-identity Paulis per term. If None, truncation is disabled.

max_loss_weight

Maximum loss weight per term (only used by LossyPauliSum). If None, truncation is disabled. Note, that this should usually be chosen to be quite low, since e.g. 10 would correspond to keeping terms that contribute if up to 10 qubits are lost simultaneously.

preserve_strings

Pauli strings (length n_qubits each) that truncation must never drop. Empty by default.

Returns
Self

A new instance of the class this method is called on.

Raises
ValueError

If a compact qubit index is out of range for n_qubits.

method overlap ppvm.paulisum.PauliSum.overlap
overlap(other: PauliSum) -> float

Compute the overlap of the current PauliSum with another PauliSum. The overlap is defined as

Full docstring

Compute the overlap of the current PauliSum with another PauliSum. The overlap is defined as

math \text{tr}(A^\dagger \cdot B),

where self -> A other -> B

Returns
float

The trace overlap of the PauliSums.

method overlap_with_zero ppvm.paulisum.PauliSum.overlap_with_zero
overlap_with_zero() -> float

Compute the overlap with the all-zeros computational basis state.

Full docstring

Compute the overlap with the all-zeros computational basis state.

Returns
float

The expectation value of the Pauli sum with respect to |0...0>.

method trace ppvm.paulisum.PauliSum.trace
trace(pattern: str) -> float

Compute the trace using a pattern string.

Full docstring

Compute the trace using a pattern string.

Parameters
pattern str

A pattern specifying which terms to include in the trace. Use 'Z' to project onto |0>, '?' for any single character, and '*' to match zero or more characters.

Returns
float

The trace result.

method truncate ppvm.paulisum.PauliSum.truncate
truncate() -> None

Run the configured truncation strategy (min_abs_coeff and/or max_pauli_weight) on the current state.

Full docstring

Run the configured truncation strategy (min_abs_coeff and/or max_pauli_weight) on the current state.

Useful when gates were called with truncate=False to chain a composition of commuting operations (e.g. rxx + ryy on the same edge, an exchange-like step that conserves total Z), so that intermediate truncation does not drop conserved-charge components. Call truncate once at the end of the composition to apply the cut to the combined result.

method weights ppvm.paulisum.PauliSum.weights
weights()

Get the weight of each Pauli term.

Full docstring

Get the weight of each Pauli term.

Returns

A list of tuples, each containing a Pauli string and its weight.

attribute terms ppvm.paulisum.PauliSum.terms
terms

Get the list of Pauli terms and their coefficients.

Full docstring

Get the list of Pauli terms and their coefficients.

Returns

A list of tuples, each containing a Pauli string and its coefficient.

squin_interpreter

module squin_interpreter ppvm.squin_interpreter
module ppvm.squin_interpreter

TODO: once we open-source, all of this will be moved into bloqade-circuit

Rust crates

ppvm-traits

Trait system, the `Config` bundle, the `Pauli` alphabet, and map impls.

module ppvm_traits ppvm_traits
mod ppvm_traits

Foundational trait system, Config trait, single-qubit Pauli alphabet, and the ACMap/Trace map implementations shared across ppvm crates.

struct NoStrategy ppvm_traits::traits::strategy::NoStrategy
struct NoStrategy

Strategy that never truncates — exact simulation, all entries kept.

enum Pauli ppvm_traits::char::Pauli
enum Pauli

A single-qubit Pauli symbol.

Full docstring

A single-qubit Pauli symbol.

The four standard Paulis are encoded so that the low two bits identify the operator (I = 0b00, X = 0b01, Z = 0b10, Y = 0b11), which is the same encoding stabilizer-formalism tools commonly use. The extra variant Pauli::L marks a qubit as lost, used by the loss-aware portions of the runtime.

Examples

use ppvm_traits::char::Pauli;

assert_eq!(Pauli::I.to_string(), "I");
assert_eq!(Pauli::X.to_string(), "X");
assert_eq!(Pauli::Y.to_string(), "Y");
assert_eq!(Pauli::Z.to_string(), "Z");
assert_eq!(Pauli::L.to_string(), "L");
trait Config ppvm_traits::config::Config
trait Config

Compile-time configuration bundle for a PauliSum.

Full docstring

Compile-time configuration bundle for a PauliSum.

Config is a zero-cost generic dispatch mechanism: it pins down the storage backing (Storage), coefficient type (Coeff), truncation strategy (Strategy), hasher (BuildHasher), Pauli-word representation (PauliWordType), and concrete map (Map) used by a single PauliSum instantiation. Pre-built bundles live in the submodules (fxhash, indexmap, …); user code may define its own.

trait CRx ppvm_traits::traits::branch::crx::CRx
trait CRx<T>

Controlled RX rotation.

trait Projection ppvm_traits::traits::branch::proj::Projection
trait Projection

Projective Z-basis projectors |0⟩⟨0| and |1⟩⟨1|.

trait RotationOne ppvm_traits::traits::branch::rot1::RotationOne
trait RotationOne<T>

Single-qubit Pauli rotations exp(-i θ/2 · P).

trait RotationTwo ppvm_traits::traits::branch::rot2::RotationTwo
trait RotationTwo<T>

Two-qubit Pauli rotations, generated by P_a ⊗ P_b for any pair of non-identity Paulis. Provides the named convenience methods rxx, rxy, …, rzz on top of the generic [rotate_2].

Full docstring

Two-qubit Pauli rotations, generated by P_a ⊗ P_b for any pair of non-identity Paulis. Provides the named convenience methods rxx, rxy, …, rzz on top of the generic rotate_2.

trait TGate ppvm_traits::traits::branch::tgate::TGate
trait TGate<T>

The non-Clifford T gate and its adjoint.

Full docstring

The non-Clifford T gate and its adjoint.

T = diag(1, e^{iπ/4}). Implemented by the simulator backends; see the example in ppvm_tableau.

trait U3Gate ppvm_traits::traits::branch::u3::U3Gate
trait U3Gate<T>

The general single-qubit U3(θ, φ, λ) gate.

trait Clifford ppvm_traits::traits::clifford::Clifford
trait Clifford

The minimal Clifford gate set: the single-qubit Paulis (X, Y, Z), Hadamard (H), phase gate (S), and the two entangling Cliffords CNOT and CZ.

Full docstring

The minimal Clifford gate set: the single-qubit Paulis (X, Y, Z), Hadamard (H), phase gate (S), and the two entangling Cliffords CNOT and CZ.

Implemented by PauliSum, by every tableau type, and — via the blanket impl in this module — by every PauliWordTrait implementor.

Examples

Build the GHZ-preparation circuit on a PauliSum (Heisenberg picture, so gates are applied in reverse). PauliSum lives in the downstream ppvm-pauli-sum crate, so this example is ignored here:

use ppvm_pauli_sum::prelude::*;

let mut state: PauliSum<config::indexmap::ByteFxHashF64<1>> =
    PauliSum::builder().n_qubits(2).build();
state += ("ZZ", 1.0);
state.cnot(0, 1);
state.h(0);
assert_eq!(state.len(), 1);
trait CliffordBatch ppvm_traits::traits::clifford::CliffordBatch
trait CliffordBatch

Batched Clifford gates: apply the same gate to many qubits in one call.

Full docstring

Batched Clifford gates: apply the same gate to many qubits in one call.

Default implementations loop over the corresponding single-qubit (or single-pair) method on Clifford. Types like the stabilizer Tableau override these methods with a fused inner-loop or bitmask implementation. Types that don't need specialization can implement this trait with an empty impl to use the defaults.

trait CliffordExtensions ppvm_traits::traits::clifford::CliffordExtensions
trait CliffordExtensions

Additional Clifford gates beyond the minimal set: S†, √X, √X†, √Y, √Y†, and CY.

trait Coefficient ppvm_traits::traits::coefficient::Coefficient
trait Coefficient

Numeric coefficient type usable inside a PauliSum.

Full docstring

Numeric coefficient type usable inside a PauliSum.

Coefficient bundles every arithmetic operation a Pauli-propagation step needs — addition, multiplication, signed multiplication, half, sin/cos, and a cutoff predicate used by truncation strategies. The built-in f64 impl covers the common case; Complex<f64> is available when phase tracking is required.

trait ComplexCoefficient ppvm_traits::traits::coefficient::ComplexCoefficient
trait ComplexCoefficient

A Coefficient extended with multiplication by a fourth-root-of-unity phase. Used by PhasedPauliWord.

trait HashFinalize ppvm_traits::traits::hash::HashFinalize
trait HashFinalize

Post-processing that a PauliWord's hasher applies to its raw 64-bit digest before it is cached as the map-key hash.

Full docstring

Post-processing that a PauliWord's hasher applies to its raw 64-bit digest before it is cached as the map-key hash.

The cached value is what hashbrown ultimately splits into a bucket index (low bits) and a control-byte tag (top 7 bits). Whether the raw digest is good enough for that split is a property of the hasher, not of the Pauli word: an AES-based hasher such as gxhash avalanches well even for an 8-byte key, whereas FxHasher — a couple of multiply-rotate rounds — leaves the low bits of a short key highly correlated and needs a fold to fix them.

Keeping this on the hasher is what makes the abstraction correct. An earlier version folded based on storage width alone, which conflated "narrow storage" with "weak hasher" and so wrongly folded gxhash too. Here each hasher declares how (if at all) its output must be adjusted, and PauliWord::rehash just defers to it. The default is the identity — the right choice for any hasher that already distributes its low bits well — so a custom hasher opts in with a bare impl HashFinalize for MyHasher {}.

trait ACMap ppvm_traits::traits::map::ACMap
trait ACMap<S, V, H, W>

Aggregate trait combining every operation a backing map must support to be usable as the storage for a PauliSum.

Full docstring

Aggregate trait combining every operation a backing map must support to be usable as the storage for a PauliSum.

You don't normally implement ACMap directly: the blanket impl below covers any type that implements all the constituent traits.

trait ACMapAddAssign ppvm_traits::traits::map::ACMapAddAssign
trait ACMapAddAssign<S, V, H, W>

+= semantics for an ACMap: insert a new entry or accumulate into the existing one with the same key.

trait ACMapBase ppvm_traits::traits::map::ACMapBase
trait ACMapBase

Minimal interface for any "associative coefficient map" backing a PauliSum — construction, length, and clear.

Full docstring

Minimal interface for any "associative coefficient map" backing a PauliSum — construction, length, and clear.

Implementations exist for HashMap, IndexMap, and DashMap; pick one via a Config.

trait ACMapConsume ppvm_traits::traits::map::ACMapConsume
trait ACMapConsume

Merge two maps with accumulation: drain dest into self, summing values that share a key.

trait ACMapContains ppvm_traits::traits::map::ACMapContains
trait ACMapContains<S, V, H, W>

Membership queries — (key, value) exact match or with a custom predicate on the value.

trait ACMapInsert ppvm_traits::traits::map::ACMapInsert
trait ACMapInsert<S, V, H, W>

Combined in-place modify + insert pattern used to express branching gates (where one input entry can produce several output entries).

trait ACMapIter ppvm_traits::traits::map::ACMapIter
trait ACMapIter<'a>

Borrowing iteration over an ACMap. Lives in its own trait so that implementations may pick their own item / iterator types.

trait ACMapMulAssign ppvm_traits::traits::map::ACMapMulAssign
trait ACMapMulAssign<V, H>

Scalar *= semantics for an ACMap: multiply every value by a constant.

trait ACMapRetain ppvm_traits::traits::map::ACMapRetain
trait ACMapRetain<S, V, H, W>

Drop entries that don't satisfy a predicate — used by truncation strategies.

trait ACMapScale ppvm_traits::traits::map::ACMapScale
trait ACMapScale<S, V, H, W>

In-place per-entry transformation of values.

trait LossyMeasure ppvm_traits::traits::measure::LossyMeasure
trait LossyMeasure

Loss-aware Z-basis measurement.

trait Measure ppvm_traits::traits::measure::Measure
trait Measure

Projective Z-basis measurement returning a bare boolean outcome.

trait AmplitudeDamping ppvm_traits::traits::noise::AmplitudeDamping
trait AmplitudeDamping<T>

Amplitude-damping channel (single qubit).

trait AsymmetricLossChannel ppvm_traits::traits::noise::AsymmetricLossChannel
trait AsymmetricLossChannel<T>

State-dependent ("asymmetric") single-qubit loss channel: a qubit is lost from |0⟩ with probability p0 and from |1⟩ with probability p1. Unlike LossChannel, the total loss probability depends on the qubit's populations, so th…

Full docstring

State-dependent ("asymmetric") single-qubit loss channel: a qubit is lost from |0⟩ with probability p0 and from |1⟩ with probability p1. Unlike LossChannel, the total loss probability depends on the qubit's populations, so the channel reads the current ⟨Z⟩.

trait CorrelatedLossChannel ppvm_traits::traits::noise::CorrelatedLossChannel
trait CorrelatedLossChannel<T>

Correlated two-qubit loss channel.

trait Depolarizing ppvm_traits::traits::noise::Depolarizing
trait Depolarizing<T>

Single-qubit depolarizing channel.

trait Depolarizing2 ppvm_traits::traits::noise::Depolarizing2
trait Depolarizing2<T>

Two-qubit depolarizing channel.

trait LossChannel ppvm_traits::traits::noise::LossChannel
trait LossChannel<T>

Single-qubit loss channel — with probability p, mark the qubit as lost (Pauli::L).

trait PauliError ppvm_traits::traits::noise::PauliError
trait PauliError<T>

Single-qubit Pauli error channel — apply X, Y, or Z with the three given probabilities.

trait PauliErrorAll ppvm_traits::traits::noise::PauliErrorAll
trait PauliErrorAll<T>

Apply the same single-qubit Pauli error channel uniformly to every qubit in the system.

trait ResetLossChannel ppvm_traits::traits::noise::ResetLossChannel
trait ResetLossChannel<T>

Reset the loss bit on a qubit — used to model a re-cooling / re-loading event that brings a previously-lost atom back.

trait TwoQubitPauliError ppvm_traits::traits::noise::TwoQubitPauliError
trait TwoQubitPauliError<T>

Two-qubit Pauli error channel.

trait Reset ppvm_traits::traits::reset::Reset
trait Reset

Reset one qubit to a computational/Pauli basis state.

trait PauliStorage ppvm_traits::traits::storage::PauliStorage
trait PauliStorage

Backing storage for a PauliWord — a fixed-size, Copy-able block of bits (typically [u8; N] or [u64; N]).

Full docstring

Backing storage for a PauliWord — a fixed-size, Copy-able block of bits (typically [u8; N] or [u64; N]).

The bytemuck::Pod bound guarantees the storage is a plain-old-data type with no padding and all bit patterns valid, which lets PauliWord::rehash view it as a &[u8] for fast byte-slice hashing without unsafe. Every concrete storage used here ([u8; N], [u64; N]) is already Pod.

trait Strategy ppvm_traits::traits::strategy::Strategy
trait Strategy

A truncation policy applied to a PauliSum during Pauli propagation.

Full docstring

A truncation policy applied to a PauliSum during Pauli propagation.

The strategy controls two things: the initial capacity allocated for the underlying map (estimating how many Pauli paths the simulation is expected to generate) and the cut applied when truncate is called explicitly. Implementations include NoStrategy, the coefficient-magnitude threshold, the max-Pauli-weight bound, etc.

trait Trace ppvm_traits::traits::trace::Trace
trait Trace<'a, RHS>

Trait for computing trace(self * RHS).

Full docstring

Trait for computing trace(self * RHS).

If a type implements Trace, a corresponding TraceBy implementation is also provided automatically.

trait PauliIter ppvm_traits::traits::word_trait::PauliIter
trait PauliIter

Iterate over a Pauli word slot-by-slot.

trait PauliWordTrait ppvm_traits::traits::word_trait::PauliWordTrait
trait PauliWordTrait

Word-level Pauli operations. Types implementing this trait automatically gain crate::traits::Clifford and crate::traits::CliffordExtensions behavior via blanket impls in the crate::traits::clifford module, using get_lbit / `g…

Full docstring

Word-level Pauli operations. Types implementing this trait automatically gain crate::traits::Clifford and crate::traits::CliffordExtensions behavior via blanket impls in the crate::traits::clifford module, using get_lbit / get_xbit / set_xbit / set_zbit / rehash to transform Pauli words.

Word-level vs. state-level gate semantics

The blanket Clifford impl applies gates at the bit level of a single Pauli word. X / Y / Z are bit-level no-ops on a Pauli word — they affect phase, not the X/Z bits — so word.x(i), word.y(i), word.z(i) are deliberately silent. Phase is tracked separately by PhasedPauliWord, which implements Clifford manually.

If you need a word representation whose gate behavior is not pure bit manipulation (phase tracking, fused multi-qubit updates, alternative loss semantics), do not implement PauliWordTrait on it — define a specialized Clifford impl instead, the way PhasedPauliWord does. Implementing both PauliWordTrait and a custom impl Clifford for ... for the same type will not compile: the blanket impl overlaps with your custom impl (coherence error), not silently shadows it.

ppvm-pauli-word

Packed Pauli strings: `PauliWord`, phased, lossy, and pattern variants.

module ppvm_pauli_word ppvm_pauli_word
mod ppvm_pauli_word

Packed Pauli-word types: PauliWord, PhasedPauliWord, LossyPauliWord, and PauliPattern. Built on the ppvm-traits foundation.

struct LossyPauliWord ppvm_pauli_word::loss::data::LossyPauliWord
struct LossyPauliWord<A, S>

A PauliWord-like type that additionally tracks per-qubit loss.

Full docstring

A PauliWord-like type that additionally tracks per-qubit loss.

In neutral-atom hardware (and in any loss-aware error model), a measurement can return "lost" instead of 0 or 1. LossyPauliWord adds a parallel lbits array marking which qubits have been lost; a set loss bit excludes that qubit from the standard Pauli operations and shows up as the [Pauli::L] symbol.

Examples

use ppvm_traits::char::Pauli;
use ppvm_pauli_word::loss::LossyPauliWord;
use ppvm_traits::traits::PauliWordTrait;

let w: LossyPauliWord<[u8; 1]> = "XLZL".into();
assert_eq!(w.weight(), 4);          // X, L, Z, L are all non-identity
assert_eq!(w.loss_weight(), 2);     // two qubits are lost
assert!(w.is(1, Pauli::L));
assert!(w.is(0, Pauli::X));
struct PauliPattern ppvm_pauli_word::pattern::data::PauliPattern
struct PauliPattern

A Pauli pattern representing a set of matching Pauli words.

Full docstring

A Pauli pattern representing a set of matching Pauli words.

Example

[XY]2Z3 represents X2Z3 or Y2Z3. Z? represents any Pauli word with I or Z.

struct EnumMatchesPauliPattern ppvm_pauli_word::pattern::enumerate::EnumMatchesPauliPattern
struct EnumMatchesPauliPattern<'a, A>

Iterator over the concrete [PauliWord]s accepted by a [PauliPattern].

struct PhasedPauliWord ppvm_pauli_word::phase::data::PhasedPauliWord
struct PhasedPauliWord<A, H, W>

A PauliWord paired with one of the four fourth-roots of unity.

Full docstring

A PauliWord paired with one of the four fourth-roots of unity.

The phase field encodes the scalar prefactor:

phase scalar
0 +1
1 +i
2 -1
3 -i

(i.e. the low bit is the imaginary flag and the high bit is the sign.)

Examples

use ppvm_pauli_word::phase::PhasedPauliWord;

// Parse from a "[sign][i]<PauliString>" literal.
let pw: PhasedPauliWord<u64> = "+iXYZI".into();
assert_eq!(pw.n_qubits(), 4);
assert_eq!(pw.phase, 1);            // +i
assert!(pw.is_positive());

let neg: PhasedPauliWord<u64> = "-XYZI".into();
assert_eq!(neg.phase, 2);           // -1
assert!(!neg.is_positive());
struct PauliWord ppvm_pauli_word::word::data::PauliWord
struct PauliWord<A, S, REHASH>

A fixed-width Pauli string stored as parallel x and z bit arrays.

Full docstring

A fixed-width Pauli string stored as parallel x and z bit arrays.

Each qubit slot is encoded by two bits, (x, z), giving the four Pauli operators I = (0,0), X = (1,0), Z = (0,1), Y = (1,1) — the same encoding stabilizer-formalism tools use. The bit arrays live in a single PauliStorage blob (typically [u8; N] or [u64; N]), so a PauliWord<[u8; 1]> packs up to 8 qubits, [u8; 2] up to 16, etc.

A cached hash speeds up use as a map key; pass REHASH = false if you build words in bulk and want to control rehashing manually.

Examples

use ppvm_traits::char::Pauli;
use ppvm_traits::traits::PauliWordTrait;
use ppvm_pauli_word::word::PauliWord;

// Build a word from a string …
let w: PauliWord<[u8; 1]> = "XYZI".into();
assert_eq!(w.n_qubits(), 4);
assert_eq!(w.get(0), Pauli::X);
assert_eq!(w.get(3), Pauli::I);

// … or build it slot-by-slot.
let mut w2: PauliWord<[u8; 1]> = PauliWord::new(2);
w2.set(0, Pauli::X).set(1, Pauli::Y);
assert_eq!(w2.to_string(), "XY");
assert_eq!(w2.weight(), 2);
enum NotIdentity ppvm_pauli_word::pattern::data::NotIdentity
enum NotIdentity

A single-qubit Pauli that is not the identity: X, Y, or Z. Encoded so the low two bits match Pauli (X = 1, Z = 2, Y = 3), which lets From<NotIdentity> for Pauli be a no-op transmute.

trait Contains ppvm_pauli_word::pattern::contains::Contains
trait Contains<T>

Membership test for pattern types.

Full docstring

Membership test for pattern types.

Implemented by Pauli patterns over symbols (Contains<Pauli>) and over whole words (Contains<W: PauliIter>); used by the masking machinery to ask "does this pattern accept this concrete word?"

ppvm-pauli-sum

The `PauliSum` engine, truncation strategies, and concrete config bundles.

module ppvm_pauli_sum ppvm_pauli_sum
mod ppvm_pauli_sum

PauliSum / LossyPauliSum Pauli-propagation engine, truncation strategies, and pre-built Config bundles. Built on ppvm-traits and ppvm-pauli-word.

module dashmap ppvm_pauli_sum::config::dashmap
mod dashmap

Pre-built configs backed by dashmap::DashMap for concurrent access. Native-only: dashmap pulls rayon, which needs OS threads, so this module is unavailable on wasm32.

module fx64hash ppvm_pauli_sum::config::fx64hash
mod fx64hash

Pre-built configs using rustc-hash's FxHasher and f64 coefficients.

module fxhash ppvm_pauli_sum::config::fxhash
mod fxhash

Pre-built configs using FxHasher.

module gxhash ppvm_pauli_sum::config::gxhash
mod gxhash

Pre-built configs using gxhash — fast on platforms with AES hardware acceleration. Requires the gxhash feature.

module indexmap ppvm_pauli_sum::config::indexmap
mod indexmap

Pre-built configs backed by indexmap::IndexMap, preserving insertion order — useful for deterministic iteration and snapshot testing.

module prelude ppvm_pauli_sum::prelude
mod prelude

Drop-in replacement for the old ppvm_runtime::prelude.

struct ByteFxHash ppvm_pauli_sum::config::dashmap::ByteFxHash
struct ByteFxHash<N, C, St, W>

DashMap-backed concurrent Config with [u8; N] storage and FxHasher.

struct ByteGxHash ppvm_pauli_sum::config::dashmap::ByteGxHash
struct ByteGxHash<N, C, St, W>

DashMap-backed concurrent Config with [u8; N] storage and gxhash.

struct Byte8 ppvm_pauli_sum::config::fx64hash::Byte8
struct Byte8<N, C, St, W>

HashMap-backed Config with native-word ([usize; N]) storage and FxHasher.

Full docstring

HashMap-backed Config with native-word ([usize; N]) storage and FxHasher.

The storage element is usize, i.e. the target's native machine word: u64 on 64-bit targets (identical layout and performance to a hardcoded [u64; N]) and u32 on 32-bit targets such as wasm32. Using usize rather than u64 keeps this config available on every target — bitvec only implements BitStore for u64 on 64-bit pointer widths, but always implements it for usize. (The Byte8 name refers to the 64-bit word this config packs into on native targets.)

struct Byte ppvm_pauli_sum::config::fxhash::Byte
struct Byte<N, C, St, W>

HashMap-backed Config with [u8; N] storage and FxHasher.

struct Byte ppvm_pauli_sum::config::gxhash::Byte
struct Byte<N, C, St, W>

HashMap-backed Config with [u8; N] storage and gxhash.

struct ByteFxHash ppvm_pauli_sum::config::indexmap::ByteFxHash
struct ByteFxHash<N, C, St, W>

IndexMap-backed Config with [u8; N] storage and FxHasher.

struct ByteGxHash ppvm_pauli_sum::config::indexmap::ByteGxHash
struct ByteGxHash<N, C, St, W>

IndexMap-backed Config with [u8; N] storage and gxhash.

Full docstring

IndexMap-backed Config with [u8; N] storage and gxhash.

gxhash is AES-based and native-only, so this config is unavailable on wasm32; use ByteFxHash there.

struct CoefficientThreshold ppvm_pauli_sum::strategy::CoefficientThreshold
struct CoefficientThreshold

Drop terms whose coefficient magnitude falls below the given threshold. Defaults to 1e-12.

Full docstring

Drop terms whose coefficient magnitude falls below the given threshold. Defaults to 1e-12.

Examples

use ppvm_pauli_sum::prelude::*;
use ppvm_pauli_sum::strategy::CoefficientThreshold;

let strict = CoefficientThreshold(1e-6);
let mut state: PauliSum<config::indexmap::ByteFxHashF64<1, CoefficientThreshold>> =
    PauliSum::builder().n_qubits(2).strategy(strict).build();
state += ("ZZ", 1.0);
state += ("XX", 1e-9);              // below threshold
state.truncate();
assert_eq!(state.len(), 1);         // the XX term was dropped
struct CombinedStrategy ppvm_pauli_sum::strategy::CombinedStrategy
struct CombinedStrategy<S1, S2>

Two strategies run in sequence: S1 then S2.

Full docstring

Two strategies run in sequence: S1 then S2.

The capacity hint is the smaller of the two; truncation applies both policies in order, so use this when you want, e.g., "drop by coefficient threshold and cap maximum Pauli weight".

struct MaxLossWeight ppvm_pauli_sum::strategy::MaxLossWeight
struct MaxLossWeight

Drop terms whose loss weight (number of lost qubits) exceeds the given bound. Only meaningful for LossyPauliWord.

struct MaxPauliWeight ppvm_pauli_sum::strategy::MaxPauliWeight
struct MaxPauliWeight

Drop terms whose Pauli weight (number of non-identity slots) exceeds the given bound.

Full docstring

Drop terms whose Pauli weight (number of non-identity slots) exceeds the given bound.

Examples

use ppvm_pauli_sum::prelude::*;
use ppvm_pauli_sum::strategy::MaxPauliWeight;

// Keep only weight-1 terms.
let strat = MaxPauliWeight(1);
let mut state: PauliSum<config::indexmap::ByteFxHashF64<1, MaxPauliWeight>> =
    PauliSum::builder().n_qubits(3).strategy(strat).build();
state += ("XII", 1.0);              // weight 1, kept
state += ("XYI", 1.0);              // weight 2, dropped
state.truncate();
assert_eq!(state.len(), 1);
struct Empty ppvm_pauli_sum::sum::data::pauli_sum_builder::Empty
struct Empty

Represents a [State] that has [IsUnset] implemented for all members.

Full docstring

Represents a [State] that has [IsUnset] implemented for all members.

This is the initial state of the builder before any setters are called.

struct SetCapacity ppvm_pauli_sum::sum::data::pauli_sum_builder::SetCapacity
struct SetCapacity<S>

Represents a [State] that has [IsSet] implemented for [State::Capacity].

Full docstring

Represents a [State] that has [IsSet] implemented for [State::Capacity].

The state for all other members is left the same as in the input state.

struct SetNQubits ppvm_pauli_sum::sum::data::pauli_sum_builder::SetNQubits
struct SetNQubits<S>

Represents a [State] that has [IsSet] implemented for [State::NQubits].

Full docstring

Represents a [State] that has [IsSet] implemented for [State::NQubits].

The state for all other members is left the same as in the input state.

struct SetPreserveStrings ppvm_pauli_sum::sum::data::pauli_sum_builder::SetPreserveStrings
struct SetPreserveStrings<S>

Represents a [State] that has [IsSet] implemented for [State::PreserveStrings].

Full docstring

Represents a [State] that has [IsSet] implemented for [State::PreserveStrings].

The state for all other members is left the same as in the input state.

struct SetStrategy ppvm_pauli_sum::sum::data::pauli_sum_builder::SetStrategy
struct SetStrategy<S>

Represents a [State] that has [IsSet] implemented for [State::Strategy].

Full docstring

Represents a [State] that has [IsSet] implemented for [State::Strategy].

The state for all other members is left the same as in the input state.

struct PauliSum ppvm_pauli_sum::sum::data::PauliSum
struct PauliSum<T>

A sparse formal sum Σ cᵢ Pᵢ of Pauli strings.

Full docstring

A sparse formal sum Σ cᵢ Pᵢ of Pauli strings.

The central data type of the Pauli-propagation backend. Keys are PauliWord-shaped Pauli strings; values are numeric coefficients. Generic over a Config that fixes the concrete storage / hasher / coefficient / strategy.

Internally PauliSum holds two maps — a primary and an auxiliary — and swaps between them during gate propagation to avoid repeated allocations. The [PauliSum::data] / [PauliSum::aux] accessors expose the current orientation; most callers will only ever touch the primary side via the high-level gate / measurement traits.

Examples

Heisenberg-picture propagation of ZZ through the GHZ circuit:

use ppvm_pauli_sum::prelude::*;

let mut state: PauliSum<config::indexmap::ByteFxHashF64<1>> =
    PauliSum::builder().n_qubits(2).build();
state += ("ZZ", 1.0);

// Circuit: H(0); CNOT(0, 1) — apply in reverse for Heisenberg propagation.
state.cnot(0, 1);
state.h(0);

// ZZ → IZ under the GHZ circuit, with coefficient 1.0.
assert_eq!(state.len(), 1);
struct PauliSumBuilder ppvm_pauli_sum::sum::data::PauliSumBuilder
struct PauliSumBuilder<T, S>

Use builder syntax to set the inputs and finish with build().

trait IsComplete ppvm_pauli_sum::sum::data::pauli_sum_builder::IsComplete
trait IsComplete

Marker trait that indicates that all required members are set.

Full docstring

Marker trait that indicates that all required members are set.

In this state, you can finish building by calling the method PauliSumBuilder::build()

trait State ppvm_pauli_sum::sum::data::pauli_sum_builder::State
trait State

Builder's type state specifies if members are set or not (unset).

Full docstring

Builder's type state specifies if members are set or not (unset).

You can use the associated types of this trait to control the state of individual members with the [IsSet] and [IsUnset] traits. You can change the state of the members with the Set* structs available in this module.

type alias ByteFxHashF64 ppvm_pauli_sum::config::dashmap::ByteFxHashF64
type ByteFxHashF64

ByteFxHash specialised to f64 coefficients.

type alias ByteGxHashF64 ppvm_pauli_sum::config::dashmap::ByteGxHashF64
type ByteGxHashF64

ByteGxHash specialised to f64 coefficients.

type alias Byte8F64 ppvm_pauli_sum::config::fx64hash::Byte8F64
type Byte8F64

Byte8 specialised to f64 coefficients.

type alias ByteF64 ppvm_pauli_sum::config::fxhash::ByteF64
type ByteF64

Byte specialised to f64 coefficients.

type alias ByteF64 ppvm_pauli_sum::config::gxhash::ByteF64
type ByteF64

Byte specialised to f64 coefficients.

type alias ByteFxHashF64 ppvm_pauli_sum::config::indexmap::ByteFxHashF64
type ByteFxHashF64

ByteFxHash specialised to f64 coefficients.

type alias ByteGxHashF64 ppvm_pauli_sum::config::indexmap::ByteGxHashF64
type ByteGxHashF64

ByteGxHash specialised to f64 coefficients.

macro impl_op_mul_assign_coefficient ppvm_pauli_sum::impl_op_mul_assign_coefficient
impl_op_mul_assign_coefficient!

Implement multiplication by a scalar coefficient for PauliSum. Use this macro to implement MulAssign for other scalar types if needed. This macro will forward the multiplication to the underlying map's mul_assign method.

ppvm-tableau

Generalized stabilizer tableau simulator (Clifford + non-Clifford).

module ppvm_tableau ppvm_tableau
mod ppvm_tableau

Generalized stabilizer-tableau simulator built on top of the ppvm core crates (ppvm-traits and ppvm-pauli-word).

Full docstring

Generalized stabilizer-tableau simulator built on top of the ppvm core crates (ppvm-traits and ppvm-pauli-word).

Provides a forward-evolving state representation using the stabilizer formalism, extended to non-Clifford gates by tracking a sparse vector of coefficients indexed over bitstrings. The two top-level types are data::Tableau (pure Clifford) and data::GeneralizedTableau (Clifford + non-Clifford with sparse coefficient tracking).

Quick example

Prepare a Bell pair and verify the two measurements are perfectly correlated:

use ppvm_tableau::prelude::*;
use ppvm_pauli_sum::config::fxhash::ByteF64;

let mut tab: GeneralizedTableau<ByteF64<1>> =
    GeneralizedTableau::new_with_seed(2, 1e-12, 0);
tab.h(0);
tab.cnot(0, 1);

let r0 = LossyMeasure::measure(&mut tab, 0);
let r1 = LossyMeasure::measure(&mut tab, 1);
assert_eq!(r0, r1);
module display ppvm_tableau::display
mod display

Display implementations for tableau types.

module gates ppvm_tableau::gates
mod gates

Gate implementations (Clifford, T, rotations).

module measure ppvm_tableau::measure
mod measure

Z-basis measurement, including loss-aware variants.

module noise ppvm_tableau::noise
mod noise

Noise channels: depolarizing, Pauli error, loss.

module prelude ppvm_tableau::prelude
mod prelude

Convenience re-exports for downstream code.

module tableau_index ppvm_tableau::tableau_index
mod tableau_index

TableauIndex — abstraction over the bitstring index type (usize, u128, U256, …).

module tableau_like ppvm_tableau::tableau_like
mod tableau_like

TableauLike — shared trait for stabilizer-tableau backends. TableauLike trait: shared interface for stabilizer-tableau backends.

Full docstring

TableauLike — shared trait for stabilizer-tableau backends. TableauLike trait: shared interface for stabilizer-tableau backends.

Any type implementing TableauLike gets default implementations of single- and two-qubit Pauli noise channels (Depolarizing, PauliError, Depolarizing2, TwoQubitPauliError). New tableau backends only need to provide TableauLike::rng_mut and (optionally) override TableauLike::is_qubit_lost.

struct GeneralizedTableau ppvm_tableau::data::GeneralizedTableau
struct GeneralizedTableau<T, IndexType, SparseVectorType>

A Tableau extended with sparse coefficient tracking to handle non-Clifford gates.

Full docstring

A Tableau extended with sparse coefficient tracking to handle non-Clifford gates.

Non-Clifford gates (T, rotations) split a single tableau into a sum of weighted branches indexed by bitstrings. GeneralizedTableau stores those weights in a SparseVector keyed by an IndexType. Choose:

  • IndexType = usize for up to 64 qubits,
  • IndexType = u128 for up to 128,
  • IndexType = bnum::types::U256 and friends for the very wide regime.

Per-qubit loss is tracked in is_lost; gates respect it automatically.

Examples

Prepare a Bell pair and sample one shot. With a fixed seed the two measurements are perfectly correlated on every shot:

use ppvm_pauli_sum::config::fxhash::ByteF64;
use ppvm_traits::traits::{Clifford, LossyMeasure};
use ppvm_tableau::data::GeneralizedTableau;

let mut tab: GeneralizedTableau<ByteF64<1>> =
    GeneralizedTableau::new_with_seed(2, 1e-12, 0);
tab.h(0);
tab.cnot(0, 1);

let r0 = LossyMeasure::measure(&mut tab, 0);
let r1 = LossyMeasure::measure(&mut tab, 1);
assert_eq!(r0, r1);

Non-Clifford gates work through the same interface — apply a T gate followed by T† and the state is unchanged:

use ppvm_pauli_sum::config::fxhash::ByteF64;
use ppvm_traits::traits::{Clifford, TGate};
use ppvm_tableau::data::GeneralizedTableau;

let mut tab: GeneralizedTableau<ByteF64<1>> =
    GeneralizedTableau::new_with_seed(1, 1e-12, 0);
tab.h(0);
tab.t(0);
tab.t_dag(0);
// T followed by T† is the identity; the |+⟩ state is restored.
struct Tableau ppvm_tableau::data::Tableau
struct Tableau<T>

A 2n-row stabilizer / destabilizer tableau.

Full docstring

A 2n-row stabilizer / destabilizer tableau.

Rows 0..n hold the destabilizers; rows n..2n hold the stabilizers. Each row is a PhasedPauliWord tracking both its X/Z bits and a phase in {±1, ±i}. Implements every Clifford-only operation natively (Hadamard, phase, CNOT, CZ, etc.).

Examples

use ppvm_pauli_sum::config::fxhash::ByteF64;
use ppvm_traits::traits::Clifford;
use ppvm_tableau::data::Tableau;

let mut tab: Tableau<ByteF64<1>> = Tableau::new(2);
tab.h(0);
tab.cnot(0, 1);
assert_eq!(tab.n_qubits, 2);
assert_eq!(tab.stabilizers().len(), 2);
struct MeasureScratch ppvm_tableau::measure::MeasureScratch
struct MeasureScratch<I, R>

Per-measurement scratch buffers, reused across qubits within a single measure_all invocation — and, when threaded through measure_all_with_scratch, across many shots of a sampler too. R…

Full docstring

Per-measurement scratch buffers, reused across qubits within a single measure_all invocation — and, when threaded through measure_all_with_scratch, across many shots of a sampler too. Reusing one scratch keeps the case-a HashMap and the b-entries Vec out of the per-shot allocator churn.

  • odd_phase_mask is lazily computed and cached until the destabilizers change (i.e. until a case-a measurement runs update_tableau_according_to_outcome).
  • coeff_map is the case-a HashMap holding (idx → amplitude) between the overlap, partition, and merge passes.
  • b_entries is the case-a partition's "k-bit = 1" scratch Vec.

Construct one per active sampling thread; the type is not meant to be shared across threads concurrently.

trait SparseVector ppvm_tableau::sparsevec::SparseVector
trait SparseVector<T, I>

A sparse vector keyed by index type I with values of type T.

Full docstring

A sparse vector keyed by index type I with values of type T.

Used by GeneralizedTableau to store the coefficient over each branching bitstring. The default implementation is Vec<(T, I)>; alternative backings (BTreeMap, HashMap, etc.) can be provided by downstream code.

trait TableauIndex ppvm_tableau::tableau_index::TableauIndex
trait TableauIndex

Bit-string index type used by GeneralizedTableau to address individual branches of its sparse coefficient vector.

Full docstring

Bit-string index type used by GeneralizedTableau to address individual branches of its sparse coefficient vector.

Blanket-implemented for every primitive (and bnum-style) integer type that supports the required bit operations. Pick:

  • usize for ≤ 64 qubits,
  • u128 for ≤ 128,
  • bnum::types::U256 / U512 / U1024 for the wide regime.
trait TableauLike ppvm_tableau::tableau_like::TableauLike
trait TableauLike

A stabilizer-tableau-like backend that supports Clifford gates and an RNG.

Full docstring

A stabilizer-tableau-like backend that supports Clifford gates and an RNG.

Implementing this trait grants default implementations of the Pauli noise channels via [TableauLike::depolarize_impl] and friends. The associated Rng type lets each backend choose its own RNG; nothing in this trait depends on SmallRng.

function symplectic_inner ppvm_tableau::data::symplectic_inner
fn symplectic_inner(alpha, beta) -> …

Symplectic inner product of two tableau index values — the count of shared set bits, used in stabilizer phase calculations.

ppvm-sym

Symbolic, parametric Pauli propagation.

module ppvm_sym ppvm_sym
mod ppvm_sym

Symbolic, parametric Pauli propagation.

Full docstring

Symbolic, parametric Pauli propagation.

ppvm-sym provides a Term type that represents a polynomial in sines and cosines of symbolic parameters. It is used by ppvm to propagate Pauli operators through parametric circuits (e.g., variational ansätze) without committing to specific angle values until the very end.

Quick example

Build the symbolic expression sin(x0) * cos(x1), then evaluate it at a concrete (x0, x1):

use ppvm_sym::Term;

let expr = Term::var(0).sin() * Term::var(1).cos();

let v = expr.eval(&[0.5, 1.0]).unwrap();
let expected = 0.5_f64.sin() * 1.0_f64.cos();
assert!((v - expected).abs() < 1e-12);
struct Prod ppvm_sym::term::Prod
struct Prod

<coeff> sin^m cos^n

Full docstring

<coeff> sin^m cos^n

A single product of trigonometric atoms over symbolic variables. Sines and cosines are grouped by variable id; powers are tracked as totals so we can quickly compute and bound them. The order of variables is kept canonical (ascending) so two Prod values representing the same monomial compare equal.

struct Sum ppvm_sym::term::Sum
struct Sum

A formal sum c₀ + Σᵢ cᵢ · pᵢ, where each pᵢ is a Prod and cᵢ is an f64 coefficient.

struct Term ppvm_sym::term::Term
struct Term

A symbolic polynomial in sin(x_i) and cos(x_i).

Full docstring

A symbolic polynomial in sin(x_i) and cos(x_i).

Term is the public-facing wrapper around its Inner enum. It also carries two truncation parameters, applied during multiplication and addition:

Examples

use ppvm_sym::Term;

// sin²(x0) at x0 = π/2 equals 1.
let expr = Term::var(0).sin() * Term::var(0).sin();
let v = expr.eval(&[std::f64::consts::FRAC_PI_2]).unwrap();
assert!((v - 1.0).abs() < 1e-12);
  • max_sin — drop terms whose total sine power exceeds this bound.
  • min_eps — drop terms whose coefficient magnitude falls below this threshold.
enum Inner ppvm_sym::term::Inner
enum Inner

Internal representation of a Term.

Full docstring

Internal representation of a Term.

Sum holds a full formal sum; One is the optimisation for a single weighted product; Var is a bare symbolic variable used before it has been wrapped in a sin or cos; Const is a numeric scalar.