QGate Module

This module contains the QGate class, which represents a quantum gate. It provides methods to easily create a gate from different representations (matrix, sequence, tuple) and to stock its information in an intuitive way. The class also contains methods to stock the decomposition of the gate, its initial representation and its error. Finally, the class provides a method to calculate the matrix representation of the gate from its sequence.

Classes:
  • QGate: Class representing a quantum gate.

class qdecomp.utils.qgate.QGate(name: str | None = None, target: tuple[int, ...] = (0,))[source]

Bases: object

Class representing a quantum gate. It provides the user the ability to easily create and manipulate quantum gates. The gates can be defined either by their matrix, their sequence or a tuple. A Gate object contains the information about the qubit on which it acts, its control bit, if any, and its error if a sequence is used to approximate it. The class also provides a method to calculate the matrix representation of the gate from its sequence.

Class methods to instantiate a QGate object:
  • from_matrix: Create a QGate object from a matrix.

  • from_sequence: Create a QGate object from a sequence.

  • from_tuple: Create a QGate object from a tuple.

Parameters:
  • name (str | None) – Name of the gate.

  • num_qubits (int) – Number of qubits on which the gate applies.

  • sequence (str | None) – Sequence associated with the gate decomposition.

  • target (tuple[int]) – Qubits on which the gate acts.

  • init_matrix (np.ndarray | None) – Matrix used to initialize the gate.

  • sequence_matrix (np.ndarray | None) – Approximated matrix representation of the gate.

  • epsilon (float) – Tolerance for the gate.

Methods to change the QGate representation:
  • to_tuple: Convert the gate to a tuple representation.

  • convert: Convert the gate by using a user-defined function.

  • set_decomposition: Set the decomposition of the gate. The decomposition might be an approximation of the initial gate stored in the init_matrix attribute.

  • calculate_seq_matrix: Calculate the matrix representation of the gate from its sequence.

Example

>>> import numpy as np
>>> from qdecomp.utils import QGate

# Create a gate from a sequence
>>> g1 = QGate.from_sequence(sequence="CNOT", target=(1, 3))
>>> print(g1)
Sequence: CNOT
Target: (1, 3)

# Create a gate from a matrix
>>> g2 = QGate.from_matrix(matrix=np.diag([1, -1]), name="My_Z_Gate")
>>> print(g2)
Gate: My_Z_Gate
Target: (0,)
Init. matrix:
[[ 1  0]
 [ 0 -1]]

# Create a gate from a tuple
>>> g3 = QGate.from_tuple(("H", (0, ), 0))
>>> print(g3)
Sequence: H
Target: (0,)

# Get the matrix of a from_sequence() gate
>>> gate = QGate.from_sequence(sequence="X Z Y", name="my_gate")
>>> print("Name:", gate.name)
Name: my_gate
>>> print("Sequence:", gate.sequence)
Sequence: X Z Y
>>> print("Target:", gate.target)
Target: (0,)
>>> print("Matrix:\n", gate.sequence_matrix, "\n")
Matrix:
 [[ 0.+1.j  0.+0.j]
 [-0.+0.j -0.+1.j]]

# Set the approximation sequence of a gate
>>> approx_gate = QGate.from_matrix(matrix=np.diag([1-0.001j, 1.j+0.001]), name="approx_my_gate")
>>> approx_gate.set_decomposition("S", epsilon=0.01)
>>> print("Name:", approx_gate.name)
Name: approx_my_gate
>>> print("Sequence:", approx_gate.sequence)
Sequence: S
>>> print("Initial matrix:\n", approx_gate.init_matrix)
Initial matrix:
 [[1.   -0.001j 0.   +0.j   ]
 [0.   +0.j    0.001+1.j   ]]
>>> print("Matrix from sequence:\n", approx_gate.sequence_matrix)
Matrix from sequence:
 [[1.+0.j 0.+0.j]
 [0.+0.j 0.+1.j]]
__init__(name: str | None = None, target: tuple[int, ...] = (0,)) None[source]

Initialize the QGate object.

Parameters:
  • name (str | None) – Name of the gate

  • target (tuple[int, ...]) – Qubits on which the gate applies.

Raises:
  • ValueError – If the target qubits are not a tuple.

  • ValueError – If the target qubits are not integers.

  • ValueError – If the target qubits are not in ascending order.

classmethod from_matrix(matrix: ndarray, name: str | None = None, target: tuple[int, ...] = (0,), epsilon: float | None = None) QGate[source]

Create a QGate object from a matrix.

Parameters:
  • matrix (np.ndarray) – Matrix representation of the gate.

  • name (str | None) – Name of the gate.

  • target (tuple[int, ...]) – Qubits on which the gate applies.

  • epsilon (float | None) – Tolerance for the gate.

Returns:

The QGate object.

Return type:

QGate

Raises:
  • ValueError – If the matrix is not unitary.

  • ValueError – If the number of rows of the matrix is not 2^num_of_qubits.

Example

>>> import numpy as np
>>> from qdecomp.utils import QGate

>>> gate = QGate.from_matrix(np.diag([1, 1j]), name="my_S_gate", target=(1, ))
>>> print(gate)
Gate: my_S_gate
Target: (1,)
Init. matrix:
[[1.+0.j 0.+0.j]
 [0.+0.j 0.+1.j]]
classmethod from_sequence(sequence: str, name: str | None = None, target: tuple[int, ...] = (0,)) QGate[source]

Create a QGate object from a sequence.

Parameters:
  • sequence (str) – Sequence associated with the gate decomposition.

  • target (tuple[int, ...]) – Qubits on which the gate applies.

Returns:

The QGate object.

Return type:

QGate

Example

>>> from qdecomp.utils import QGate

>>> h_gate = QGate.from_sequence("H", name="my_H_gate", target=(2, ))
>>> print(h_gate)
Gate: my_H_gate
Sequence: H
Target: (2,)

>>> cx_gate = QGate.from_sequence("CNOT", name="my_CNOT_gate", target=(1, 3))
>>> print(cx_gate)
Gate: my_CNOT_gate
Sequence: CNOT
Target: (1, 3)
classmethod from_tuple(gate_tuple: tuple, name: str | None = None) QGate[source]

Create a QGate object from a tuple.

Two tuple formats are allowed:
  • (sequence, target, epsilon)

  • (matrix, target, epsilon)

In the first case, the epsilon is discarded.

Parameters:

gate_tuple (tuple) – Tuple representation of the gate.

Returns:

The QGate object.

Return type:

QGate

Raises:
  • TypeError – If the first elements of the tuple is not a string or a np.ndarray.

  • ValueError – If the tuple does not contain three elements.

Example

>>> from qdecomp.utils import QGate

# Create a QGate object from a sequence
>>> init_gate = QGate.from_sequence("H", name="my_H_gate", target=(2, ))
>>> print(init_gate)
Gate: my_H_gate
Sequence: H
Target: (2,)

# Get the tuple representation of the QGate object
>>> tup = init_gate.to_tuple()
>>> print(tup, "\n")
('H', (2,), 0)

# Reconstruct the QGate object from the tuple
>>> tup_gate = QGate.from_tuple(tup)
>>> print(tup_gate)
Sequence: H
Target: (2,)
property name: str | None

Get the name of the gate.

Returns:

The name of the gate.

Return type:

str | None

property sequence: str | None

Get the sequence associated with the gate decomposition.

Returns:

The sequence associated with the gate decomposition.

Return type:

str | None

property target: tuple[int]

Get the target qubit(s).

Returns:

The target qubit(s).

Return type:

tuple[int]

property init_matrix: ndarray

Return the matrix used to initialize the gate.

Returns:

Matrix representation of the initialization gate.

Return type:

np.ndarray

property sequence_matrix: ndarray

Get the matrix representation of the gate given by its sequence. If the gate is initialized with a matrix (obtained with the init_matrix property), and then its sequence is specified, the sequence matrix represents the matrix obtained by multiplying the gates in the sequence.

Returns:

Approximated matrix representation of the gate.

Return type:

np.ndarray

property matrix: ndarray

Get a matrix representation of the gate. If the sequence is known, the matrix associated to the sequence is returned, as the sequence_matrix property does. If the sequence is not known, the matrix used to initialize the gate (accessed via the init_matrix property) is returned.

Returns:

Matrix representation of the gate.

Return type:

np.ndarray

property num_qubits: int

Get the number of qubits on which the gate applies.

Returns:

The number of qubits on which the gate applies.

Return type:

int

property epsilon: float | None

Get the tolerance for the gate.

Returns:

The tolerance for the gate.

Return type:

float | None

to_tuple() tuple[source]

Convert the gate to a tuple representation.

Returns:

The tuple representation of the gate.

Return type:

tuple

Raises:

ValueError – If the sequence is not initialized.

set_decomposition(sequence: str, epsilon: float | None = None) None[source]

Set the decomposition of the gate. This decomposition doesn’t need to be exact. The error epsilon specifies the error made by approximating the initial gate by the sequence and the exact matrix representation is stored in the approx_matrix attribute.

Parameters:
  • sequence (str) – The decomposition of the gate.

  • epsilon (float | None) – The tolerance for the gate. If None, the value of the epsilon attribute is used.

Raises:
  • ValueError – If the sequence is already initialized.

  • ValueError – If the epsilon is not already initialized for the gate and not provided as an argument.