Ruismodellen bouwen voor poorten met meerdere qubits

Het Microsoft Quantum Development-kit (QDK) Python pakket ondersteunt flexibele ruismodellen voor poorten met meerdere qubits in kwantumprogrammasimulaties. U kunt gecorreleerde fouten en andere ruiseffecten op meerdere qubits modelleren om het gedrag van kwantumhardware nauwkeuriger weer te geven.

Voor meer informatie over ruismodellen in de QDK, zie QDK.

Prerequisites

Installeer de volgende hulpprogramma's om ruismodellen in de QDKomgeving te bouwen.

  • Visual Studio Code (VS Code) met QDK extensie en Jupyter extensie geïnstalleerd.
  • De nieuwste versie van het qdkPython pakket met de jupyter extra.
pip install --upgrade "qdk[jupyter]"

Gecorreleerde ruis

Poorten met meerdere qubits kunnen gecorreleerde ruis produceren, waarbij hetzelfde ruispatroon van toepassing is op alle qubits waarop de poort werkt. Als u gecorreleerde ruis wilt instellen voor poorten met meerdere qubits, geeft u een ruisparameter voor elke qubit op.

Met bijvoorbeeld de volgende Python code worden gecorreleerde bitflips op de $CX$-poorten ingesteld met een kans van 2%. Wanneer er ruis optreedt op een $CX$-poort, is een $X$-poort van toepassing op zowel de controle-qubit als de doel-qubit. De ruis wordt gecorreleerd omdat de ruis altijd van toepassing is op beide qubits.

from qdk.simulation import NoiseConfig

noise = NoiseConfig()

noise.cx.xx = 0.02

Als u de ruis niet-gerelateerd wilt maken, stelt u meerdere ruistypen in met de identiteitsparameter.

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 het niet-gerelateerde model vindt elke ruisinstelling onafhankelijk plaats met 2% kans. Omdat slechts één ruisinstelling op een afzonderlijke poort kan worden toegepast, kan dit ruismodel geen $X$ ruis toepassen op beide qubits in dezelfde poort.

Als u de mogelijkheid van ruis op beide qubits wilt modelleren, configureert u een andere ruisinstelling die ruis toepast op beide 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

Qubit-verliesbeleid

Qubitverlies is een soort ruis waarbij qubits verloren gaan van het apparaat. Verliesbeleid definieert het gedrag van een poort met meerdere qubits wanneer een of meer qubits ontbreken wanneer de bewerking begint. QDK ondersteunt de volgende verliesbeleiden.

Verliesbeleid Poorten waarop het beleid van toepassing kan zijn Effect op resterende qubits
SKIP Alle poorten De poort heeft geen effect op de resterende qubits
PROPAGATE Alle poorten De andere qubits gaan ook verloren
DEGRADE rxx ,ryy, en rzz Toepassen als single-qubit-poort op resterende qubit
RESIDUAL_S_DAGGER Alle poorten Pas de s_sdj-poort toe op de resterende qubits
APPLY_ANYWAY swap Resterende qubit wisselt nog steeds statussen met verloren qubit

Als u wilt dat verliesbeleid van invloed is op uw simulatie, moet u qubitverlies opnemen in uw ruismodel. Verloren qubits worden bijgehouden tijdens de simulatie. Verliesbeleid is van toepassing wanneer een poort werkt op ten minste één verloren qubit.

Gebruik LossPolicy uit de module qdk.simulation om verliesbeleidsregels op te nemen in uw ruismodel. In de volgende code ziet u voorbeelden voor het instellen van elk beleid.

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

Voor alle verliesbeleidsregels kan geconfigureerde ruis nog steeds van invloed zijn op de resterende qubits. Met de volgende code kan bijvoorbeeld nog steeds bit flipruis op CZ-poorten worden toegepast, zelfs wanneer een van de qubits in een CZ-poort ontbreekt.

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

Aangepaste ruis intrinsieken

Om complexere ruismodellen op te bouwen, heeft het QDK aangepaste intrinsieke ruisfuncties voor Q#- en OpenQASM-programma's. Ruisintrinsiek gedraagt zich als aangepaste poorten die u in uw programma invoegt om gecorreleerde ruis te modelleren. U kunt aangepaste intrinsieke functies gebruiken om ruis te modelleren op de poorten die door NoiseConfig worden ondersteund, of op aangepaste poorten.

In de volgende voorbeelden ziet u hoe u een aangepast ruisintrinsiek opbouwt dat overspraak tussen drie qubits modelleert. De intrinsieke ruis past gecorreleerde bitflips toe op twee van de qubits nadat een $CNOT$-poort is toegepast.

Ruis intrinsiek toevoegen aan een Q#-programma

Gebruik in Q#-programma's@NoiseIntrinsic() om een intrinsieke ruis te declareren. Gebruik vervolgens de methode intrinsic van NoiseConfig om de intrinsieke ruis te configureren.

Volg deze stappen in een Jupyter notebook om de intrinsieke voorbeeldruis te configureren en te gebruiken.

  1. Importeer de vereiste objecten en stel het QIR-doelprofiel in.

    from qdk import init, TargetProfile
    from qdk import qsharp
    from qdk.simulation import run_qir, NoiseConfig
    
    init(target_profile=TargetProfile.Adaptive_RIF)
    
  2. Schrijf een Q#-programma met de naam GHZ dat na elke $CNOT$-poort een ruisintrinsiek met de naam Crosstalk3Q aanroept.

    %%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. Configureer de ruistabel voor de intrinsieke waarde. Stel het aantal qubits, de typen ruis en de waarschijnlijkheid voor elk ruistype in.

    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. Compileer het programma naar QIR.

    qir = qsharp.compile("GHZ()")
    
  5. Voer de simulatie uit en maak een histogram van de resultaten.

    result = run_qir(qir, shots=1000, noise=noise)
    Histogram(result)
    
  6. Als u het resultaat wilt vergelijken met een simulatie zonder ruis, voert u de simulatie opnieuw uit zonder ruismodel.

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

Ruis intrinsiek toevoegen aan een OpenQASM-programma

Gebruik in OpenQASM-programma's @qdk.qir.noise_intrinsic om een ruis intrinsiek te maken als een aangepaste poortdefinitie. Gebruik vervolgens de methode intrinsic van NoiseConfig om de intrinsieke ruis te configureren.

Om een OpenQASM-programma te schrijven met een ruisintrinsiek genaamd crosstalk_3q en het programma naar QIR te compileren, voert u de volgende code uit in een Jupyter-notebook.

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

Voer de volgende code uit om de intrinsieke ruis te configureren en de simulatie uit te voeren.

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)