Criar modelos de ruído para portões de vários qubits

O pacote Microsoft Quantum Development Kit (QDK) Python oferece suporte a modelos de ruído flexíveis para portas de vários qubits em simulações de programas quânticos. Você pode modelar erros correlacionados e outros efeitos de ruído em vários qubits para representar com mais precisão o comportamento do hardware quântico.

Para obter mais informações sobre modelos de ruído no QDK. Consulte Como criar modelos de ruído para simulações quânticas no QDK.

Pré-requisitos

Para criar modelos de ruído no QDK, instale as seguintes ferramentas.

pip install --upgrade "qdk[jupyter]"

Ruído correlacionado

As portas de vários qubits podem produzir ruído correlacionado, em que o mesmo padrão de ruído se aplica a todos os qubits em que o portão opera. Para definir o ruído correlacionado em portas de vários qubits, especifique um parâmetro de ruído para cada qubit.

Por exemplo, o seguinte código Python define inversões de bits correlacionadas em portas $CX$ com uma probabilidade de 2%. Quando ocorre ruído em uma porta $CX$, uma porta $X$ é aplicada tanto ao qubit de controle quanto ao qubit-alvo. O ruído está correlacionado porque o ruído sempre se aplica a ambos os qubits.

from qdk.simulation import NoiseConfig

noise = NoiseConfig()

noise.cx.xx = 0.02

Para tornar o ruído não relacionado, defina vários tipos de ruído com o parâmetro de identidade.

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

No modelo não relacionado, cada configuração de ruído ocorre independentemente com 2% probabilidade. Como apenas uma configuração de ruído pode se aplicar a uma porta individual, esse modelo de ruído não pode aplicar ruído $X$ a ambos os qubits no mesmo portão.

Para modelar a possibilidade de ruído em ambos os qubits, defina outra configuração de ruído que aplique ruído a ambos os 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

Políticas de perda de qubits

A perda de qubit é um tipo de ruído em que os qubits são perdidos do dispositivo. As políticas de perda definem o comportamento de uma porta de vários qubits quando um ou mais dos qubits estão ausentes quando a operação é iniciada. O QDK oferece suporte às seguintes políticas de perda.

Política de perdas Portões aos quais a política se aplica Efeito nos qubits restantes
SKIP Todos os portões O portão não tem efeito sobre os qubits restantes
PROPAGATE Todos os portões Os outros qubits também são perdidos
DEGRADE rxx ,ryy, e rzz Aplicar como porta de qubit único ao qubit restante
RESIDUAL_S_DAGGER Todos os portões Aplicar a porta s_sdj aos qubits restantes
APPLY_ANYWAY swap O qubit restante ainda troca estados com o qubit perdido

Para que as políticas de perda afetem sua simulação, você precisa incluir a perda de qubits no seu modelo de ruído. Os qubits perdidos são rastreados durante a simulação. As políticas de perda se aplicam quando uma porta opera em pelo menos um qubit perdido.

Para incluir políticas de perda em seu modelo de ruído, use LossPolicy do módulo qdk.simulation. O código a seguir mostra exemplos para definir cada política.

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

Para todas as políticas de perda, o ruído configurado ainda pode afetar os qubits restantes. Por exemplo, o seguinte código ainda pode aplicar ruído de inversão de bits em portas CZ mesmo quando um dos qubits em uma porta CZ estiver faltando.

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

Intrínsecos de ruído personalizados

Para criar modelos de ruído mais complexos, o QDK tem intrínsecos de ruído personalizados para programas Q# e OpenQASM. Os intrínsecos de ruído funcionam como portas personalizadas que são inseridas no programa para modelar ruído correlacionado. Você pode usar intrínsecos personalizados para modelar ruído nas portas a que NoiseConfig oferece suporte ou em portas personalizadas.

Os exemplos a seguir mostram como criar um ruído personalizado intrínseco que modela o crosstalk entre três qubits. O intrínseco de ruído aplica inversões de bit correlacionadas a dois dos qubits após a execução de uma porta $CNOT$.

Adicionar intrínsecos de ruído a um programa Q#

Em programas Q#, use@NoiseIntrinsic() para declarar um ruído intrínseco. Em seguida, use o método intrinsic de NoiseConfig para configurar o ruído intrínseco.

Para configurar e usar o exemplo de intrínseco de ruído, siga estas etapas em um Jupyter Notebook.

  1. Importe os objetos necessários e defina o perfil de destino qir.

    from qdk import init, TargetProfile
    from qdk import qsharp
    from qdk.simulation import run_qir, NoiseConfig
    
    init(target_profile=TargetProfile.Adaptive_RIF)
    
  2. Escreva um programa Q# chamado GHZ que chama um intrínseco de ruído chamado Crosstalk3Q após cada 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. Configure a tabela de ruído para o intrínseco. Defina o número de qubits, os tipos de ruído e a probabilidade para cada tipo de ruído.

    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. Compile o programa para QIR.

    qir = qsharp.compile("GHZ()")
    
  5. Execute a simulação e plote o histograma dos resultados.

    result = run_qir(qir, shots=1000, noise=noise)
    Histogram(result)
    
  6. Para comparar o resultado com uma simulação sem ruído, execute a simulação novamente sem nenhum modelo de ruído.

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

Adicionar intrínsecos de ruído a um programa OpenQASM

Em programas OpenQASM, use @qdk.qir.noise_intrinsic para criar um intrínseco de ruído como uma definição de porta personalizada. Em seguida, use o método intrinsic de NoiseConfig para configurar o ruído intrínseco.

Para escrever um programa OpenQASM com um ruído intrínseco chamado crosstalk_3q e compilar o programa no QIR, execute o código a seguir em um 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,
)

Para configurar o ruído intrínseco e executar a simulação, execute o código a seguir.

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)