Aller au contenu principal

Représenter les ordinateurs quantiques pour le transpileur

Versions des packages

Le code de cette page a été développé avec les dépendances suivantes. Nous recommandons d'utiliser ces versions ou des versions plus récentes.

qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1

Pour convertir un circuit abstrait en circuit ISA pouvant s'exécuter sur un QPU (unité de traitement quantique) spécifique, le transpileur a besoin de certaines informations sur ce QPU. Ces informations se trouvent à deux endroits : l'objet BackendV2 (ou l'ancien BackendV1) vers lequel tu prévois de soumettre des jobs, et l'attribut Target du backend.

  • Le Target contient toutes les contraintes pertinentes d'un appareil, telles que ses portes de base natives, la connectivité des qubits, et les informations d'impulsion ou de timing.
  • Le Backend possède un Target par défaut, contient des informations supplémentaires — comme l'InstructionScheduleMap — et fournit l'interface pour soumettre des jobs de circuit quantique.

Tu peux également fournir explicitement des informations au transpileur, par exemple si tu as un cas d'usage spécifique, ou si tu penses que ces informations l'aideront à générer un circuit plus optimisé.

La précision avec laquelle le transpileur produit le circuit le plus adapté à un matériel spécifique dépend de la quantité d'informations sur ses contraintes que contient le Target ou le Backend.

remarque

Comme beaucoup des algorithmes de transpilation sous-jacents sont stochastiques, il n'est pas garanti qu'un meilleur circuit sera trouvé.

Cette page présente plusieurs exemples de transmission d'informations QPU au transpileur. Ces exemples utilisent la cible du backend fictif FakeSherbrooke.

Configuration par défaut

La façon la plus simple d'utiliser le transpileur est de lui fournir toutes les informations sur le QPU via le Backend ou le Target. Pour mieux comprendre comment fonctionne le transpileur, construis un circuit et transpile-le avec différentes informations, comme suit.

Importe les bibliothèques nécessaires et instancie le QPU :

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-ibm-runtime
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke

backend = FakeSherbrooke()
target = backend.target

L'exemple de circuit utilise une instance d'efficient_su2 de la bibliothèque de circuits de Qiskit.

from qiskit.circuit.library import efficient_su2

qc = efficient_su2(12, entanglement="circular", reps=1)

qc.draw("mpl")

Sortie de la cellule de code précédente

Cet exemple utilise les paramètres par défaut pour transpiler vers le target du backend, qui fournit toutes les informations nécessaires pour convertir le circuit en un circuit pouvant s'exécuter sur le backend.

from qiskit.transpiler import generate_preset_pass_manager

pass_manager = generate_preset_pass_manager(
optimization_level=1, target=target, seed_transpiler=12345
)
qc_t_target = pass_manager.run(qc)
qc_t_target.draw("mpl", idle_wires=False, fold=-1)

Sortie de la cellule de code précédente

Cet exemple est utilisé dans les sections suivantes de ce sujet pour illustrer que la carte de couplage et les portes de base sont les informations essentielles à transmettre au transpileur pour une construction optimale du circuit. Le QPU peut généralement sélectionner des paramètres par défaut pour les autres informations non transmises, comme le timing et la planification.

Carte de couplage

La carte de couplage est un graphe qui montre quels qubits sont connectés et donc disposent de portes à deux qubits entre eux. Ce graphe est parfois directionnel, ce qui signifie que les portes à deux qubits ne peuvent aller que dans un seul sens. Cependant, le transpileur peut toujours inverser la direction d'une porte en ajoutant des portes à qubit unique supplémentaires. Un circuit quantique abstrait peut toujours être représenté sur ce graphe, même si sa connectivité est limitée, en introduisant des portes SWAP pour déplacer l'information quantique.

Les qubits de nos circuits abstraits sont appelés qubits virtuels et ceux de la carte de couplage sont des qubits physiques. Le transpileur fournit une correspondance entre les qubits virtuels et les qubits physiques. L'une des premières étapes de la transpilation, l'étape de layout, effectue cette correspondance.

remarque

Bien que l'étape de routage soit étroitement liée à l'étape de layout — qui sélectionne les qubits réels — par défaut, ce sujet les traite comme des étapes séparées pour simplifier. La combinaison du routage et du layout est appelée mapping de qubits. Pour en savoir plus sur ces étapes, consulte le sujet Étapes du transpileur.

Passe l'argument nommé coupling_map pour voir son effet sur le transpileur :

coupling_map = target.build_coupling_map()

pass_manager = generate_preset_pass_manager(
optimization_level=0, coupling_map=coupling_map, seed_transpiler=12345
)
qc_t_cm_lv0 = pass_manager.run(qc)
qc_t_cm_lv0.draw("mpl", idle_wires=False, fold=-1)

Sortie de la cellule de code précédente

Comme indiqué ci-dessus, plusieurs portes SWAP ont été insérées (chacune composée de trois portes CX), ce qui entraînera beaucoup d'erreurs sur les appareils actuels. Pour voir quels qubits sont sélectionnés sur la topologie réelle des qubits, utilise plot_circuit_layout des visualisations Qiskit :

from qiskit.visualization import plot_circuit_layout

plot_circuit_layout(qc_t_cm_lv0, backend, view="physical")

Sortie de la cellule de code précédente

Cela montre que nos qubits virtuels 0 à 11 ont été trivialement mappés à la ligne de qubits physiques 0 à 11. Revenons au niveau par défaut (optimization_level=1), qui utilise VF2Layout si un routage est nécessaire.

pass_manager = generate_preset_pass_manager(
optimization_level=1, coupling_map=coupling_map, seed_transpiler=12345
)
qc_t_cm_lv1 = pass_manager.run(qc)
qc_t_cm_lv1.draw("mpl", idle_wires=False, fold=-1)

Sortie de la cellule de code précédente

À présent, aucune porte SWAP n'est insérée et les qubits physiques sélectionnés sont les mêmes qu'avec la classe target.

from qiskit.visualization import plot_circuit_layout

plot_circuit_layout(qc_t_cm_lv1, backend, view="physical")

Sortie de la cellule de code précédente

Maintenant le layout est en anneau. Comme ce layout respecte la connectivité du circuit, il n'y a aucune porte SWAP, ce qui donne un circuit bien meilleur pour l'exécution.

Portes de base

Chaque ordinateur quantique prend en charge un ensemble d'instructions limité, appelé ses portes de base. Chaque porte du circuit doit être traduite en éléments de cet ensemble. Cet ensemble doit être composé de portes à un et deux qubits qui forment un ensemble de portes universel, ce qui signifie que toute opération quantique peut être décomposée en ces portes. Cette opération est effectuée par le BasisTranslator, et les portes de base peuvent être spécifiées comme argument nommé du transpileur pour fournir cette information.

basis_gates = list(target.operation_names)
print(basis_gates)
['sx', 'switch_case', 'x', 'if_else', 'measure', 'for_loop', 'delay', 'ecr', 'id', 'reset', 'rz']

Les portes à qubit unique par défaut sur ibm_sherbrooke sont rz, x et sx, et la porte à deux qubits par défaut est ecr (echoed cross-resonance). Les portes CX sont construites à partir de portes ecr, donc sur certains QPUs, ecr est spécifiée comme porte de base à deux qubits, tandis que sur d'autres, cx est la valeur par défaut. La porte ecr est la partie d'intrication de la porte cx. En plus des portes de contrôle, il y a aussi des instructions delay et measurement.

remarque

Les QPUs ont des portes de base par défaut, mais tu peux choisir les portes que tu veux, du moment que tu fournis l'instruction ou que tu ajoutes des portes d'impulsion (voir Créer des passes de transpilation.). Les portes de base par défaut sont celles pour lesquelles des calibrations ont été effectuées sur le QPU, donc aucune instruction supplémentaire ni porte d'impulsion n'est nécessaire. Par exemple, sur certains QPUs cx est la porte à deux qubits par défaut et ecr sur d'autres. Consulte la liste des portes et opérations natives possibles pour plus de détails.

pass_manager = generate_preset_pass_manager(
optimization_level=1,
coupling_map=coupling_map,
basis_gates=basis_gates,
seed_transpiler=12345,
)
qc_t_cm_bg = pass_manager.run(qc)
qc_t_cm_bg.draw("mpl", idle_wires=False, fold=-1)

Sortie de la cellule de code précédente

Note que les objets CXGate ont été décomposés en portes ecr et en portes de base à qubit unique.

Taux d'erreur de l'appareil

La classe Target peut contenir des informations sur les taux d'erreur des opérations sur l'appareil. Par exemple, le code suivant récupère les propriétés de la porte echoed cross-resonance (ECR) entre le qubit 1 et le qubit 0 (note que la porte ECR est directionnelle) :

target["ecr"][(1, 0)]
InstructionProperties(duration=5.333333333333332e-07, error=0.007494257741828603)

La sortie affiche la durée de la porte (en secondes) et son taux d'erreur. Pour révéler les informations d'erreur au transpileur, construis un modèle de cible avec les basis_gates et la coupling_map ci-dessus et remplis-le avec les valeurs d'erreur du backend FakeSherbrooke.

from qiskit.transpiler import Target
from qiskit.circuit.controlflow import IfElseOp, SwitchCaseOp, ForLoopOp

err_targ = Target.from_configuration(
basis_gates=basis_gates,
coupling_map=coupling_map,
num_qubits=target.num_qubits,
custom_name_mapping={
"if_else": IfElseOp,
"switch_case": SwitchCaseOp,
"for_loop": ForLoopOp,
},
)

for i, (op, qargs) in enumerate(target.instructions):
if op.name in basis_gates:
err_targ[op.name][qargs] = target.instruction_properties(i)

Transpile avec notre nouvelle cible err_targ en tant que cible :

pass_manager = generate_preset_pass_manager(
optimization_level=1, target=err_targ, seed_transpiler=12345
)
qc_t_cm_bg_et = pass_manager.run(qc)
qc_t_cm_bg_et.draw("mpl", idle_wires=False, fold=-1)

Sortie de la cellule de code précédente

Comme la cible inclut des informations sur les erreurs, la passe VF2PostLayout tente de trouver les qubits optimaux à utiliser, ce qui donne le même circuit que celui trouvé initialement avec les mêmes qubits physiques.

Étapes suivantes