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 creare modelli di rumore in QDK, installare i seguenti 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, il codice seguente Python imposta i capovolgimenti di bit correlati sui cancelli $CX$ 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

Nel modello non correlato, ogni configurazione di rumore si verifica in modo indipendente con una probabilità del 2%. Poiché a una singola porta può essere applicata una sola impostazione di rumore, questo modello di rumore non può applicare rumore $X$ a entrambi i qubit della stessa porta.

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

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. QDK supporta i criteri di perdita seguenti.

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 gate 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_sdj ai qubit rimanenti
APPLY_ANYWAY swap Il qubit rimanente continua a scambiare stato con il qubit perso

Affinché i criteri di perdita abbiano effetto sulla simulazione, è necessario includere la perdita di qubit nel modello di rumore. I qubit persi vengono rilevati durante la simulazione. 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. Il codice seguente mostra esempi per impostare ogni criterio.

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, il codice seguente può comunque applicare il rumore di inversione di bit alle porte CZ, anche se uno dei qubit di una porta CZ è mancante.

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 personalizzati per il rumore per i 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.

Gli esempi seguenti mostrano come costruire un intrinseco di rumore personalizzato che modella la diafonia tra tre qubit. L'effetto intrinseco del rumore applica i capovolgimenti di bit correlati a due dei qubit dopo l'applicazione di un gate $CNOT$.

Aggiungere operazioni intrinseche di rumore a un programma Q#

Nei programmi Q# usare@NoiseIntrinsic() per dichiarare un intrinseco rumore. 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
    
    init(target_profile=TargetProfile.Adaptive_RIF)
    
  2. Scrivere un programma Q# chiamato GHZ che richiama un intrinseco di rumore chiamato Crosstalk3Q dopo ogni porta $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. 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. Esegui la simulazione e traccia il grafico dell'istogramma dei risultati.

    result = run_qir(qir, shots=1000, noise=noise)
    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)
    Histogram(result)
    

Aggiungere oggetti intrinseci del rumore a un programma OpenQASM

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

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

Per configurare l'intrinseco rumore ed eseguire la simulazione, eseguire il codice seguente.

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)