Skip to main content
IBM Quantum Platform

Définir le niveau d'optimisation du transpiler

  • Le code de cette page a été développé en tenant compte des exigences suivantes. Nous recommandons d'utiliser ces versions ou des versions plus récentes.

    qiskit[all]~=2.5.1
    qiskit-ibm-runtime~=0.47.0
    

Les dispositifs quantiques réels sont sujets au bruit et aux erreurs de porte, de sorte que l'optimisation des circuits pour réduire leur profondeur et le nombre de portes peut améliorer de manière significative les résultats obtenus lors de l'exécution de ces circuits. La fonction generate_preset_pass_manager a un argument de position obligatoire, optimization_level, qui contrôle l'effort que le transpileur consacre à l'optimisation des circuits. Cet argument peut être un nombre entier prenant l'une des valeurs 0, 1, 2 ou 3. Des niveaux d'optimisation plus élevés génèrent des circuits plus optimisés au prix de temps de compilation plus longs. Le tableau suivant explique les optimisations réalisées avec chaque paramètre.

Niveau d'optimisation
Description
0

Pas d'optimisation : typiquement utilisé pour la caractérisation du matériel

  • Traduction de base
  • Disposition/Routage : TrivialLayout, où il sélectionne les mêmes numéros de qubits physiques que virtuels et insère des SWAPs pour que cela fonctionne (en utilisant SabreSwap)
1

Optimisation de la lumière :

  • Mise en page/Routage : La mise en page est d'abord tentée avec TrivialLayout. Si des SWAP supplémentaires sont nécessaires, une disposition avec un nombre minimum de SWAP est trouvée en utilisant SabreSwap, puis VF2LayoutPostLayout pour essayer de sélectionner les meilleurs qubits dans le graphe.
  • InverseCancellation
  • 1Q optimisation de la porte
2

Optimisation moyenne :

  • Mise en page/routage : Optimisation de niveau 1 (sans trivialité) + heuristique optimisée avec une plus grande profondeur de recherche et des essais de la fonction d'optimisation avec une plus grande profondeur de recherche et des essais de la fonction d'optimisation. Comme TrivialLayout n'est pas utilisé, il n'y a pas de tentative d'utiliser les mêmes numéros de qubits physiques et virtuels.
  • CommutativeCancellation
3

Haute optimisation :

  • Optimisation niveau 2 + heuristique optimisée sur l'agencement/le routage avec plus d'efforts/essais
  • Resynthèse de blocs à deux qubits à l'aide de la décomposition KAK de Cartan.
  • Passes brisant l'unité :
    • OptimizeSwapBeforeMeasure: Déplace les mesures pour éviter les SWAPs
    • RemoveDiagonalGatesBeforeMeasure: Supprime les portes avant les mesures qui n'auraient pas d'effet sur les mesures

Niveau d'optimisation en action

Étant donné que les portes à deux qubits sont généralement la source d'erreurs la plus importante, nous pouvons quantifier approximativement l'"efficacité matérielle" de la transpilation en comptant le nombre de portes à deux qubits dans le circuit résultant. Ici, nous allons essayer les différents niveaux d'optimisation sur un circuit d'entrée composé d'un unitaire aléatoire suivi d'une porte SWAP.

from qiskit import QuantumCircuit
from qiskit.circuit.library import UnitaryGate
from qiskit.quantum_info import Operator, random_unitary

UU = random_unitary(4, seed=12345)
rand_U = UnitaryGate(UU)

qc = QuantumCircuit(2)
qc.append(rand_U, range(2))
qc.swap(0, 1)
qc.draw("mpl", style="iqp")

Output:

Output of the previous code cell
Note

Le backend FakeSherbrooke fictif de qiskit_ibm_runtime est utilisé dans ces exemples, mais vous pouvez l'essayer sur n'importe quel backend réel ou fictif compatible avec Qiskit. Vos résultats peuvent varier.

Commençons par effectuer la transpilation avec un niveau d'optimisation de 0.

from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke

backend = FakeSherbrooke()

pass_manager = generate_preset_pass_manager(
    optimization_level=0, backend=backend, seed_transpiler=12345
)
qc_t1_exact = pass_manager.run(qc)
qc_t1_exact.draw("mpl", idle_wires=False)

Output:

Output of the previous code cell

Le circuit transposé comporte six portes ECR à deux qubits.

Répéter pour le niveau d'optimisation 1 :

from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke

backend = FakeSherbrooke()

pass_manager = generate_preset_pass_manager(
    optimization_level=1, backend=backend, seed_transpiler=12345
)
qc_t1_exact = pass_manager.run(qc)
qc_t1_exact.draw("mpl", idle_wires=False)

Output:

Output of the previous code cell

Le circuit transposé comporte toujours six portes ECR, mais le nombre de portes à qubit unique a été réduit.

Répétez l'opération pour le niveau d'optimisation 2 :

pass_manager = generate_preset_pass_manager(
    optimization_level=2, backend=backend, seed_transpiler=12345
)
qc_t2_exact = pass_manager.run(qc)
qc_t2_exact.draw("mpl", idle_wires=False)

Output:

Output of the previous code cell

Cela donne les mêmes résultats que le niveau d'optimisation 1. Notez que l'augmentation du niveau d'optimisation ne fait pas toujours la différence.

Répétez l'opération avec le niveau d'optimisation 3 :

pass_manager = generate_preset_pass_manager(
    optimization_level=3, backend=backend, seed_transpiler=12345
)
qc_t3_exact = pass_manager.run(qc)
qc_t3_exact.draw("mpl", idle_wires=False)

Output:

Output of the previous code cell

Aujourd'hui, il n'y a plus que trois portes ECR. Nous obtenons ce résultat parce qu'au niveau d'optimisation 3, Qiskit tente de resynthétiser des blocs de portes de deux qubits, et que toute porte de deux qubits peut être implémentée en utilisant au plus trois portes ECR. Nous pouvons obtenir encore moins de portes ECR si nous fixons approximation_degree à une valeur inférieure à 1, ce qui permet au transpilateur de faire des approximations susceptibles d'introduire une erreur dans la décomposition de la porte (voir Paramètres couramment utilisés pour la transpilation ) :

pass_manager = generate_preset_pass_manager(
    optimization_level=3,
    approximation_degree=0.99,
    backend=backend,
    seed_transpiler=12345,
)
qc_t3_approx = pass_manager.run(qc)
qc_t3_approx.draw("mpl", idle_wires=False)

Output:

Output of the previous code cell

Ce circuit ne comporte que deux portes ECR, mais il s'agit d'un circuit approximatif. Pour comprendre en quoi son effet diffère de celui du circuit exact, nous pouvons calculer la fidélité entre l'opérateur unitaire que ce circuit met en œuvre et l'opérateur unitaire exact. Avant d'effectuer le calcul, nous réduisons d'abord le circuit transpilé, qui contient 127 qubits, à un circuit qui ne contient que les qubits actifs, qui sont au nombre de deux.

import numpy as np


def trace_to_fidelity_2q(trace: float) -> float:
    return (4.0 + trace * trace.conjugate()) / 20.0


# Reduce circuits down to 2 qubits so they are easy to simulate
qc_t3_exact_small = QuantumCircuit.from_instructions(qc_t3_exact)
qc_t3_approx_small = QuantumCircuit.from_instructions(qc_t3_approx)

# Compute the fidelity
exact_fid = trace_to_fidelity_2q(
    np.trace(np.dot(Operator(qc_t3_exact_small).adjoint().data, UU))
)
approx_fid = trace_to_fidelity_2q(
    np.trace(np.dot(Operator(qc_t3_approx_small).adjoint().data, UU))
)
print(
    f"Synthesis fidelity\nExact: {exact_fid:.3f}\nApproximate: {approx_fid:.3f}"
)

Output:

Synthesis fidelity
Exact: 1.000+0.000j
Approximate: 0.992+0.000j

Le réglage du niveau d'optimisation peut également modifier d'autres aspects du circuit, et pas seulement le nombre de portes ECR. Pour voir des exemples illustrant comment la modification du niveau d'optimisation influe sur la disposition, consultez la section « Représentation des ordinateurs quantiques ».


Etapes suivantes

Recommandations
Cette page a-t-elle été utile ?
Signaler un bogue, une coquille ou proposer du contenu sur GitHub.