Créer des modèles de bruit pour les portes multi-qubit

Le package Microsoft Quantum Development Kit (QDK) Python prend en charge des modèles de bruit flexibles pour les portes à plusieurs qubits dans les simulations de programmes quantiques. Vous pouvez modéliser des erreurs corrélées et d’autres effets sonores sur plusieurs qubits pour représenter plus précisément le comportement du matériel quantique.

Pour plus d’informations sur les modèles de bruit dans le QDK, consultez Comment créer des modèles de bruit pour les simulations quantiques dans le QDK.

Prerequisites

Pour générer des modèles de bruit dans le QDK, installez les outils suivants.

pip install --upgrade "qdk[jupyter]"

Bruit corrélé

Les portes multi-qubits peuvent produire un bruit corrélé, où le même modèle de bruit s’applique à tous les qubits sur lesquels la porte fonctionne. Pour définir le bruit corrélé sur les portes multi-qubits, spécifiez un paramètre de bruit pour chaque qubit.

Par exemple, le code Python suivant définit des inversions de bits corrélées sur les portes $CX$ avec une probabilité de 2 %. Lorsque le bruit se produit sur une porte $CX$, une porte $X$ s’applique à la fois au qubit de contrôle et au qubit cible. Le bruit est corrélé car le bruit s’applique toujours aux deux qubits.

from qdk.simulation import NoiseConfig

noise = NoiseConfig()

noise.cx.xx = 0.02

Pour rendre le bruit non corrélé, définissez plusieurs types de bruit avec le paramètre d’identité.

noise.cx.xi = 0.02 # Bit flip on control qubit, do nothing to target qubit
noise.cx.ix = 0.02 # Do nothing to control qubit, bit flip on target qubit

Dans le modèle sans corrélation, chaque paramètre de bruit se produit indépendamment avec 2% probabilité. Étant donné qu’une seule configuration de bruit peut s’appliquer à une porte donnée, ce modèle de bruit ne peut pas appliquer un bruit $X$ aux deux qubits d’une même porte.

Pour modéliser la possibilité de bruit sur les deux qubits, configurez un autre paramètre de bruit qui applique le bruit aux deux qubits.

noise.cx.xi = 0.02 # Bit flip on control qubit, do nothing to target qubit
noise.cx.ix = 0.02 # Do nothing to control qubit, bit flip on target qubit
noise.cx.xx = 0.02 # Bit flip on both qubits

Politiques de perte de qubits

La perte de qubit est un type de bruit où les qubits sont perdus de l’appareil. Les politiques de perte définissent le comportement d’une porte multi-qubit lorsqu’un ou plusieurs qubits sont absents au début de l’opération. Le QDK prend en charge les stratégies de perte suivantes.

Politique de perte Portes auxquelles la stratégie peut s’appliquer Effet sur les qubits restants
SKIP Toutes les portes La porte n’a aucun effet sur les qubits restants
PROPAGATE Toutes les portes Les autres qubits sont également perdus
DEGRADE rxx ,ryy et rzz Appliquer comme porte à un qubit au qubit restant
RESIDUAL_S_DAGGER Toutes les portes Appliquer la porte s_sdj aux qubits restants
APPLY_ANYWAY swap Le qubit restant continue d’échanger son état avec le qubit perdu

Pour que les stratégies de perte affectent votre simulation, vous devez inclure la perte de qubits dans votre modèle de bruit. Les qubits perdus sont suivis pendant la simulation. Les stratégies de perte s’appliquent lorsqu’une porte agit sur au moins un qubit perdu.

Pour inclure des politiques de perte dans votre modèle de bruit, utilisez LossPolicy du module qdk.simulation. Le code suivant montre des exemples pour définir chaque stratégie.

from qdk.simulation import NoiseConfig, LossPolicy

noise = NoiseConfig()

noise.x.l = 0.01 # 1% chance of qubit loss after X gates

noise.cz.on_loss   = LossPolicy.SKIP               # Don't apply CZ to remaining qubit
noise.cx.on_loss   = LossPolicy.PROPAGATE          # Both qubits are lost from CX gate
noise.rxx.on_loss  = LossPolicy.DEGRADE            # Apply Rx gate to remaining qubit
noise.ryy.on_loss  = LossPolicy.RESIDUAL_S_DAGGER  # Apply S-adjoint to remaining qubit
noise.swap.on_loss = LossPolicy.APPLY_ANYWAY       # Perform swap anyway

Pour toutes les stratégies de perte, le bruit configuré peut encore affecter les qubits restants. Par exemple, le code suivant peut toujours appliquer un bruit d’inversion de bit aux portes CZ même lorsqu’un des qubits d’une porte CZ est manquant.

noise.z.l = 0.01 # Introduce qubit loss

noise.cz.xx = 0.02 # Set correlated bit flip noise on CZ gates
noise.cz.on_loss = LossPolicy.SKIP

Intrinsèques de bruit personnalisées

Pour créer des modèles de bruit plus complexes, le QDK dispose d’instructions intrinsèques de bruit personnalisées pour les programmes Q# et OpenQASM. Les intrinsèques de bruit se comportent comme des portes personnalisées que vous insérez dans votre programme pour modéliser le bruit corrélé. Vous pouvez utiliser des fonctions intrinsèques personnalisées pour modéliser le bruit sur les portes prises en charge par NoiseConfig ou sur des portes personnalisées.

Les exemples suivants montrent comment construire une fonction intrinsèque de bruit personnalisée qui modélise la diaphonie entre trois qubits. L’intrinsèque de bruit applique des retournements de bits corrélés à deux des qubits après l’application d’une porte $CNOT$.

Ajouter des fonctions intrinsèques de bruit à un programme Q#

Dans les programmes Q#, utilisez@NoiseIntrinsic() pour déclarer une primitive intrinsèque de bruit. Ensuite, utilisez la méthode intrinsic de NoiseConfig pour configurer l’intrinsèque de bruit.

Pour configurer et utiliser l’exemple d’intrinsèque de bruit, suivez ces étapes dans un Jupyter Notebook.

  1. Importez les objets requis et définissez le profil cible QIR.

    from qdk import init, TargetProfile
    from qdk import qsharp
    from qdk.simulation import run_qir, NoiseConfig
    
    init(target_profile=TargetProfile.Adaptive_RIF)
    
  2. Écrivez un programme Q# appelé GHZ qui appelle une intrinsèque de bruit appelée Crosstalk3Q après chaque porte $CNOT$.

    %%qsharp
    
    // A noise intrinsic representing crosstalk on 3 qubits.
    // In the ideal circuit this is a no-op; the simulator injects
    // Pauli errors according to the NoiseConfig.
    @NoiseIntrinsic()
    operation Crosstalk3Q(q0: Qubit, q1: Qubit, q2: Qubit) : Unit {
        body intrinsic;
    }
    
    // Prepare a GHZ state on 3 qubits, with crosstalk after each CNOT.
    operation GHZ() : Result[] {
        use qs = Qubit[3];
        H(qs[0]);
        CNOT(qs[0], qs[1]);
        Crosstalk3Q(qs[0], qs[1], qs[2]);  // crosstalk hits all 3 qubits
        CNOT(qs[1], qs[2]);
        Crosstalk3Q(qs[0], qs[1], qs[2]);  // crosstalk again
        MResetEachZ(qs)
    }
    
  3. Configurez la table de bruit pour le paramètre intrinsèque. Définissez le nombre de qubits, les types de bruit et la probabilité de chaque type de bruit.

    noise = NoiseConfig()
    table = noise.intrinsic("Crosstalk3Q", num_qubits=3)
    table.ixx = 0.10  # 10% XX on qubits 1-2
    table.xxi = 0.05  #  5% XX on qubits 0-1
    
  4. Compilez le programme en QIR.

    qir = qsharp.compile("GHZ()")
    
  5. Exécutez la simulation et le tracé de l’histogramme des résultats.

    result = run_qir(qir, shots=1000, noise=noise)
    Histogram(result)
    
  6. Pour comparer le résultat à une simulation sans bruit, réexécutez la simulation sans modèle de bruit.

    result = run_qir(qir, shots=1000)
    Histogram(result)
    

Ajouter des intrinsèques de bruit à un programme OpenQASM

Dans les programmes OpenQASM, utilisez @qdk.qir.noise_intrinsic pour créer un bruit intrinsèque en tant que définition de porte personnalisée. Ensuite, utilisez la méthode intrinsic de NoiseConfig pour configurer l’intrinsèque de bruit.

Pour écrire un programme OpenQASM avec un intrinsèque de bruit appelé crosstalk_3q et compiler le programme en QIR, exécutez le code suivant dans un notebook Jupyter.

from qdk.openqasm import compile, OutputSemantics
from qdk import TargetProfile
from qdk.simulation import run_qir, NoiseConfig
from qdk.widgets import Histogram

qasm_source = """
OPENQASM 3.0;
include "stdgates.inc";

// A noise intrinsic representing crosstalk on 3 qubits.
// In the ideal circuit this is a no-op; the simulator injects
// Pauli errors according to the NoiseConfig.
@qdk.qir.noise_intrinsic
gate crosstalk_3q q0, q1, q2 {}

qubit[3] qs;

// Prepare a GHZ state on 3 qubits, with crosstalk after each CNOT.
h qs[0];
cx qs[0], qs[1];
crosstalk_3q qs[0], qs[1], qs[2];  // crosstalk hits all 3 qubits
cx qs[1], qs[2];
crosstalk_3q qs[0], qs[1], qs[2];  // crosstalk again

bit[3] res = measure qs;
"""

qir_qasm = compile(
    qasm_source,
    output_semantics=OutputSemantics.OpenQasm,
    target_profile=TargetProfile.Base,
)

Pour configurer l’intrinsèque du bruit et exécuter la simulation, exécutez le code suivant.

noise = NoiseConfig()
table = noise.intrinsic("crosstalk_3q", num_qubits=3)
table.ixx = 0.10  # 10% XX on qubits 1-2
table.xxi = 0.05  #  5% XX on qubits 0-1

result = run_qir(qir_qasm, shots=1000, noise=noise)
Histogram(result)