Matériel
Masao Tokunari et Tamiya Onodera (14 juin 2024)
Ce cours est basé sur un cours en direct dispensé à l'Université de Tokyo.
L'exposé pdf de cette leçon a été divisé en deux parties. Télécharger la partie 1 et télécharger la partie 2. Notez que certains extraits de code peuvent devenir obsolètes car il s'agit d'images statiques.
1. Introduction
Cette leçon explore le matériel moderne d'informatique quantique.
Nous commencerons par vérifier quelques versions et par importer quelques paquets pertinents.
import statistics
from qiskit_ibm_runtime import QiskitRuntimeService2. Backend et cible
Qiskit fournit une API permettant d'obtenir des informations, à la fois statiques et dynamiques, sur un dispositif quantique. Nous utilisons une instance Backend pour interfacer avec un appareil, qui comprend une instance Target, un modèle de machine abstraite qui résume les caractéristiques pertinentes telles que l'architecture du jeu d'instructions (ISA) et toutes les propriétés ou contraintes qui y sont associées. Utilisons ces instances backend pour obtenir certaines des informations que vous voyez sur la page Ressources de calcul sur IBM Quantum® Platform. Tout d'abord, nous créons une instance de backend pour l'appareil qui nous intéresse. Dans ce qui suit, nous choisissons "ibm_kyoto", "ibm_kawasaki" ou la machine Eagle la moins occupée. Votre accès aux QPU peut être différent; mettez à 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.nameOutput:
'ibm_strasbourg'
Nous commençons par quelques informations de base (statiques) sur l'appareil.
print(
f"""
{backend.name}, {backend.num_qubits} qubits
processor type = {backend.processor_type}
basis gates = {backend.basis_gates}
"""
)Output:
ibm_strasbourg, 127 qubits
processor type = {'family': 'Eagle', 'revision': 3}
basis gates = ['ecr', 'id', 'rz', 'sx', 'x']
2.1 Exercice
Essayez d'obtenir les informations de base sur un appareil Heron, "ibm_strasbourg". Essayez par vous-même, mais le code a été ajouté ci-dessous pour que vous puissiez vérifier par vous-même.
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}
"""
)Output:
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 de l'appareil. Comme vous pouvez le voir, les nœuds sont des qubits numérotés. Les arêtes indiquent les paires auxquelles vous pouvez directement appliquer la porte d'enchevêtrement à 2 qubits. Cette topologie est appelée "treillis lourd-hex".
# 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)
figOutput:
3. Propriétés des qubits
Le dispositif Eagle possède 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)}")Output:
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. Comparez le résultat à celui obtenu pour l'appareil 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"Output:
'Median T1: 285.43 μs'
3.1 Exercice
Pease calcule la médiane des temps T2 des qubits. Essayez par vous-même, mais le code a été ajouté ci-dessous pour que vous puissiez vérifier par vous-même.
# 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"Output:
'Median T2: 173.10 μs'
3.2 Erreurs de porte et d'affichage
Nous allons maintenant nous pencher sur les erreurs de point d'entrée. Pour commencer, nous étudions la structure des données de l'instance cible. Il s'agit d'un dictionnaire dont les clés sont les noms des opérations.
target = backend.target
target.keys()Output:
dict_keys(['measure', 'id', 'sx', 'delay', 'x', 'for_loop', 'rz', 'if_else', 'ecr', 'reset', 'switch_case'])
Ses valeurs sont également des dictionnaires. Examinons quelques-uns des éléments de la valeur (dictionnaire) de l'opération "sx".
for i, qq in enumerate(target["sx"]):
if i >= 5:
break
print(i, qq, target["sx"][qq])Output:
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])Output:
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])Output:
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 vous pouvez 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.
Après avoir compris les structures de données, nous sommes prêts à calculer les erreurs médianes pour les portes 'sx' et 'ecr'. Comparez à nouveau les résultats avec ceux obtenus pour l'appareil sur la plate-forme Quantum IBM
sx_errors = [inst_prop.error for inst_prop in target["sx"].values()]
f"Median SX error: {(statistics.median(sx_errors)):.3e}"Output:
'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}"Output:
'Median ECR error: 6.895e-03'
4. Annexe
L'une des caractéristiques les plus appréciées de Qiskit est sa capacité de visualisation. Il comprend des visualisateurs de circuits, des visualisateurs d'état et de distribution et des visualisateurs de cibles. Vous avez déjà utilisé les deux premiers dans les précédents carnets jupyter. Utilisons certaines capacités du visualisateur de cibles.
from qiskit.visualization import plot_gate_map
plot_gate_map(backend, font_size=14)Output:
from qiskit.visualization import plot_error_map
plot_error_map(backend)Output:
# Check Qiskit version
import qiskit
qiskit.__version__Output:
'2.0.2'