Rauschmodelle für Multi-Qubit-Gates erstellen

Das Microsoft Quantum Development Kit (QDK) Python Paket unterstützt flexible Rauschmodelle für Multi-Qubit-Gatter in Simulationen von Quantenprogrammen. Sie können korrelierte Fehler und andere Rauscheffekte über mehrere Qubits modellieren, um das Verhalten der Quantenhardware genauer darzustellen.

Weitere Informationen zu Rauschmodellen im QDK finden Sie unter Erstellen von Rauschmodellen für Quantensimulationen im QDK.

Voraussetzungen

Um Rauschmodelle in QDK zu erstellen, installieren Sie diese Tools.

pip install --upgrade "qdk[jupyter]"

Korreliertes Rauschen

Mehr-Qubit-Gates können korreliertes Rauschen erzeugen, bei dem dasselbe Rauschmuster auf alle Qubits angewendet wird, auf die das Gate wirkt. Um korreliertes Rauschen bei Multi-Qubit-Gattern festzulegen, geben Sie für jedes Qubit einen Rauschparameter an.

Dieser Python Code legt beispielsweise korrelierte Bit-Flips auf $CX$ Gates mit einer Wahrscheinlichkeit von 2% fest. Wenn Rauschen auf einem $CX$-Gate auftreten, gilt ein $X$-Gate sowohl für das Steuer-Qubit als auch für das Ziel-Qubit. Das Rauschen ist korreliert, da es immer auf beide Qubits wirkt.

from qdk.simulation import NoiseConfig

noise = NoiseConfig()

noise.cx.xx = 0.02

Um das Rauschen unkorreliert zu machen, legen Sie mehrere Rauschtypen mit dem Parameter „identity“ fest.

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

In diesem Modell weist jeder Rauscheintrag eine Wahrscheinlichkeit von 2% auf. Da der Simulator höchstens einen konfigurierten Rauscheintrag für jeden Gate-Vorgang auswählt, kann dieses Modell nicht $X$-Rauschen auf beide Qubits während desselben $CX$-Vorgangs anwenden.

Um die Möglichkeit von Rauschen auf beiden Qubits zu modellieren, konfigurieren Sie eine weitere Rauscheinstellung, die Rauschen auf beide Qubits anwendet.

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

Rauschen bei Nicht-CliffordMulti-Qubit-Rotationen

Der Stabilisator-Simulator unterstützt $R_{XX}$-, $R_{YY}$- und $R_{ZZ}$-Drehungen um beliebige Winkel durch Stabilisator-Verzweigung. Auf rxx, ryy oder rzz konfiguriertes Rauschen wird nach der idealen Drehung angewendet. Dieses Verhalten ändert sich nicht, wenn die Drehung zusätzliche Stabilisierungszweige erstellt.

Jede Nicht-Clifford-Rotation kann die Anzahl der Verzweigungen erhöhen, sodass die Speicherauslastung und die Ausführungszeit exponentiell wachsen können. Verwenden Sie den Stabilisierungssimulator für Schaltkreise mit einer begrenzten Anzahl von Nicht-Clifford-Rotationen und verwenden Sie den CPU- oder GPU-Gesamtzustandssimulator, wenn Nicht-Clifford-Vorgänge einen wesentlichen Teil der Schaltung bilden.

Qubit-Verlustrichtlinien

Qubit-Verlust ist eine Art von Rauschen, bei dem Qubits vom Gerät verloren gehen. Verlustregeln legen das Verhalten eines Mehr-Qubit-Gatters fest, wenn zu Beginn des Vorgangs eines oder mehrere der Qubits fehlen. Das QDK unterstützt diese Verlustrichtlinien.

Verlustrichtlinie Gates, für die die Richtlinie gelten kann Auswirkung auf verbleibende Qubits
SKIP Alle Tore Das Tor wirkt sich nicht auf die verbleibenden Qubits aus
PROPAGATE Alle Tore Die anderen Qubits gehen ebenfalls verloren
DEGRADE rxx, ryy und rzz Als Single-Qubit-Gate auf das verbleibende Qubit anwenden
RESIDUAL_S_DAGGER Alle Tore Das s_adj-Gatter auf die verbleibenden Qubits anwenden
APPLY_ANYWAY swap Das verbleibende Qubit tauscht weiterhin Zustände mit dem verlorenen Qubit aus.

Damit Verlustrichtlinien Ihre Simulation beeinflussen, schließen Sie Qubit-Verlust in Ihr Rauschmodell ein. Die Simulation verfolgt verlorene Qubits. Verlustrichtlinien gelten, wenn ein Gate mit mindestens einem verlorenen Qubit arbeitet.

Verwenden Sie LossPolicy aus dem qdk.simulation-Modul, um Verlustrichtlinien in Ihr Rauschmodell einzuschließen. Dieser Code zeigt Beispiele zum Festlegen der einzelnen Richtlinien.

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

Für alle Verlustrichtlinien kann sich das konfigurierte Rauschen weiterhin auf die verbleibenden Qubits auswirken. Dieser Code kann z. B. weiterhin Bit-Flip-Rauschen auf CZ-Toren anwenden, auch wenn einer der Qubits in einem CZ-Tor fehlt.

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

Benutzerdefiniertes systeminternes Rauschen

Um komplexere Rauschmodelle zu erstellen, hat das QDK benutzerdefinierte Noise-Intrinsics für Q#- und OpenQASM-Programme. Systeminternes Rauschen verhält sich wie benutzerdefinierte Gatter, die Sie in Ihr Programm einfügen, um korreliertes Rauschen zu modellieren. Sie können benutzerdefiniertes systeminternes Rauschen verwenden, um das Rauschen an den Gattern zu modellieren, die von NoiseConfig unterstützt werden, oder an benutzerdefinierten Gattern.

In diesen Beispielen wird gezeigt, wie Sie ein benutzerdefiniertes Rausch-Intrinsic erstellen, das die Übersprechung zwischen drei Qubits modelliert. Das intrinsische Rauschen wendet korrelierte Bit-Flips auf zwei der Qubits an, nachdem ein $CNOT$ Gate angewendet wurde.

Hinzufügen von Noise-Intrinsics zu einem Q# Programm

Verwenden Sie in @NoiseIntrinsic() Programmen Q#, um das noise-Intrinsic zu deklarieren. Verwenden Sie anschließend die Methode intrinsic aus NoiseConfig, um das systeminterne Rauschen zu konfigurieren.

Um das systeminterne Rauschen aus dem Beispiel zu konfigurieren und zu verwenden, führen Sie die folgenden Schritte in einem Jupyter Notebook aus.

  1. Importieren Sie die erforderlichen Objekte, und legen Sie das QIR Zielprofil fest.

    from qdk import init, TargetProfile
    from qdk import qsharp
    from qdk.simulation import run_qir, NoiseConfig
    from qdk.widgets import Histogram
    
    init(target_profile=TargetProfile.Adaptive_RIF)
    
  2. Schreiben Sie ein Q#-Programm namens GHZ, das nach jedem $Crosstalk3Q$-Gate eine Rausch-Intrinsic namens CNOT aufruft.

    %%qsharp
    
    // A noise intrinsic that represents 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. Konfigurieren Sie die Rauschtabelle für das systeminterne Rauschen. Legen Sie die Anzahl der Qubits, die Typen von Rauschen und die Wahrscheinlichkeit für jeden Rauschtyp fest.

    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. Kompilieren Sie das Programm in QIR.

    qir = qsharp.compile("GHZ()")
    
  5. Führen Sie die Simulation auf dem Stabilisierungssimulator aus und zeichnen Sie ein Histogramm der Ergebnisse.

    result = run_qir(qir, shots=1000, noise=noise, type="stabilizer")
    Histogram(result)
    
  6. Um das Ergebnis mit einer Simulation ohne Rauschen zu vergleichen, führen Sie die Simulation ohne Rauschmodell erneut aus.

    result = run_qir(qir, shots=1000, type="stabilizer")
    Histogram(result)
    

Hinzufügen von Noise-Intrinsics zu einem OpenQASM Programm

Verwenden Sie in @qdk.qir.noise_intrinsic Programmen OpenQASM, um ein Noise-Intrinsic als benutzerdefinierte Gate-Definition zu erstellen. Verwenden Sie anschließend die Methode intrinsic aus NoiseConfig, um das systeminterne Rauschen zu konfigurieren.

Um ein OpenQASM Programm mit einem Rausch-Intrinsic namens crosstalk_3q zu schreiben und das Programm zu QIRkompilieren, führen Sie diesen Code in einem Jupyter Notizbuch aus.

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 that represents 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,
)

Führen Sie diesen Code aus, um das intrinsische Rauschen zu konfigurieren und die Simulation auszuführen.

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,
    type="stabilizer",
)
Histogram(result)