pauli_propagation¶
Dependencies¶
Included in the core package — no additional dependencies required.
Executor¶
- class qc_executor.pauli_propagation.PauliPropagationExecutor(shots=None, seed=None, log_file=None, log_level='WARNING', caching=None, cache_dir='cache', max_cache_size=None, truncate_threshold=None, max_weight=None, symmetry_strategy=None, n_jobs=1)[source]¶
Bases:
ExecutorBaseExecutor for quantum circuits using Pauli propagation (Heisenberg picture).
This executor propagates observables backward through quantum circuits, enabling efficient computation of expectation values for sparse observables.
- Parameters:
shots (
int|None) – Number of measurement shots (not used for exact simulation)seed (
int|None) – Random seed for reproducibility (not used for exact simulation)log_file (
str|None) – Path to log file (not implemented)caching (
bool|None) – Whether to use caching (not implemented yet)cache_dir (
str) – Directory for caching (not implemented yet)truncate_threshold (
float|None) – Coefficient threshold for automatic truncation (None = no truncation)max_weight (
int|None) – Maximum Pauli weight for truncation (None = no weight limit)symmetry_strategy (
SymmetryStrategy|None) – Strategy for Pauli symmetry merging (None = no merging)n_jobs (
int) – Number of worker processes for independent expectation-value evaluations (multiple circuits x observables, parameter-shift gradients). 1 (default) runs serially; -1 uses all CPU cores. Process startup on Windows (spawn) costs roughly 100 ms per worker plus import time, so parallelism pays off only for workloads with many or expensive independent evaluations.log_level (str)
max_cache_size (int | None)
- property shots: int | None¶
Return the number of shots.
- property remote: bool¶
Return False (Pauli propagation is local execution).
- transpile_operator(operator, symmetry_strategy=None)[source]¶
- Overloads:
self, operator (QuantumOperatorBase) → PauliPropagationOperator
self, operator (QuantumOperatorBase), symmetry_strategy (SymmetryStrategy) → PauliPropagationOperator
self, operator (List[QuantumOperatorBase]) → List[PauliPropagationOperator]
self, operator (List[QuantumOperatorBase]), symmetry_strategy (SymmetryStrategy) → List[PauliPropagationOperator]
- Parameters:
operator (QuantumOperatorBase | List[QuantumOperatorBase])
symmetry_strategy (SymmetryStrategy | None)
- Return type:
Transpile the operator for execution on Pauli Propagation backend.
Accepts both native PauliPropagationOperator and generic QuantumOperator types. When a list of operators is provided, each operator is transpiled and cached individually.
- Parameters:
operator (QuantumOperatorBase | List[QuantumOperatorBase]) – The quantum operator or a list of operators to transpile.
symmetry_strategy (SymmetryStrategy | None) – Strategy for symmetry handling. If provided, takes precedence over executor-level default.
- Returns:
- The
transpiled operator(s) in native format.
- Return type:
- get_truncation_stats()[source]¶
Get statistics from last truncation operation.
- Return type:
TruncationStats|None- Returns:
TruncationStats from most recent execution, or None if no truncation
Native abstraction¶
Circuit¶
- class qc_executor.pauli_propagation.PauliPropagationCircuit(num_qubits, *, gates=None, parameter_symbols=None)[source]¶
Bases:
QuantumCircuitBaseBackend-native circuit representation for Pauli propagation.
This datatype stores operations directly in the internal gate representation used by the propagation engine and does not depend on Qiskit objects.
- Parameters:
num_qubits (int)
gates (Sequence[Gate | LayerBarrier] | None)
parameter_symbols (Dict[str, sp.Symbol] | None)
- classmethod from_quantum_circuit(circuit)[source]¶
Create a PauliPropagationCircuit from a generic circuit.
- Return type:
- Parameters:
circuit (QuantumCircuitBase)
- property gates: List[Gate | LayerBarrier]¶
Return a shallow copy of gate instructions.
- property parameters: List[str]¶
Return parameter names used by the circuit.
- property parameter_symbols: Dict[str, Symbol]¶
Return a copy of the parameter-name to sympy-symbol mapping.
- property num_parameters: int¶
Return the number of free trainable parameters in the circuit.
- property is_parameterized: bool¶
Check if the wavefunction is parameterized.
- cx(control_qubit, target_qubit)[source]¶
Add CNOT gates
- Parameters:
control_qubit (int)
target_qubit (int)
- cy(control_qubit, target_qubit)[source]¶
Add CY gates
- Parameters:
control_qubit (int)
target_qubit (int)
- cz(control_qubit, target_qubit)[source]¶
Add CZ gates
- Parameters:
control_qubit (int)
target_qubit (int)
- crx(control_qubit, target_qubit, angle)[source]¶
Add CRX gates
- Parameters:
control_qubit (int)
target_qubit (int)
angle (float)
- cry(control_qubit, target_qubit, angle)[source]¶
Add CRX gates
- Parameters:
control_qubit (int)
target_qubit (int)
angle (float)
- crz(control_qubit, target_qubit, angle)[source]¶
Add CRX gates
- Parameters:
control_qubit (int)
target_qubit (int)
angle (float)
- rxx(control_qubit, target_qubit, angle)[source]¶
Add RXX gates
- Parameters:
control_qubit (int)
target_qubit (int)
angle (float)
- ryy(control_qubit, target_qubit, angle)[source]¶
Add RYY gates
- Parameters:
control_qubit (int)
target_qubit (int)
angle (float)
- rzz(control_qubit, target_qubit, angle)[source]¶
Add RZZ gates
- Parameters:
control_qubit (int)
target_qubit (int)
angle (float)
- rzx(control_qubit, target_qubit, angle)[source]¶
Add RZX gates
- Parameters:
control_qubit (int)
target_qubit (int)
angle (float)
- compose(qc, qubits)[source]¶
Compose two quantum circuits.
- Return type:
- Parameters:
qc (QuantumCircuitBase)
qubits (List[int])
- assign_parameters(parameters)[source]¶
Bind symbolic parameters to concrete values.
- Parameters:
parameters (
Dict[str,float]) – Dict mapping parameter names to float values- Return type:
- Returns:
New circuit with parameters substituted
- replace_gate(index, gate)[source]¶
Return a new circuit with the gate at
indexreplaced.Unreplaced gate objects are shared with this circuit; gates are immutable after construction, so this is safe.
- Return type:
- Parameters:
index (int)
gate (Gate | LayerBarrier)
Operator¶
- class qc_executor.pauli_propagation.PauliPropagationOperator(paulis=None, coeffs=None, num_qubits=None, pauli_sum=None, symmetry_strategy=None, *, parametric_coeffs=None, parameter_symbols=None)[source]¶
Bases:
QuantumOperatorBaseBackend-native operator representation for Pauli propagation.
- Parameters:
paulis (List[str] | None)
coeffs (List[complex | 'sp.Expr'] | None)
num_qubits (int | None)
pauli_sum (PauliSum | None)
symmetry_strategy (SymmetryStrategy | None)
parametric_coeffs (Dict[int, sp.Expr] | None)
parameter_symbols (Dict[str, sp.Symbol] | None)
- classmethod from_quantum_operator(operator, symmetry_strategy=None)[source]¶
- Overloads:
cls, operator (QuantumOperatorBase) → PauliPropagationOperator
cls, operator (QuantumOperatorBase), symmetry_strategy (SymmetryStrategy) → PauliPropagationOperator
- Parameters:
operator (QuantumOperatorBase)
symmetry_strategy (SymmetryStrategy | None)
- Return type:
Create a PauliPropagationOperator from a generic operator.
- property pauli_sum: PauliSum¶
Return a copy of the underlying PauliSum.
- property symmetry¶
Return the symmetry strategy of the underlying PauliSum.
- property has_active_symmetry: bool¶
Return True if a non-trivial symmetry strategy is active.
- property num_qubits: int¶
Return the number of qubits in the circuit.
- property num_paulis: int¶
Return the number of Paulis in the operator.
- property paulis: List[str]¶
Return the list of Paulis.
- property coeffs: List[complex]¶
Return the list of coefficients.
- property is_parametrized: bool¶
Return True if the operator is parametrized.
- property parameters: List[str]¶
Return the parameters of the operator.
- Returns:
List of parameters.
- property parameter_symbols: Dict[str, Symbol]¶
Return a copy of the parameter-name to sympy-symbol mapping.
- property parametric_coeffs: Dict[int, Expr]¶
Return a copy of the term to symbolic-coefficient mapping.
- property num_parameters: int¶
Return the number of parameters in the operator.
- Returns:
Number of parameters.
- assign_parameters(parameters)[source]¶
Bind symbolic parameters to concrete values.
- Parameters:
parameters (
Dict[str,float]) – Dict mapping parameter names to float values- Return type:
- Returns:
New operator with parameters substituted
- adjoint()[source]¶
Return the adjoint of the operator.
- Return type:
- Returns:
Adjoint of the operator.
- apply_layout(layout)[source]¶
Apply a layout to the operator.
- Parameters:
layout (List[int]) – Layout to apply.
- Return type:
- Returns:
Operator with applied layout.
- compose(other)[source]¶
Compose the operator with another operator.
- Parameters:
other (QuantumOperatorBase) – Operator to compose with.
- Return type:
- Returns:
Composed operator.
- append(pauli, coeff=None)[source]¶
Append another operator to the current operator.
- Parameters:
other (QuantumOperatorBase) – Operator to append.
pauli (str)
- Return type:
- Returns:
Appended operator.
- transpose()[source]¶
Return the transpose of the operator.
- Return type:
- Returns:
Transpose of the operator.
- conjugate()[source]¶
Return the conjugate of the operator.
- Return type:
- Returns:
Conjugate of the operator.
- group_commuting()[source]¶
Group commuting operators.
- Return type:
List[PauliPropagationOperator]- Returns:
List of commuting operators.
- property is_unitary: bool¶
Return True if the operator is unitary.
- Returns:
True if the operator is unitary.
- property is_real: bool¶
Return True if the operator is real.
- Returns:
True if the operator is real.
- property is_imaginary: bool¶
Return True if the operator is imaginary.
- Returns:
True if the operator is imaginary.
Other classes¶
- class qc_executor.pauli_propagation.SymmetryStrategy[source]¶
Bases:
ABCAbstract base class for symmetry strategies.
Symmetry strategies define how Pauli terms are grouped into equivalence classes. Each strategy must implement canonical_representative() to map a Pauli term to its canonical form.
- Canonical Representative:
A unique representative element from each equivalence class under the symmetry transformation. Terms with the same canonical representative are considered equivalent and can be merged (coefficients summed).
Example
For qubit permutation symmetry, the strings XXY, XYX, YXX all have the same multiset {X, X, Y} and should map to the same canonical form.
- Implementation Notes:
Pauli terms are encoded as integers (2 bits per qubit)
Encoding: I=00, X=01, Y=10, Z=11 (little-endian)
canonical_representative() must be deterministic
canonical_representative() should be fast (called many times)
- abstractmethod canonical_representative(term, nqubits)[source]¶
Compute canonical representative of a Pauli term.
Maps a Pauli term to its canonical form under this symmetry. All terms in the same equivalence class must map to the same canonical.
- Parameters:
term (
int) – Pauli term encoded as integer (2 bits per qubit, little-endian)nqubits (
int) – Number of qubits
- Return type:
int- Returns:
Canonical representative (integer, same encoding as input)
- abstract property name: str¶
Return human-readable name of this symmetry strategy.
Used for debugging, logging, and statistics tracking.
- class qc_executor.pauli_propagation.NoSymmetry[source]¶
Bases:
SymmetryStrategyIdentity symmetry strategy (no merging).
This strategy performs no merging - each Pauli term is its own canonical representative. Used as the default symmetry when no specific symmetry is requested.
- Useful for:
Backward compatibility (default behavior)
Baseline comparisons (measuring impact of symmetry merging)
Debugging (disable merging without changing code structure)
- Performance:
O(1) per canonical call (identity function)
Zero computational overhead
- canonical_representative(term, nqubits)[source]¶
Return term unchanged (identity function).
- Parameters:
term (
int) – Pauli term encoded as integernqubits (
int) – Number of qubits (unused)
- Return type:
int- Returns:
The input term unchanged
- property name: str¶
Return ‘no_symmetry’ as identifier.
- class qc_executor.pauli_propagation.PermutationSymmetry[source]¶
Bases:
SymmetryStrategyQubit permutation symmetry (S_n) using sorted multiset canonical form.
Groups Pauli terms that differ only by qubit permutations. The canonical representative is the term with Paulis sorted lexicographically (I < X < Y < Z).
- Mathematical Background:
Two Pauli strings P and Q are in the same orbit under S_n (symmetric group of n elements) if they have the same multiset of local Pauli operators.
Example: XXY, XYX, YXX all have multiset {X, X, Y} → same orbit
- Implementation:
Uses O(n) bit manipulation without lookup tables. Canonical form is computed by counting occurrences of each Pauli type and reconstructing in sorted order.
- Algorithm Complexity:
Time: O(n) per canonical computation (one pass to count, one to reconstruct) Space: O(1) (fixed-size counter array [4])
Scales efficiently to 100+ qubits.
Example
>>> sym = PermutationSymmetry() >>> # Encode XXY, XYX, YXX at 3 qubits >>> term1 = 0x05 # XXY binary: 010001 >>> term2 = 0x09 # XYX binary: 100001 >>> term3 = 0x06 # YXX binary: 000110 >>> sym.canonical_representative(term1, 3) # All map to same value >>> sym.canonical_representative(term2, 3) >>> sym.canonical_representative(term3, 3)
- canonical_representative(term, nqubits)[source]¶
Compute canonical Pauli term under qubit permutations.
The canonical form is reconstructed from the multiset of local Pauli symbols in sorted order
I < X < Y < Z.Uses whole-word popcounts to count Pauli types and repeated-pattern arithmetic to reconstruct the sorted form, so the cost is O(1) word operations instead of a per-qubit Python loop.
- Parameters:
term (
int) – Pauli term encoded as integer (2 bits per qubit, little-endian).nqubits (
int) – Number of qubits.
- Return type:
int- Returns:
Canonical representative as integer.
- property name: str¶
Return ‘permutation’ as identifier.
- class qc_executor.pauli_propagation.CompositeSymmetry(*strategies)[source]¶
Bases:
SymmetryStrategyCompose multiple symmetry strategies.
Applies multiple symmetry strategies sequentially to compute the final canonical representative. The result of strategy i becomes the input to strategy i+1.
- Use Cases:
Combine multiple independent symmetries (e.g., permutation + point group)
Layer symmetries with different granularities
Experimental symmetry compositions for research
- Implementation:
Strategies are applied in the order they are provided to __init__(). For commuting symmetries, order doesn’t matter. For non-commuting symmetries, different orders may give different canonical forms.
- Performance:
Time: Sum of individual strategy times Space: O(1) beyond storage of strategy references
Example
>>> perm_sym = PermutationSymmetry() >>> point_group_sym = PointGroupSymmetry() # hypothetical >>> composite = CompositeSymmetry(perm_sym, point_group_sym) >>> >>> # Applies permutation symmetry first, then point group >>> canonical = composite.canonical_representative(term, nqubits)
Notes
Empty CompositeSymmetry (no strategies) acts as NoSymmetry
Single strategy behaves identically to using that strategy alone
Ordering matters only if symmetries don’t commute
- Parameters:
strategies (SymmetryStrategy)
- canonical_representative(term, nqubits)[source]¶
Apply all configured strategies sequentially.
- Parameters:
term (
int) – Pauli term encoded as integer.nqubits (
int) – Number of qubits.
- Return type:
int- Returns:
Canonical representative after all strategies are applied.
- property name: str¶
Return composite name listing all strategies.
Format: ‘composite(strategy1 + strategy2 + …)’