graphix.circ_ext package

Submodules

Module contents

Utilities for circuit extraction and compilation.

class CliffordMap(x_map: Sequence[PauliString], z_map: Sequence[PauliString], input_nodes: Sequence[int], output_nodes: Sequence[int])[source]

Bases: object

Dataclass to represent a Clifford map.

A Clifford map encodes the action of a Clifford operator on Pauli generators. It describes how single-qubit Pauli operators on the input qubits are mapped, under conjugation, to Pauli strings on the output qubits.

For each input qubit \(i\), the map specifies:

\[P_i = C X_i C^\dagger\]
\[P_i = C Z_i C^\dagger\]

where the resulting operators \(P_i\) are Pauli strings over the output qubits.

The sequences input_nodes and output_nodes define the correspondence between qubit indices and node labels in the input and output spaces.

x_map

Images of the \(X\) generators. The \(i\)-th element is the Pauli string corresponding to \(C X_i C^\dagger\).

Type:

Sequence[PauliString]

z_map

Images of the \(Z\) generators. The \(i\)-th element is the Pauli string corresponding to \(C Z_i C^\dagger\).

Type:

Sequence[PauliString]

input_nodes

Sequence of inputs nodes.

Type:

Sequence[int]

output_nodes

Sequence of outputs nodes.

Type:

Sequence[int]

Notes

See Definition 3.3 in Ref. [1].

Elements of x_map and z_map are in one-to-one correspondance with input_nodes. Each Pauli string is defined over qubit indices corresponding to positions in output_nodes.

References

[1] Simmons, 2021 (arXiv:2109.05654).

x_map: Sequence[PauliString]
z_map: Sequence[PauliString]
input_nodes: Sequence[int]
output_nodes: Sequence[int]
static from_focused_flow(flow: PauliFlow[Measurement], *, stacklevel: int = 1) → CliffordMap[source]

Extract a Clifford map from a focused Pauli flow.

This routine associates two Pauli strings (one per generator of the Pauli group, X and Z) to each input node in flow.og.

Parameters:
  • flow (PauliFlow[Measurement]) – A focused Pauli flow.

  • stacklevel (int, optional) – Stack level to use for warnings. Defaults to 1, meaning that warnings are reported at this function’s call site.

Return type:

CliffordMap

Notes

See Definition 3.3 and Example C.13 in Ref. [1].

References

[1] Simmons, 2021 (arXiv:2109.05654).

to_tableau() → MatGF2[source]

Convert the CliffordMap into its binary tableau representation.

The returned tableau is a (2n, 2n + 1) binary matrix over GF(2), where n is the number of qubits. The first n rows correspond to the images of X generators, and the next n rows correspond to the images of Z generators. Columns encode the X and Z components of the resulting Pauli strings, along with a sign column.

Each PauliString in x_map and z_map is decomposed into its X/Z support: - X contributes a 1 to the X block. - Z contributes a 1 to the Z block. - Y contributes a 1 to both X and Z blocks. The sign of the Pauli string is stored in the final column (0 for Sign.PLUS and 1 for Sign.MINUS).

Returns:

A binary matrix of shape (2n, 2n + 1) representing the Clifford tableau.

Return type:

MatGF2

Raises:

NotImplementedError – If the number of input nodes differs from the number of output nodes (i.e., the map is an isometry instead of a square Clifford).

__init__(x_map: Sequence[PauliString], z_map: Sequence[PauliString], input_nodes: Sequence[int], output_nodes: Sequence[int]) → None
class PauliExponential(angle: Expression | float, pauli_string: PauliString)[source]

Bases: object

Dataclass representing a Pauli exponential.

A Pauli exponential corresponds to the unitary operator

\[U(\alpha) = \exp \left(i \frac{\alpha}{2} P\right),\]

where \(\alpha\) is a real-valued angle and \(P\) is a Pauli string.

angle

The Pauli exponential angle \(\alpha\) in units of \(\pi\). When extracted from a corrected node, it corresponds to the node’s measurement divided by two.

Type:

ParameterizedAngle

pauli_string

The signed Pauli string \(P\) specifying the tensor product of Pauli operators acting on qubit indices.

Type:

PauliString

angle: Expression | float
pauli_string: PauliString
static from_measured_node(flow: PauliFlow[Measurement], node: Node) → PauliExponential[source]

Extract the Pauli exponential of a measured node and its focused correction set.

Parameters:
  • flow (PauliFlow[Measurement]) – A focused Pauli flow. The resulting Pauli string is extracted from its correction function.

  • node (int) – A measured node whose associated Pauli string is computed.

Returns:

Primary extraction string associated to the input measured nodes. The sets in the returned PauliString instance are disjoint.

Return type:

PauliExponential

Notes

See Eq. (13) and Lemma 4.4 in Ref. [1]. The phase of the Pauli string is given by Eq. (37).

References

[1] Simmons, 2021 (arXiv:2109.05654).

__init__(angle: Expression | float, pauli_string: PauliString) → None
class PauliExponentialDAG(pauli_exponentials: Mapping[int, PauliExponential], partial_order_layers: Sequence[AbstractSet[int]], output_nodes: Sequence[int])[source]

Bases: object

Dataclass to represent a multi-qubit rotation formed by a sequence of Pauli exponentials extracted from a pattern.

pauli_exponentials

Mapping between measured nodes (keys) and Pauli exponentials (values).

Type:

Mapping[int, PauliExponential]

partial_order_layers

Partial order between the Pauli exponentials in a layer form. The set layers[i] comprises the nodes in layer i. Nodes in layer i are “larger” in the partial order than nodes in layer i+1. The pattern’s output nodes are always in layer 0.

Type:

Sequence[AbstractSet[int]]

output_nodes

Output nodes on which the Pauli exponential rotation acts.

Type:

Sequence[int]

Notes

See Definition 3.3 in Ref. [1].

The Pauli strings in the Pauli exponentials are defined on qubit indices which correspond to the indices of the sequence output_nodes.

References

[1] Simmons, 2021 (arXiv:2109.05654).

pauli_exponentials: Mapping[int, PauliExponential]
partial_order_layers: Sequence[AbstractSet[int]]
output_nodes: Sequence[int]
static from_focused_flow(flow: PauliFlow[Measurement]) → PauliExponentialDAG[source]

Extract a Pauli exponential rotation from a focused Pauli flow.

This routine associates a Pauli exponential to each measured node in flow. The flow’s partial order defines a partial order between the Pauli exponentials such that Pauli exponentials in the same layer commute.

Parameters:

flow (PauliFlow[Measurement]) – A focused Pauli flow.

Return type:

PauliExponentialDAG

Notes

See Definition 3.3 and Example C.13 in Ref. [1].

References

[1] Simmons, 2021 (arXiv:2109.05654).

__init__(pauli_exponentials: Mapping[int, PauliExponential], partial_order_layers: Sequence[AbstractSet[int]], output_nodes: Sequence[int]) → None
class PauliString(dim: int, axes: Mapping[int, Axis], sign: Sign = Sign.PLUS)[source]

Bases: object

Dataclass representing a Pauli string.

dim

Dimension of the Hilbert space on which the Pauli string acts.

Type:

int

axes

Mapping between qubit indices and the applied Pauli operator.

Type:

Mapping[int, Axis]

sign

Sign of the Pauli string.

Type:

Sign

Notes

The identity operators in the Pauli string are omitted in axes, but they can be inferred from the dimension of the Hilbert space dim.

dim: int
axes: Mapping[int, Axis]
sign: Sign = 1
static from_str(ps: str) → PauliString[source]

Construct a PauliString from its string representation.

The sign prefix ('+' or '-') is optional; if omitted, the sign defaults to Sign.PLUS.

Parameters:

ps (str) – String encoding of a Pauli string. Optionally starts with '+' or '-', followed by zero or more single-character Pauli operators ('X', 'Y', 'Z', or 'I').

Returns:

The PauliString instance corresponding to the input string.

Return type:

PauliString

Raises:

ValueError – If the first character is not '+' or '-' or a valid operator character, or any operator character is not one of 'X', 'Y', 'Z', 'I'.

Examples

>>> PauliString.from_str("+XYZ")
PauliString(dim=3, axes={0: Axis.X, 1: Axis.Y, 2: Axis.Z}, sign=Sign.PLUS)
>>> PauliString.from_str("-IXI")
PauliString(dim=3, axes={1: Axis.X}, sign=Sign.MINUS)
>>> PauliString.from_str("X")
PauliString(dim=1, axes={0: Axis.X}, sign=Sign.PLUS)
>>> PauliString.from_str("")
PauliString(dim=0, axes={}, sign=Sign.PLUS)
static from_tableau(tab: MatGF2) → PauliString[source]

Construct a PauliString from a one-dimensional tableau representation.

The tableau encodes a Pauli operator of the form \(\pm P_0 \otimes P_1 \otimes \cdots \otimes P_{n-1}\), where each single-qubit Pauli is stored as an (x, z) bit pair and the final element encodes the sign.

Layout of tab (length 2n + 1):

[ x_0, x_1, …, x_{n-1} | z_0, z_1, …, z_{n-1} | sign ]

Encoding conventions:

  • (x=1, z=0) → X

  • (x=0, z=1) → Z

  • (x=1, z=1) → Y

  • (x=0, z=0) → I (identity, qubit absent in axes)

  • sign = 0 → +1

  • sign = 1 → -1

Parameters:

tab (MatGF2) – A one-dimensional GF(2) array of odd length 2n + 1 representing an n-qubit Pauli operator.

Returns:

The Pauli operator encoded by tab.

Return type:

PauliString

Raises:

ValueError – If tab is not one-dimensional or len(tab) is even.

Examples

>>> tab = MatGF2(np.array([1, 1, 1]))
>>> PauliString.from_tableau(tab)
PauliString(dim=1, axes={0: Axis.Y}, sign=Sign.MINUS)
>>> tab = MatGF2(np.array([0, 0, 0, 1, 0]))
>>> PauliString.from_tableau(tab)
PauliString(dim=2, axes={1: Axis.Z}, sign=Sign.PLUS)
to_tableau() → MatGF2[source]

Serialise this PauliString into a one-dimensional tableau representation.

Produces the inverse of from_tableau(): a MatGF2 of length 2n + 1 whose layout is:

[ x_0, x_1, …, x_{n-1} | z_0, z_1, …, z_{n-1} | sign ]

Encoding conventions:

  • X → (x=1, z=0)

  • Z → (x=0, z=1)

  • Y → (x=1, z=1)

  • I → (x=0, z=0) (absent in self.axes)

  • + sign → 0

  • - sign → 1

Returns:

A one-dimensional GF(2) array of length 2 * self.dim + 1.

Return type:

MatGF2

Examples

>>> ps = PauliString.from_str("-XY")
>>> ps.to_tableau()
MatGF2([1, 1, 0, 1, 1], dtype=uint8)
__init__(dim: int, axes: Mapping[int, Axis], sign: Sign = Sign.PLUS) → None