Crie modelos de ruído para portas multi-qubit

O pacote Microsoft Quantum Development Kit (QDK) Python suporta modelos flexíveis de ruído para portas de vários qubits em simulações de programas quânticos. Pode modelar erros correlacionados e outros efeitos de ruído através de múltiplos qubits para representar com mais precisão o comportamento do hardware quântico.

Para mais informações sobre modelos de ruído no QDK, veja Como construir modelos de ruído para simulações quânticas no QDK.

Pré-requisitos

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

pip install --upgrade "qdk[jupyter]"

Ruído correlacionado

Portas multi-qubits podem produzir ruído correlacionado, onde o mesmo padrão de ruído se aplica a todos os qubits sobre os quais a porta opera. Para definir ruído correlacionado em portas de múltiplos qubits, especifique um parâmetro de ruído para cada qubit.

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

from qdk.simulation import NoiseConfig

noise = NoiseConfig()

noise.cx.xx = 0.02

Para tornar o ruído não correlacionado, defina vários tipos de ruído com o parâmetro 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 correlacionado, cada configuração de ruído ocorre independentemente com 2% de probabilidade. Como apenas uma definição de ruído pode aplicar-se a uma porta individual, este modelo de ruído não pode aplicar ruído de $X$ a ambos os qubits na mesma porta.

Para modelar a possibilidade de ruído em ambos os qubits, configure 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 qubits é 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 multi-qubit quando um ou mais qubits estiverem ausentes no início da operação. O QDK suporta as seguintes políticas de perda.

Apólice de perdas Gates aos quais a política se pode aplicar Efeito nos qubits restantes
SKIP Todos os portões A porta 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 a sua simulação, é necessário 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 aplicam-se quando uma porta opera com pelo menos um qubit perdido.

Para incluir políticas de perda no seu modelo de ruído, utilize LossPolicy do módulo qdk.simulation. O código seguinte 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

Em todas as políticas de perda, o ruído configurado ainda pode afetar os qubits restantes. Por exemplo, o código seguinte pode continuar a aplicar ruído de inversão de bit às portas CZ, mesmo quando falta um dos qubits de uma porta 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

Funções intrínsecas de ruído personalizadas

Para criar modelos de ruído mais complexos, o QDK dispõe de intrínsecos personalizados de ruído para programas Q# e OpenQASM. Os elementos intrínsecos do ruído comportam-se como portas personalizadas que inseres no teu programa para modelar ruído correlacionado. Pode utilizar funções intrínsecas personalizadas para modelar ruído em portas suportadas por NoiseConfig ou em portas personalizadas.

Os exemplos seguintes mostram como construir um ruído intrínseco personalizado que modele a diafonia entre três qubits. O ruído intrínseco aplica inversões de bit correlacionadas a dois dos qubits após a aplicação da porta $CNOT$.

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

Em programas Q#, usa-se@NoiseIntrinsic() para declarar um ruído intrínseco. Depois, utilize o método intrinsic de NoiseConfig para configurar o ruído intrínseco.

Para configurar e usar o exemplo de ruído intrínseco, siga estes passos num Jupyter caderno.

  1. Importa os objetos necessários e define o perfil de alvo 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 chame um ruído intrínseco 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 intrinsic. 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. Compila o programa para QIR.

    qir = qsharp.compile("GHZ()")
    
  5. Executa a simulação e traça 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 novamente a simulação sem modelo de ruído.

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

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

Nos programas OpenQASM, utiliza-se @qdk.qir.noise_intrinsic para criar um ruído intrínseco como definição de porta personalizada. Depois, utilize 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 para QIR, execute o seguinte código num Jupyter caderno.

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 seguinte código.

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)