Creación de modelos de ruido para puertas de varios cúbits

El Microsoft Quantum Development Kit (QDK) admite, mediante su paquete de Python, modelos de ruido flexibles para puertas de varios cúbits en simulaciones de programas cuánticos. Puede modelar errores correlacionados y otros efectos de ruido en varios cúbits para representar con más precisión el comportamiento del hardware cuántico.

Para obtener más información sobre los modelos de ruido en QDK, vea Cómo crear modelos de ruido para simulaciones cuánticas en QDK.

Prerequisites

Para crear modelos de ruido en QDK, instale las siguientes herramientas.

pip install --upgrade "qdk[jupyter]"

Ruido correlacionado

Las puertas de varios cúbits pueden producir ruido correlacionado, donde el mismo patrón de ruido se aplica a todos los cúbits en los que opera la puerta. Para configurar el ruido correlacionado en puertas de varios cúbits, especifique un parámetro de ruido para cada cúbit.

Por ejemplo, el siguiente código de Python establece volteos de bits correlacionados en puertas $CX$ con una probabilidad del 2 %. Cuando se produce ruido en una puerta $CX$, una puerta $X$ se aplica tanto al cúbit de control como al cúbit de destino. El ruido se correlaciona porque el ruido siempre se aplica a ambos cúbits.

from qdk.simulation import NoiseConfig

noise = NoiseConfig()

noise.cx.xx = 0.02

Para que el ruido no esté relacionado, establezca varios tipos de ruido con el parámetro identity.

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

En el modelo no relacionado, cada configuración de ruido se produce de forma independiente con 2% probabilidad. Dado que solo se puede aplicar una configuración de ruido a una puerta concreta, este modelo de ruido no puede aplicar ruido $X$ a ambos qubits de la misma puerta.

Para modelar la posibilidad de ruido en ambos cúbits, configure otro valor de ruido que aplique ruido a ambos cúbits.

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 pérdida de cúbits

La pérdida de cúbits es un tipo de ruido en el que los cúbits se pierden del dispositivo. Las políticas de pérdida definen el comportamiento de una puerta multicúbit cuando uno o varios de los cúbits no están presentes al comenzar la operación. El QDK admite las siguientes políticas de pérdida.

Política de pérdidas Puertas a las que se puede aplicar la directiva Efecto en los cúbits restantes
SKIP Todas las puertas La puerta no tiene ningún efecto en los cúbits restantes
PROPAGATE Todas las puertas Los otros cúbits también se pierden
DEGRADE rxx ,ryy y rzz Aplicar como puerta de un solo cúbit al cúbit restante
RESIDUAL_S_DAGGER Todas las puertas Aplicar la puerta s_sdj a los cúbits restantes
APPLY_ANYWAY swap El qubit restante sigue intercambiando estados con el qubit perdido

Para que las políticas de pérdida afecten a su simulación, debe incluir la pérdida de cúbits en el modelo de ruido. Se realiza un seguimiento de los cúbits perdidos durante la simulación. Las políticas de pérdida se aplican cuando una puerta opera sobre al menos un cúbit perdido.

Para incluir políticas de pérdida en su modelo de ruido, utilice LossPolicy del módulo qdk.simulation. En el código siguiente se muestran ejemplos para establecer cada directiva.

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

En todas las políticas de pérdida, el ruido configurado puede seguir afectando a los cúbits restantes. Por ejemplo, el siguiente código puede seguir aplicando ruido de volteo de bits en puertas CZ aunque falte uno de los cúbits de una puerta 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

Intrínsecas de ruido personalizadas

Para crear modelos de ruido más complejos, QDK dispone de operaciones intrínsecas de ruido personalizadas para programas Q# y OpenQASM. Las intrínsecas de ruido se comportan como puertas personalizadas que se insertan en el programa para modelar el ruido correlacionado. Puede usar funciones intrínsecas personalizadas para modelar el ruido en las compuertas que admite NoiseConfig o en compuertas personalizadas.

Los siguientes ejemplos muestran cómo crear una intrínseca de ruido personalizada que modele la diafonía entre tres qubits. La función intrínseca de ruido aplica inversiones de bits correlacionadas a dos de los qubits tras aplicar una puerta $CNOT$.

Añadir funciones intrínsecas de ruido a un programa Q#

En los programas Q#, utiliza@NoiseIntrinsic() para declarar una función intrínseca de ruido. A continuación, utilice el método intrinsic de NoiseConfig para configurar el ruido intrínseco.

Para configurar y utilizar la función intrínseca de ruido del ejemplo, sigue estos pasos en un Jupyter Notebook.

  1. Importe los objetos necesarios y establezca el 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. Escribe un programa Q# llamado GHZ que llame a una función intrínseca de ruido llamada Crosstalk3Q después de cada puerta $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. Configura la tabla de ruido para la función intrínseca. Establezca el número de cúbits, los tipos de ruido y la probabilidad de cada tipo de ruido.

    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 el programa en QIR.

    qir = qsharp.compile("GHZ()")
    
  5. Ejecute la simulación y el trazado del histograma de los resultados.

    result = run_qir(qir, shots=1000, noise=noise)
    Histogram(result)
    
  6. Para comparar el resultado con una simulación sin ruido, vuelva a ejecutar la simulación sin ningún modelo de ruido.

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

Agregar funciones intrínsecas de ruido a un programa OpenQASM

En los programas de OpenQASM, utiliza @qdk.qir.noise_intrinsic para crear una función intrínseca de ruido como definición de puerta personalizada. A continuación, utilice el método intrinsic de NoiseConfig para configurar el ruido intrínseco.

Para escribir un programa OpenQASM con una función intrínseca de ruido llamada crosstalk_3q y compilar el programa en QIR, ejecute el código siguiente en un cuaderno de Jupyter.

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 el ruido intrínseco y ejecutar la simulación, ejecute el código siguiente.

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)