quri_parts.core.operator.pauli module#

class SinglePauli(value)#

Bases: IntEnum

An integer enumeration representing Pauli matrices X, Y, Z acting on a single qubit.

X = 1#
Y = 2#
Z = 3#
pauli_name(p)#

Returns the name of Pauli matrix for a SinglePauli (int)

Parameters:

p (int) –

Return type:

str

class PauliLabelProvider(*args, **kwargs)#

Bases: Protocol

PauliLabelProvider is an interface for classes providing information of a Pauli label.

abstract get_index_list()#

A list of indices of qubits on which the Pauli matrices act.

Return type:

Collection[int]

abstract get_pauli_id_list()#

A list of SinglePauli’s contained in the Pauli string, sorted in the order corresponding to the qubit index list.

Return type:

Collection[int]

class PauliLabel(arg=())#

Bases: frozenset[tuple[int, int]]

PauliLabel represents a label for a Pauli string, e.g. X0 Y1 Z2.

It represents only a “label” of a multi-qubit Pauli term and does not hold a coefficient or a phase factor. This class is basically a frozenset of pairs of a qubit index and a SinglePauli, and also can be used as a key for a dict (Hashable).

Example

>>> label = pauli_label({(0, SinglePauli.X), (1, SinglePauli.Y), (2, SinglePauli.Z)})
>>> label
PauliLabel({(0, <SinglePauli.X: 1>), (1, <SinglePauli.Y: 2>), (2, <SinglePauli.Z: 3>)})
>>> str(label)
'X0 Y1 Z2'
>>> for pair in label:
...     print(pair)
...
(0, <SinglePauli.X: 1>)
(1, <SinglePauli.Y: 2>)
(2, <SinglePauli.Z: 3>)
>>> label.pauli_at(1)
<SinglePauli.Y: 2>
>>> 1 in label.qubit_indices()
True
>>> for i in label.qubit_indices():
...     print(f"index: {i}, operator: {label.pauli_at(i)}")
...
index: 0, operator: 1
index: 1, operator: 2
index: 2, operator: 3

You can construct a PauliLabel in one of the following ways:

  • With a tuples of a qubit index (int) and a Pauli matrix label (int)
    >>> pauli_label({(0, 1), (1, 2), (2, 3)})
    
  • With a tuples of a qubit index (int) and a Pauli matrix label (SinglePauli)
    >>> pauli_label({(0, SinglePauli.X), (1, SinglePauli.Y), (2, SinglePauli.Z)})
    
  • With a string representation of a Pauli string (Note that string parsing has a significant performance overhead)
    >>> pauli_label("X0 Y1 Z2")
    
  • From a qubit index list and a matrix label (SinglePauli) list
    >>> PauliLabel.from_index_and_pauli_list(
            [0, 1, 2], [SinglePauli.X, SinglePauli.Y, SinglePauli.Z]
        )
    
  • From an object providing a qubit index list and a matrix label list (PauliLabelProvider)
    >>> pauli_label(obj) # obj has get_index_list and get_pauli_id_list methods
    

Note that the following code does not raise an error but creates an invalid PauliLabel. To avoid this kind of error, it is recommended to use a factory function pauli_label() instead of the original constructor PauliLabel().

>>> PauliLabel("X0 Y1 Z2") # Should be pauli_label("X0 Y1 Z2") or PauliLabel.from_str("X0 Y1 Z2")
PauliLabel({' ', 'Z', '0', '1', 'X', 'Y', '2'})

The string input should be given as a list of single pauli terms separated by white spaces. Each single pauli term consists of a Pauli matrix label (X, Y or Z) and a qubit index (int), possibly separated by white spaces.

Valid string input examples:

  • X0 Y1 Z2

  • X 0 Y 1 Z 2

Invalid string input examples:

  • X0 Y1 A2 (Invalid Pauli matrix label A)

  • X0Y1Z2 (No spaces between each term)

  • X0 Y1 Z1 (Duplicate qubit indices)

  • X0 Y Z2 (No qubit index specified)

  • X0 1 Z2 (No Pauli matrix label specified)

Order of the terms is irrelevant when comparing two PauliLabel’s:

>>> pauli_label("X0 Y1 Z2") == pauli_label("X0 Z2 Y1")
True

Performance tip: An index access by pauli_at() involves an iteration inside it, so it is inefficient when you want to iterate over all single Pauli terms in a PauliLabel. Instead of doing this:

>>> for i in range(len(label)):
...     p = label.pauli_at(i)
...     # Do something with p

the following is faster:

>>> for i, p in label:
...     # Do something with p
Parameters:

arg (Iterable[tuple[int, int]]) –

Return type:

PauliLabel

qubit_indices()#

Returns a Collection of qubit indices on which Pauli matrices act.

Note that this collection does not have a definite ordering.

Return type:

Collection[int]

pauli_at(index)#

Returns a Pauli matrix at the qubit index index.

Returns None if no Pauli matrix acts on the index.

Parameters:

index (int) –

Return type:

int | None

property index_and_pauli_id_list: tuple[Sequence[int], Sequence[int]]#

A pair of a list of indices of qubits on which the Pauli matrices act, and a list of the Pauli matrices in the order corresponding to the index list.

static from_index_and_pauli_list(index, pauli)#

Create a PauliLabel from a list of qubit indices and a list of Pauli matrices.

Parameters:
  • index (Collection[int]) –

  • pauli (Collection[int]) –

Return type:

PauliLabel

static from_str(pauli_label_str)#

Create a PauliLabel from a string representation of a Pauli String.

Parameters:

pauli_label_str (str) –

Return type:

PauliLabel

static of(pauli)#

Create a PauliLabel from an object providing a qubit index list and a SinglePauli list.

Parameters:

pauli (PauliLabelProvider) –

Return type:

PauliLabel

pauli_label(p)#

Create a PauliLabel.

The argument can be one of the followings:

  • A string representation of a Pauli string.

  • A PauliLabelProvider, an object providing a qubit index list and a SinglePauli list.

  • An Iterable of tuple[int, int], pairs of a qubit index and a SinglePauli.

Parameters:

p (str | PauliLabelProvider | Iterable[tuple[int, int]]) –

Return type:

PauliLabel

pauli_product(pauli1, pauli2)#

Returns the product of two PauliLabels.

Note that this function returns a tuple (PauliLabel, phase) since the multiplication of two Pauli operators can yield a Pauli operator multiplied by the imaginary unit (e.g., XY = iZ).

Parameters:
Return type:

tuple[PauliLabel, complex]

PAULI_IDENTITY = frozenset({})#

PauliLabel used as an identity.

CommutablePauliSet#

CommutablePauliSet