Matériel
Masao Tokunari and Tamiya Onodera (14 June 2024)
This course is based on a live course delivered at the University of Tokyo.
This lesson's lecture pdf was split into two parts. Download part 1 and download part 2. Note that some code snippets might become deprecated since these are static images.
1. Introduction
Cette leçon explore le matériel moderne de calcul quantique.
Nous commencerons par vérifier certaines versions et importer quelques paquets pertinents.
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-ibm-runtime
import statistics
from qiskit_ibm_runtime import QiskitRuntimeService
2. Backend et Target
Qiskit fournit une API pour obtenir des informations, à la fois statiques et dynamiques, sur un dispositif quantique. Nous utilisons une instance backend pour interfacer avec un dispositif, qui inclut une instance Target, un modèle de machine abstrait résumant les caractéristiques pertinentes telles que son architecture de jeu d'instructions (ISA) et toutes les propriétés ou contraintes qui lui sont associées. Utilisons ces instances backend pour obtenir certaines des informations que tu vois sur la page Ressources de calcul sur IBM Quantum® Platform. D'abord, créons une instance backend pour un dispositif d'intérêt. Dans ce qui suit, nous choisissons « ibm_kyoto », « ibm_kawasaki » ou la machine Eagle la moins chargée. Ton accès aux QPU peut différer ; mets à jour le nom du backend en conséquence.
service = QiskitRuntimeService()
# backend = service.backend("ibm_kawasaki") # an Eagle, if you have access to ibm_kawasaki
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=127
) # Eagle
backend.name
'ibm_strasbourg'
Commençons par quelques informations de base (statiques) sur le dispositif.
print(
f"""
{backend.name}, {backend.num_qubits} qubits
processor type = {backend.processor_type}
basis gates = {backend.basis_gates}
"""
)
ibm_strasbourg, 127 qubits
processor type = {'family': 'Eagle', 'revision': 3}
basis gates = ['ecr', 'id', 'rz', 'sx', 'x']
2.1 Exercice
Essaie d'obtenir les informations de base sur un dispositif Heron, « ibm_strasbourg ». Essaie par toi-même, mais du code a été ajouté ci-dessous pour que tu puisses te vérifier.
a_heron = service.backend("ibm_strasbourg") # a Heron
# your code here
print(
f"""
{backend.name}, {a_heron.num_qubits} qubits
processor type = {a_heron.processor_type}
basis gates = {a_heron.basis_gates}
"""
)
ibm_strasbourg, 133 qubits
processor type = {'family': 'Heron', 'revision': '1'}
basis gates = ['cz', 'id', 'rz', 'sx', 'x']
2.2 Carte de couplage
Nous allons maintenant dessiner la carte de couplage du dispositif. Comme tu peux le voir, les nœuds sont des qubits numérotés. Les arêtes indiquent les paires sur lesquelles tu peux directement appliquer la porte d'intrication à 2 qubits. La topologie est appelée un « réseau hexagonal lourd ».
# This function requires that Graphviz is installed. If you need to install Graphviz you can refer to:
# https://graphviz.org/download/#executable-packages for instructions.
try:
fig = backend.coupling_map.draw()
except RuntimeError as ex:
print(ex)
fig

3. Propriétés des qubits
Le dispositif Eagle a 127 qubits. Obtenons les propriétés de certains d'entre eux.
for qn in range(backend.num_qubits):
if qn >= 5:
break
print(f"{qn}: {backend.qubit_properties(qn)}")
0: QubitProperties(t1=0.000183686508736532, t2=0.00023613944465408068, frequency=4832100227.116953)
1: QubitProperties(t1=0.00048794378526038294, t2=9.007098375327869e-05, frequency=4736264354.075363)
2: QubitProperties(t1=0.00021247781834456527, t2=7.81037910324034e-05, frequency=4859349851.150393)
3: QubitProperties(t1=0.0002936462084765663, t2=0.00011400214529510604, frequency=4679749549.503852)
4: QubitProperties(t1=0.00044229440258559125, t2=0.0003181648356339447, frequency=4845872064.050596)
Calculons la médiane des temps T1 des qubits. Compare le résultat avec celui affiché pour le dispositif sur IBM Quantum Platform.
t1s = [backend.qubit_properties(qq).t1 for qq in range(backend.num_qubits)]
f"Median T1: {(statistics.median(t1s)*10**6):.2f} \u03bcs"
'Median T1: 285.43 μs'
3.1 Exercice
Calcule la médiane des temps T2 des qubits. Essaie par toi-même, mais du code a été ajouté ci-dessous pour que tu puisses te vérifier.
# Your code here
t2s = [backend.qubit_properties(qq).t2 for qq in range(backend.num_qubits)]
f"Median T2: {(statistics.median(t2s)*10**6):.2f} \u03bcs"
'Median T2: 173.10 μs'
3.2 Erreurs de portes et de lecture
Nous nous tournons maintenant vers les erreurs de portes. Pour commencer, nous étudions la structure de données de l'instance Target. Il s'agit d'un dictionnaire dont les clés sont des noms d'opérations.
target = backend.target
target.keys()
dict_keys(['measure', 'id', 'sx', 'delay', 'x', 'for_loop', 'rz', 'if_else', 'ecr', 'reset', 'switch_case'])
Ses valeurs sont également des dictionnaires. Examinons certains des éléments de la valeur (dictionnaire) pour l'opération « sx ».
for i, qq in enumerate(target["sx"]):
if i >= 5:
break
print(i, qq, target["sx"][qq])
0 (0,) InstructionProperties(duration=6e-08, error=0.0007401311759115297)
1 (1,) InstructionProperties(duration=6e-08, error=0.0003163759907528654)
2 (2,) InstructionProperties(duration=6e-08, error=0.0003183859004638003)
3 (3,) InstructionProperties(duration=6e-08, error=0.00042235914178831863)
4 (4,) InstructionProperties(duration=6e-08, error=0.011163151923589715)
Faisons de même pour les opérations « ecr » et « measure ».
for i, edge in enumerate(target["ecr"]):
if i >= 5:
break
print(i, edge, target["ecr"][edge])
0 (0, 14) InstructionProperties(duration=6.6e-07, error=0.01486295709788732)
1 (1, 0) InstructionProperties(duration=6.6e-07, error=0.015201590794522601)
2 (2, 1) InstructionProperties(duration=6.6e-07, error=0.00697838102630724)
3 (2, 3) InstructionProperties(duration=6.6e-07, error=0.008075067943986797)
4 (3, 4) InstructionProperties(duration=6.6e-07, error=0.0630164507876913)
for i, qq in enumerate(target["measure"]):
if i >= 5:
break
print(i, qq, target["measure"][qq])
0 (0,) InstructionProperties(duration=1.6e-06, error=0.0078125)
1 (1,) InstructionProperties(duration=1.6e-06, error=0.155029296875)
2 (2,) InstructionProperties(duration=1.6e-06, error=0.057373046875)
3 (3,) InstructionProperties(duration=1.6e-06, error=0.02880859375)
4 (4,) InstructionProperties(duration=1.6e-06, error=0.01318359375)
Comme tu peux le constater, les erreurs de lecture ont tendance à être plus importantes que celles de l'opération à 2 qubits, qui à leur tour ont tendance à être plus importantes que l'opération à 1 qubit.
Ayant compris les structures de données, nous sommes prêts à calculer les erreurs médianes pour les portes « sx » et « ecr ». Compare de nouveau les résultats avec ceux affichés pour le dispositif sur IBM Quantum Platform.
sx_errors = [inst_prop.error for inst_prop in target["sx"].values()]
f"Median SX error: {(statistics.median(sx_errors)):.3e}"
'Median SX error: 2.277e-04'
ecr_errors = [inst_prop.error for inst_prop in target["ecr"].values()]
f"Median ECR error: {(statistics.median(ecr_errors)):.3e}"
'Median ECR error: 6.895e-03'
4. Annexe
Une fonctionnalité populaire de Qiskit est sa capacité de visualisation. Elle comprend des visualiseurs de circuits, de visualiseurs d'états et de distributions, et un visualiseur de Target. Tu as déjà utilisé les deux premiers dans les notebooks jupyter précédents. Utilisons quelques fonctionnalités du visualiseur de Target.
from qiskit.visualization import plot_gate_map
plot_gate_map(backend, font_size=14)

from qiskit.visualization import plot_error_map
plot_error_map(backend)

# Check Qiskit version
import qiskit
qiskit.__version__
'2.0.2'