Aller au contenu principal
Ce projet est en phase bêta. Tu as trouvé un bug ? Ouvrir un ticket GitHub. Une question ou une idée ? Pose ta question dans Discussions — tes retours sont les bienvenus !
Quelle est la qualité de la traduction sur cette page ?

Matériel

remarque

Masao Tokunari and Tamiya Onodera (14 June 2024)

Ce cours est basé sur un cours donné en direct à l'Université de Tokyo.

Le PDF du cours 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 pourraient devenir obsolètes car il s'agit d'images statiques.

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 — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"qiskit": "qiskit", "qiskit_ibm_runtime": "qiskit-ibm-runtime"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
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

Output of the previous code cell

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)

Output of the previous code cell

from qiskit.visualization import plot_error_map

plot_error_map(backend)

Output of the previous code cell

# Check Qiskit version
import qiskit

qiskit.__version__
'2.0.2'