Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating GST to accept parameterised gates #1534

Merged
merged 9 commits into from
Jan 17, 2025
3 changes: 2 additions & 1 deletion doc/source/code-examples/advancedexamples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2242,7 +2242,8 @@ Let's first define the set of gates we want to estimate:

from qibo import gates

gate_set = {gates.X(0), gates.H(0), gates.CZ(0, 1)}
target_gates = [gates.RX(0, np.pi/3), gates.Z(0), gates.PRX(0, np.pi/2, np.pi/3), gates.GPI(0, np.pi/7), gates.CNOT(0,1)]
BrunoLiegiBastonLiegi marked this conversation as resolved.
Show resolved Hide resolved
gate_set = [(g.__class__, [g.parameters[i] for i in range(len(g.parameters))]) if g.parameters else (g.__class__, []) for g in target_gates]
BrunoLiegiBastonLiegi marked this conversation as resolved.
Show resolved Hide resolved

For simulation purposes we can define a noise model. Naturally this is not needed when running on real quantum hardware, which is intrinsically noisy. For example, we can suppose that the three gates we want to estimate are going to be noisy:

Expand Down
25 changes: 22 additions & 3 deletions src/qibo/tomography/gate_set_tomography.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from functools import cache
from inspect import signature
from itertools import product
from random import Random
BrunoLiegiBastonLiegi marked this conversation as resolved.
Show resolved Hide resolved
from typing import List, Union
Expand Down Expand Up @@ -227,7 +228,12 @@ def GST(
"""Runs Gate Set Tomography on the input ``gate_set``.
mho291 marked this conversation as resolved.
Show resolved Hide resolved

Args:
gate_set (tuple or set or list): set of :class:`qibo.gates.Gate` to run GST on.
gate_set (tuple or set or list): set of :class:`qibo.gates.Gate` and parameters to run
GST on.
E.g. target_gates = [gates.RX(0, np.pi/3), gates.Z(0), gates.PRX(0, np.pi/2, np.pi/3),
gates.GPI(0, np.pi/7), gates.CNOT(0,1)]
gate_set = [(g.__class__, [g.parameters[i] for i in range(len(g.parameters))])
if g.parameters else (g.__class__, []) for g in target_gates]
BrunoLiegiBastonLiegi marked this conversation as resolved.
Show resolved Hide resolved
nshots (int, optional): number of shots used in Gate Set Tomography per gate.
Defaults to :math:`10^{4}`.
noise_model (:class:`qibo.noise.NoiseModel`, optional): noise model applied to simulate
Expand Down Expand Up @@ -286,12 +292,25 @@ def GST(

for gate in gate_set:
if gate is not None:
nqubits = len(gate.qubits)
if nqubits not in (1, 2):
init_args = signature(gate[0]).parameters
params = gate[1]

angle_names = [name for name in init_args if name in {"theta", "phi"}]
MatteoRobbiati marked this conversation as resolved.
Show resolved Hide resolved

angle_values = {}
for name, value in zip(angle_names, params): # Zip ensures correct order
angle_values[name] = value
BrunoLiegiBastonLiegi marked this conversation as resolved.
Show resolved Hide resolved

if "q" in init_args:
nqubits = 1
elif "q0" in init_args and "q1" in init_args and "q2" not in init_args:
nqubits = 2
else:
raise_error(
RuntimeError,
f"Gate {gate} is not supported for `GST`, only 1- and 2-qubits gates are supported.",
mho291 marked this conversation as resolved.
Show resolved Hide resolved
)
gate = gate[0](*range(nqubits), **angle_values)
BrunoLiegiBastonLiegi marked this conversation as resolved.
Show resolved Hide resolved

matrices.append(
_gate_tomography(
Expand Down
26 changes: 20 additions & 6 deletions tests/test_tomography_gate_set_tomography.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,18 @@ def test_GST(backend, target_gates, pauli_liouville):
target_matrices = [
to_pauli_liouville(m, normalize=True, backend=backend) for m in target_matrices
]
# gate_set = [g.__class__ for g in target_gates]
gate_set = [
(
(g.__class__, [g.parameters[i] for i in range(len(g.parameters))])
if g.parameters
else (g.__class__, [])
)
for g in target_gates
]
BrunoLiegiBastonLiegi marked this conversation as resolved.
Show resolved Hide resolved

if len(target_gates) == 4:
empty_1q, empty_2q, *approx_gates = GST(
gate_set=target_gates,
gate_set=gate_set,
nshots=int(1e4),
include_empty=True,
pauli_liouville=pauli_liouville,
Expand All @@ -244,7 +251,7 @@ def test_GST(backend, target_gates, pauli_liouville):
else:
with pytest.raises(RuntimeError):
empty_1q, empty_2q, *approx_gates = GST(
gate_set=target_gates, # [g.__class__ for g in target_gates],
gate_set=gate_set,
nshots=int(1e4),
include_empty=True,
pauli_liouville=pauli_liouville,
Expand All @@ -268,10 +275,17 @@ def test_GST_with_transpiler(backend, star_connectivity):
import networkx as nx

target_gates = [gates.SX(0), gates.Z(0), gates.CNOT(0, 1)]
# gate_set = [g.__class__ for g in target_gates]
gate_set = [
(
(g.__class__, [g.parameters[i] for i in range(len(g.parameters))])
if g.parameters
else (g.__class__, [])
)
for g in target_gates
]
BrunoLiegiBastonLiegi marked this conversation as resolved.
Show resolved Hide resolved
# standard not transpiled GST
empty_1q, empty_2q, *approx_gates = GST(
gate_set=target_gates,
gate_set=gate_set,
nshots=int(1e4),
include_empty=True,
pauli_liouville=False,
Expand All @@ -291,7 +305,7 @@ def test_GST_with_transpiler(backend, star_connectivity):
)
# transpiled GST
T_empty_1q, T_empty_2q, *T_approx_gates = GST(
gate_set=target_gates,
gate_set=gate_set,
nshots=int(1e4),
include_empty=True,
pauli_liouville=False,
Expand Down
Loading