Creare modelli di rumore per porte multi-qubit

Il pacchetto Microsoft Quantum Development Kit (QDK) Python supporta modelli di rumore flessibili per le porte multi-qubit nelle simulazioni di programmi quantistici. È possibile modellare gli errori correlati e altri effetti non significativi tra più qubit per rappresentare in modo più accurato il comportamento dell'hardware quantistico.

Per altre informazioni sui modelli di rumore in QDK, vedere Come creare modelli di rumore per le simulazioni quantistiche in QDK.

Prerequisiti

Per compilare modelli di rumore in QDK, installare questi strumenti.

pip install --upgrade "qdk[jupyter]"

Rumore correlato

I gate multi-qubit possono produrre rumore correlato, in cui lo stesso modello di rumore si applica a tutti i qubit su cui opera il gate. Per impostare il rumore correlato per le porte multi-qubit, specificare un parametro di rumore per ogni qubit.

Ad esempio, questo Python codice imposta i capovolgimenti di bit correlati su $CX$ gate con una probabilità di 2%. Quando si verifica un rumore su un gate $CX$, un gate $X$ si applica sia al qubit di controllo che al qubit di destinazione. Il rumore è correlato perché il rumore si applica sempre a entrambi i qubit.

from qdk.simulation import NoiseConfig

noise = NoiseConfig()

noise.cx.xx = 0.02

Per rendere il rumore non correlato, configurare più tipi di rumore con il parametro 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

In questo modello ogni voce di rumore ha una probabilità di 2%. Poiché il simulatore campiona al massimo una voce di rumore configurata per ogni operazione di gate, questo modello non può applicare rumore $X$ a entrambi i qubit durante la stessa operazione di $CX$.

Per modellare la possibilità di rumore su entrambi i qubit, configura un'altra impostazione del rumore che applichi rumore a entrambi i qubit.

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

Rumore sulle rotazioni multi-qubit non-Clifford

Il simulatore di stabilizzatori supporta rotazioni arbitrarie $R_{XX}$, $R_{YY}$ e $R_{ZZ}$ tramite il branching dei stabilizzatori. Il rumore configurato in rxx, ryyo rzz viene applicato dopo la rotazione ideale. Questo comportamento non cambia se la rotazione crea rami stabilizzatori aggiuntivi.

Ogni rotazione non-Clifford può aumentare il numero di rami, quindi l'utilizzo della memoria e il tempo di esecuzione possono crescere in modo esponenziale. Usare il simulatore stabilizer per i circuiti con un numero limitato di rotazioni non-Clifford e usare il simulatore di stato completo CPU o GPU quando le operazioni non-Clifford costituiscono una parte sostanziale del circuito.

Politiche di perdita dei qubit

La perdita di qubit è un tipo di disturbo in cui i qubit vengono persi dal dispositivo. Le politiche di perdita definiscono il comportamento di una porta multi-qubit quando uno o più qubit sono assenti all'inizio dell'operazione. Il QDK supporta questi criteri di perdita dati.

Criteri di perdita Gate a cui il criterio può applicarsi Effetto sui qubit rimanenti
SKIP Tutti i cancelli La porta non ha alcun effetto sui qubit rimanenti
PROPAGATE Tutti i cancelli Anche gli altri qubit vengono persi
DEGRADE rxx, ryy e rzz Applica come porta a qubit singolo al qubit rimanente
RESIDUAL_S_DAGGER Tutti i cancelli Applica la porta s_adj ai qubit rimanenti
APPLY_ANYWAY swap Il qubit rimanente continua a scambiare stato con il qubit perso

Affinché le policy di perdita influiscano sulla simulazione, includere la perdita di qubit nel modello di disturbo. La simulazione tiene traccia dei qubit persi. I criteri di perdita si applicano quando un gate opera su almeno un qubit perso.

Per includere le policy di perdita nel modello di rumore, usa LossPolicy dal modulo qdk.simulation. Questo codice mostra esempi per impostare ogni criterio di policy.

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

Per tutti i criteri relativi alla perdita, il rumore configurato può comunque influire sui qubit rimanenti. Ad esempio, questo codice può comunque applicare il rumore di capovolgimento bit ai gate CZ anche quando manca uno dei qubit in un gate CZ.

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

Funzioni intrinseche di rumore personalizzate

Per creare modelli di rumore più complessi, QDK dispone di intrinseci di rumore personalizzati per programmi Q# e OpenQASM. Le intrinseche di rumore si comportano come porte personalizzate che si inseriscono nel programma per modellare il rumore correlato. È possibile usare intrinseche personalizzate per modellare il rumore sulle porte supportate da NoiseConfig o su porte personalizzate.

Questi esempi illustrano come creare un elemento intrinseco del rumore personalizzato che modella la diafonia tra tre qubit. Il rumore intrinseco applica capovolgimenti di bit correlati a due dei qubit dopo l'applicazione di un gate $CNOT$.

Aggiungere intrinseche di noise a un Q# programma

Nei Q# programmi usare @NoiseIntrinsic() per dichiarare un'intrinseca noise. Usare quindi il intrinsic metodo da NoiseConfig per configurare l'intrinseco rumore.

Per configurare e usare l'intrinseco rumore di esempio, seguire questa procedura in un Jupyter notebook.

  1. Importare gli oggetti necessari e impostare il profilo di destinazione QIR.

    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. Scrivere un Q# programma denominato GHZ che chiama un intrinseco di rumore chiamato Crosstalk3Q dopo ogni gate $CNOT$.

    %%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. Configurare la tabella del rumore per l'intrinseco. Impostare il numero di qubit, i tipi di rumore e la probabilità per ogni tipo di rumore.

    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. Compilare il programma in QIR.

    qir = qsharp.compile("GHZ()")
    
  5. Eseguire la simulazione nel simulatore dello stabilizzatore e tracciare un istogramma dei risultati.

    result = run_qir(qir, shots=1000, noise=noise, type="stabilizer")
    Histogram(result)
    
  6. Per confrontare il risultato con una simulazione senza rumore, eseguire di nuovo la simulazione senza alcun modello di rumore.

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

Aggiungere intrinseche del rumore a un OpenQASM programma

Nei OpenQASM programmi, usare @qdk.qir.noise_intrinsic per creare un noise intrinsic come definizione di gate personalizzata. Usare quindi il intrinsic metodo da NoiseConfig per configurare l'intrinseco rumore.

Per scrivere un OpenQASM programma con un intrinseco rumore denominato crosstalk_3q e compilare il programma in QIR, eseguire questo codice in un 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 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,
)

Per configurare il rumore intrinseco ed eseguire la simulazione, eseguire questo codice.

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)