Pauli algebra#

Pauli strings, sums, and observable generators.

sdplab.special.pauli.PauliString

Symbolic tensor-product Pauli operator.

sdplab.special.pauli.PauliSum

Symbolic linear combination of Pauli strings.

sdplab.special.pauli.generate_pauli_observables

Stack dense Pauli observable matrices along a leading axis.

sdplab.special.pauli.generate_single_pauli_string

Return the dense matrix for a Pauli tensor product.

class sdplab.special.pauli.PauliString(identifier, *, phase=1.0, ctx=None)[source]#

Bases: ContextBound

Symbolic tensor-product Pauli operator.

A label such as "IXZ" represents \(I \otimes X \otimes Z\) acting on three qubits. The optional complex phase represents the scalar multiplier, so the stored operator is \(\mathrm{phase}\,P_0 \otimes \cdots \otimes P_{n-1}\). The dense matrix can be materialized, but vector and matrix application use tensor structure when possible.

Parameters:
  • identifier (str)

  • phase (complex)

  • ctx (Context | str | None)

__init__(identifier, *, phase=1.0, ctx=None)[source]#

Create phase * P_0 otimes ... otimes P_{n-1} from a label.

Parameters:
  • identifier (str)

  • phase (complex)

  • ctx (Context | str | None)

Return type:

None

property n_qubits: int#

Return n for an operator on (C^2)^{otimes n}.

property label: str#

Return the normalized string label, such as "IXZ".

copy()[source]#

Return an independent copy with the same label, phase, and context.

Return type:

PauliString

support()[source]#

Return the support of the Pauli operator.

The support is the tuple of qubit indices on which the operator acts nontrivially, i.e. the sites where the local Pauli factor is not the identity.

\[P = P_0 \otimes P_1 \otimes \cdots \otimes P_{n-1},\]

with each local factor \(P_k \in \{I, X, Y, Z\}\), then

\[\operatorname{support}(P) = \{k : P_k \ne I\}.\]
Returns:

Sorted tuple of qubit indices where the local factor is not identity.

Return type:

tuple[int, …]

Examples

“IIXZI” has support (2, 3) with zero-based indexing. “IIII” has empty support ().

Notes

The size of the support is the Pauli weight, i.e. len(self.support()) == self.weight().

weight()[source]#

Return the Pauli weight of the operator.

The Pauli weight is the number of qubit sites on which the operator acts nontrivially, i.e. the number of local factors that are not the identity.

\[P = P_0 \otimes P_1 \otimes \cdots \otimes P_{n-1},\]

with each local factor \(P_k \in \{I, X, Y, Z\}\), then

\[\operatorname{weight}(P) = |\{k : P_k \ne I\}|.\]
Returns:

Number of qubit indices where the local factor is not identity.

Return type:

int

Examples

“IIXZI” has weight 2. “IIII” has weight 0.

Notes

The Pauli weight is the cardinality of the support, so self.weight() == len(self.support()).

is_identity()[source]#

Return True if every local Pauli factor is the identity.

Return type:

bool

adjoint()[source]#

Return the Hermitian adjoint of this symbolic Pauli string.

Return type:

PauliString

dagger()#

Return the Hermitian adjoint of this symbolic Pauli string.

Return type:

PauliString

trace()[source]#

Return the trace of the represented dense Pauli operator.

commutes_with(other)[source]#

Return True when this Pauli string commutes with other.

Parameters:

other (PauliString)

Return type:

bool

multiply(other)[source]#

Return the symbolic product of two compatible Pauli strings.

Parameters:

other (PauliString)

Return type:

PauliString

materialize()[source]#

Return the full 2^n x 2^n matrix for this Pauli string.

Return type:

DenseArray

matvec(x)[source]#

Return P x for a state vector x of length 2^n.

Parameters:

x (DenseArray)

Return type:

DenseArray

apply(x)#

Return P x for a state vector x of length 2^n.

Parameters:

x (DenseArray)

Return type:

DenseArray

to_sum(coeff=1.0)[source]#

Represent this Pauli string as a one-term PauliSum.

Parameters:

coeff (complex)

Return type:

PauliSum

matmat(X)[source]#

Left-multiply a matrix by this Pauli string.

If this Pauli string acts on n qubits, and X has shape (2**n, k), this returns P X without materializing the full dense matrix P.

Parameters:

X (DenseArray) – Dense matrix of shape (2**n, k).

Returns:

Matrix of shape (2**n, k).

Return type:

DenseArray

property check_level: Literal['none', 'cheap', 'standard', 'strict']#

Return this object’s runtime validation level.

convert(new_ctx=None)#

Return this object represented in new_ctx.

Parameters:

new_ctx (Context | BackendFamily | str | None)

Return type:

Self

property ctx: Context#

Return the execution context bound to this object.

property dtype: Any#

Return the default dtype associated with this object’s context.

property ops: BackendOps#

Return backend operations associated with this object’s context.

class sdplab.special.pauli.PauliSum(terms, coeffs=None, *, ctx=None, simplify=True)[source]#

Bases: ContextBound

Symbolic linear combination of Pauli strings.

Represents an operator

\[A = \sum_j c_j P_j\]

where every P_j acts on the same n-qubit Hilbert space. Repeated Pauli labels may be merged into one coefficient when simplify=True.

Parameters:
  • terms (Iterable[str | PauliString])

  • coeffs (Iterable[complex] | None)

  • ctx (Context | str | None)

  • simplify (bool)

__init__(terms, coeffs=None, *, ctx=None, simplify=True)[source]#

Create sum_j coeffs[j] * terms[j] on a common qubit register.

Parameters:
  • terms (Iterable[str | PauliString])

  • coeffs (Iterable[complex] | None)

  • ctx (Context | str | None)

  • simplify (bool)

Return type:

None

property n_qubits: int#

Return n for an operator on (C^2)^{otimes n}.

property n_terms: int#

Return the number of symbolic Pauli terms in the sum.

support()[source]#

Return the support of the Pauli sum.

The support is the tuple of qubit indices on which at least one Pauli term acts nontrivially. Equivalently, it is the union of the supports of all Pauli-string terms in the sum.

\[A = \sum_j c_j P_j,\]

then

\[\operatorname{support}(A) = \bigcup_j \operatorname{support}(P_j).\]
Returns:

Sorted tuple of qubit indices touched nontrivially by at least one term.

Return type:

tuple[int, …]

Notes

If the sum has no terms, the support is empty.

simplify()[source]#

Return a new sum with duplicate labels merged.

Return type:

PauliSum

materialize()[source]#

Return the full dense matrix sum_j c_j P_j.

Return type:

DenseArray

matvec(x)[source]#

Return sum_j c_j P_j x without materializing the full matrix.

Parameters:

x (DenseArray)

Return type:

DenseArray

apply(x)#

Return sum_j c_j P_j x without materializing the full matrix.

Parameters:

x (DenseArray)

Return type:

DenseArray

add_term(term, coeff=1.0)[source]#

Return a new sum with one additional term and coefficient.

Parameters:
Return type:

PauliSum

trace()[source]#

Return the trace of the represented dense operator.

classmethod from_matrix(mat, *, tol=1e-12, ctx=None, check_hermitian=True)[source]#

Decompose a Hermitian matrix into the Pauli-string basis.

For a matrix A acting on n qubits, this method computes coefficients \(c_\alpha\) such that

\[A = \sum_\alpha c_\alpha P_\alpha,\]

where the sum runs over all n-qubit Pauli strings and

\[c_\alpha = 2^{-n} \operatorname{Tr}[P_\alpha A].\]
Parameters:
  • mat (Any) – Dense matrix of shape (2**n, 2**n).

  • tol (float) – Terms with \(|c_\alpha| \le \mathtt{tol}\) are discarded.

  • ctx (Context | str | None) – Optional context.

  • check_hermitian (bool) – If True, validate that mat is Hermitian up to numerical tolerance.

Returns:

Symbolic Pauli decomposition of the input matrix.

Return type:

PauliSum

Raises:

ValueError – If the input is not square, its dimension is not a power of 2, or it is not Hermitian when check_hermitian=True.

matmat(X)[source]#

Left-multiply a matrix by this Pauli sum.

For

\[A = \sum_j c_j P_j,\]

this returns

\[A X = \sum_j c_j (P_j X),\]

without materializing A.

Parameters:

X (DenseArray) – Dense matrix of shape (2**n, k).

Returns:

Matrix of shape (2**n, k).

Return type:

DenseArray

property check_level: Literal['none', 'cheap', 'standard', 'strict']#

Return this object’s runtime validation level.

convert(new_ctx=None)#

Return this object represented in new_ctx.

Parameters:

new_ctx (Context | BackendFamily | str | None)

Return type:

Self

property ctx: Context#

Return the execution context bound to this object.

property dtype: Any#

Return the default dtype associated with this object’s context.

property ops: BackendOps#

Return backend operations associated with this object’s context.

sdplab.special.pauli.generate_pauli_observables(observables, ctx=None)[source]#

Stack dense Pauli observable matrices along a leading axis.

If observables contains m labels on n qubits, the output has shape (m, 2**n, 2**n). Each slice is one observable matrix that can be used in constraints such as \(\operatorname{Tr}[M_i X] = b_i\).

Parameters:
  • observables (list[str])

  • ctx (Context | str | None)

Return type:

DenseArray

sdplab.special.pauli.generate_single_pauli_string(s, ctx=None)[source]#

Return the dense matrix for a Pauli tensor product.

For example, "IXZ" means \(I \otimes X \otimes Z\) and returns an 8 x 8 dense matrix.

Parameters:
  • s (str)

  • ctx (Context | str | None)

Return type:

DenseArray