pub trait PauliEvolution {
// Required method
fn pauli_evolution(
&mut self,
pauli: &PauliString,
angle: impl Into<ParameterValue>,
qubits: &[Qubit],
) -> Result<(), CircuitError>;
}Expand description
Extension trait for Circuit to add Pauli evolution functionality.
This trait provides methods to append Pauli rotation gates to a circuit.
Required Methods§
Sourcefn pauli_evolution(
&mut self,
pauli: &PauliString,
angle: impl Into<ParameterValue>,
qubits: &[Qubit],
) -> Result<(), CircuitError>
fn pauli_evolution( &mut self, pauli: &PauliString, angle: impl Into<ParameterValue>, qubits: &[Qubit], ) -> Result<(), CircuitError>
Appends a Pauli evolution gate $e^{-i\theta/2 \cdot P}$ to the circuit.
This method implements the Pauli rotation using the basis transformation and CNOT ladder algorithm.
§Arguments
pauli- The Pauli string operator $P$ to exponentiate. Must be Hermitian (i.e., its phase must be $\pm 1$) for the evolution to be unitary.angle- The rotation angle $\theta$ (can be symbolic or fixed)qubits- The qubits to apply the operation on (must matchpauli.num_qubits)
§Returns
Ok(())- If the operation was successfully appendedErr(CircuitError)- If qubit count mismatch, PauliString has non-Hermitian phase ($\pm i$), or other error occurs
§Algorithm Details
The rotation $e^{-i\theta/2 \cdot P}$ is implemented as follows:
-
Phase Validation: The PauliString’s internal phase must be $\pm 1$ (Hermitian). If the phase is $\pm i$, an error is returned because such operators cannot generate unitary evolution.
-
Phase Absorption: The PauliString’s phase ($\pm 1$) is absorbed into the rotation angle: $\theta_{eff} = \theta \cdot \text{phase}$
-
Basis Transformation: For each qubit $i$ with non-identity Pauli $P_i$:
- $P_i = X$: Apply $H$ gate (transforms $X$ to $Z$ basis)
- $P_i = Y$: Apply $S^\dagger$ then $H$ (circuit order: $S^\dagger \to H$, i.e. $S^\dagger$ is applied first, then $H$). This transforms $Y \to Z$: $S^\dagger |y+\rangle = |x+\rangle$, $H |x+\rangle = |z+\rangle$.
- $P_i = Z$: No transformation needed
-
CNOT Chain: For non-identity qubits $[i_0, i_1, \ldots, i_{n-1}]$, apply $CNOT(i_0 \to i_1), CNOT(i_1 \to i_2), \ldots$ to accumulate parity.
-
Core Rotation: Apply $RZ(\theta_{eff})$ on the last non-identity qubit.
-
Reverse CNOT Ladder: Apply CNOT gates in reverse order.
-
Inverse Transformation: Apply inverse basis transformations.
§Global Phase
If the Pauli string consists entirely of identity operators (e.g., “III”), the operation reduces to a global phase $e^{-i\theta/2}$, which is added to the circuit’s global phase.
§Examples
use cqlib_core::circuit::Circuit;
use cqlib_core::qis::pauli::PauliString;
use cqlib_core::qis::evolution::PauliEvolution;
let mut circuit = Circuit::new(3);
let qubits = circuit.qubits();
// Create a Pauli string X ⊗ Z ⊗ I
let pauli: PauliString = "XZI".parse().unwrap();
// Apply e^(-i * π/4 * XZI)
circuit.pauli_evolution(&pauli, std::f64::consts::PI / 2.0, &qubits).unwrap();Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".