Skip to content

Commit

Permalink
[pre-commit.ci] auto fixes from pre-commit.com hooks
Browse files Browse the repository at this point in the history
for more information, see https://pre-commit.ci
  • Loading branch information
pre-commit-ci[bot] committed Feb 15, 2024
1 parent 5d29894 commit 52e530b
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 32 deletions.
4 changes: 2 additions & 2 deletions doc/source/api-reference/qibo.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2249,9 +2249,9 @@ Alternatively, a Clifford circuit can also be executed starting from the :class:
Gate Set Tomography
-------------------

The gate set tomography (GST) follows the procedure outlined in https://arxiv.org/pdf/1712.09271.pdf, which follows closely to that of the Linear inversion GST given in https://arxiv.org/pdf/1509.02921.pdf. The outputs of the functions, when used correctly, will allow one to set up the proper variables necessary for probabilistic error cancellation to mitigate noise arising from noisy quantum hardware. The codes allow for calibrating an empty circuit, and for one and two qubits of gate set tomography. We give some examples to illustrate the usage of the functions for clarity.
The gate set tomography (GST) follows the procedure outlined in https://arxiv.org/pdf/1712.09271.pdf, which follows closely to that of the Linear inversion GST given in https://arxiv.org/pdf/1509.02921.pdf. The outputs of the functions, when used correctly, will allow one to set up the proper variables necessary for probabilistic error cancellation to mitigate noise arising from noisy quantum hardware. The codes allow for calibrating an empty circuit, and for one and two qubits of gate set tomography. We give some examples to illustrate the usage of the functions for clarity.

First, import the necessary modules. As an example, we import depolarizing noise as an example.
First, import the necessary modules. As an example, we import depolarizing noise as an example.
.. testsetup:: python

from qibo.noise import NoiseModel, DepolarizingError
Expand Down
41 changes: 23 additions & 18 deletions src/qibo/tomography/gate_set_tomography.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import numpy as np

from qibo import Circuit, gates, symbols
from qibo.config import raise_error
from qibo.backends import GlobalBackend
from qibo.config import raise_error
from qibo.hamiltonians import SymbolicHamiltonian


Expand All @@ -13,21 +13,22 @@ def prepare_states(k, nqubits):
Args:
k (int): The index of the state to be prepared.
For a single qubit, \(k \in \{0, 1, 2, 3\} \equiv
\{| 0 \rangle \langle 0 |,
| 1 \rangle \langle 1 |,
| + \rangle \langle + |,
| y+ \rangle \langle y+ | \).
For two qubits, \(k \in \{0, 1, 2, 3\}^{\otimes 2}\).
nqubits (int): Number of qubits in the circuit.
For a single qubit, \\(k \\in \\{0, 1, 2, 3\\} \\equiv
\\{| 0 \rangle \\langle 0 |,
| 1 \rangle \\langle 1 |,
| + \rangle \\langle + |,
| y+ \rangle \\langle y+ | \\).
For two qubits, \\(k \\in \\{0, 1, 2, 3\\}^{\\otimes 2}\\).
nqubits (int): Number of qubits in the circuit.
Returns:
circuit (:class:`qibo.models.Circuit`): Circuit prepared in the specified state.
"""

if not nqubits in (1, 2):
raise_error(
ValueError, f"nqubits given as {nqubits}. nqubits needs to be either 1 or 2."
ValueError,
f"nqubits given as {nqubits}. nqubits needs to be either 1 or 2.",
)

gates_list = [(gates.I,), (gates.X,), (gates.H,), (gates.H, gates.S)]
Expand All @@ -40,7 +41,7 @@ def prepare_states(k, nqubits):


def measurement_basis(j, circ):
"""Implements a measurement basis for circuit indexed by `j`.
r"""Implements a measurement basis for circuit indexed by `j`.
Args:
j (int): The index of the measurement basis.
Expand All @@ -55,7 +56,8 @@ def measurement_basis(j, circ):
nqubits = circ.nqubits
if not nqubits in (1, 2):
raise_error(
ValueError, f"nqubits given as {nqubits}. nqubits needs to be either 1 or 2."
ValueError,
f"nqubits given as {nqubits}. nqubits needs to be either 1 or 2.",
)

meas_list = [gates.Z, gates.X, gates.Y, gates.Z]
Expand All @@ -69,7 +71,7 @@ def measurement_basis(j, circ):


def reset_register(circuit, invert_register):
"""Returns an inverse circuit of the selected register to prepare the zero state \(|0\rangle\).
"""Returns an inverse circuit of the selected register to prepare the zero state \\(|0\rangle\\).
One can then add inverse_circuit to the original circuit by addition:
circ_with_inverse = circ.copy()
circ_with_inverse.add(inverse_circuit.on_qubits(invert_register))
Expand Down Expand Up @@ -110,7 +112,7 @@ def reset_register(circuit, invert_register):
"sp_1"
" to reset qubit 1, or "
"sp_t"
" to reset both qubits."
" to reset both qubits.",
)

return new_circ.invert()
Expand All @@ -135,7 +137,8 @@ def GST_execute_circuit(circuit, k, j, nshots=int(1e4), backend=None):
nqubits = circuit.nqubits
if not nqubits in (1, 2):
raise_error(
ValueError, f"nqubits given as {nqubits}. nqubits needs to be either 1 or 2."
ValueError,
f"nqubits given as {nqubits}. nqubits needs to be either 1 or 2.",
)

else:
Expand Down Expand Up @@ -183,7 +186,8 @@ def execute_GST(
# Check if gate is 1 or 2 qubit gate.
if not nqubits in (1, 2):
raise_error(
ValueError, f"nqubits given as {nqubits}. nqubits needs to be either 1 or 2."
ValueError,
f"nqubits given as {nqubits}. nqubits needs to be either 1 or 2.",
)

# Check if invert_register has the correct string.
Expand All @@ -193,14 +197,15 @@ def execute_GST(
and invert_register != "sp_1"
and invert_register != "sp_t"
):
raise_error(NameError,
raise_error(
NameError,
f"{invert_register} not recognized. Input "
"sp_0"
" to reset qubit 0, "
"sp_1"
" to reset qubit 1, or "
"sp_t"
" to reset both qubits."
" to reset both qubits.",
)

if backend is None: # pragma: no cover
Expand All @@ -210,7 +215,7 @@ def execute_GST(
if nqubits != len(gate.qubits):
raise_error(
ValueError,
f"Mismatched inputs: nqubits given as {nqubits}. {gate} is a {qb_gate}-qubit gate."
f"Mismatched inputs: nqubits given as {nqubits}. {gate} is a {qb_gate}-qubit gate.",
)
gate = gate.__class__(*gate.qubits, **gate.init_kwargs)

Expand Down
20 changes: 8 additions & 12 deletions tests/test_tomography_gate_set_tomography.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def test_prepare_states_invalid_k_valid_nqubits(k, nqubits):
def test_meaasurement_basis_value_j_single_qubit(j):
# Test for valid input with a single qubit
nqubits = 1
U = 1/np.sqrt(2) * np.array([[1, -1j],[1j, -1]])
U = 1 / np.sqrt(2) * np.array([[1, -1j], [1j, -1]])
correct_gates = [
[gates.M(0)],
[gates.H(0), gates.M(0)],
Expand All @@ -87,7 +87,7 @@ def test_meaasurement_basis_value_j_single_qubit(j):
def test_measurement_basis_value_j_two_qubits(j):
# Test for valid input with two qubits
nqubits = 2
U = 1/np.sqrt(2) * np.array([[1, -1j],[1j, -1]])
U = 1 / np.sqrt(2) * np.array([[1, -1j], [1j, -1]])
correct_gates = [
[gates.M(0), gates.M(1)],
[gates.M(0), gates.H(1), gates.M(1)],
Expand Down Expand Up @@ -191,12 +191,12 @@ def test_reset_register_sp_0_singlequbitcircuit():
nqubits = 1
test_circuit = qibo.models.Circuit(nqubits)
test_circuit.add(gates.H(0))
test_circuit.add(gates.RX(0, np.pi/3))
test_circuit.add(gates.RX(0, np.pi / 3))

inverse_circuit = reset_register(test_circuit, "sp_0")

correct_gates = [
[gates.RX(0, np.pi/3).dagger()],
[gates.RX(0, np.pi / 3).dagger()],
[gates.H(0)],
]

Expand All @@ -213,9 +213,7 @@ def test_reset_register_sp_1_twoqubitcircuit():

inverse_circuit = reset_register(test_circuit, "sp_1")

correct_gates = [
[gates.S(0).dagger()]
]
correct_gates = [[gates.S(0).dagger()]]

for groundtruth, gate in zip(correct_gates, inverse_circuit.queue):
assert isinstance(gate, type(groundtruth[0]))
Expand All @@ -227,13 +225,11 @@ def test_reset_register_sp_1_singlequbitcircuit():
test_circuit = qibo.models.Circuit(nqubits)
test_circuit.add(gates.H(0))
test_circuit.add(gates.S(0))
test_circuit.add(gates.RX(1, np.pi/3))
test_circuit.add(gates.RX(1, np.pi / 3))

inverse_circuit = reset_register(test_circuit, "sp_1")

correct_gates = [
[gates.RX(1, np.pi/3).dagger()]
]
correct_gates = [[gates.RX(1, np.pi / 3).dagger()]]

for groundtruth, gate in zip(correct_gates, inverse_circuit.queue):
assert isinstance(gate, type(groundtruth[0]))
Expand All @@ -249,7 +245,7 @@ def test_reset_register_sp_t():
inverse_circuit = reset_register(test_circuit, "sp_t")

correct_gates = [
[gates.CNOT(0,1)],
[gates.CNOT(0, 1)],
[gates.H(0)],
]
for groundtruth, gate in zip(correct_gates, inverse_circuit.queue):
Expand Down

0 comments on commit 52e530b

Please sign in to comment.