Skip to main content
IBM Quantum Platform

Inicio rápido

Esta guía muestra un ejemplo mínimo y funcional del paquete qiskit-addon-pna . Utilizamos la absorción de ruido propagada (PNA) para construir un observable que mitigue el ruido. Dado un circuito y un modelo de ruido de Pauli-Lindblad, el PNA propaga clásicamente la observable a través del canal de ruido inverso. La medición de la magnitud observable resultante en la QPU con ruido atenúa el ruido de las puertas aprendidas.

Para ver cómo crear un flujo de trabajo realista y ejecutarlo en hardware cuántico con el modelo de ejecución dirigida, incluido el aprendizaje del modelo de ruido con NoiseLearnerV3, consulta el tutorial de PNA en IBM Quantum Platform.


1. Preparar los datos de entrada para PNA

El PNA toma como entradas un circuito, un modelo de ruido y una variable observable. Aquí construimos un modelo de Ising de campo transversal «trotterizado» de 10 qubits en una cadena de tipo « 1D ». Generamos un modelo aleatorio de ruido de Pauli-Lindblad de 2 locales para cada puerta de entrelazamiento y lo incorporamos como una instrucción de Qiskit Aer PauliLindbladError justo antes de dicha puerta. Elegimos un observable de Pauli-Z weight-4 para medirlo.

import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp, pauli_basis
from qiskit_aer.noise import PauliLindbladError


def random_pauli_lindblad_noise(generators, seed, noise_scale=2e-3):
    rates = np.random.default_rng(seed).random(len(generators)) * noise_scale
    return PauliLindbladError(generators, rates)


def ising_circuit(
    num_qubits,
    layers,
    edge_noise=None,
    *,
    num_steps=3,
    rx_angle=np.pi / 8,
    rzz_angle=-np.pi / 2,
):
    """Trotterized transverse-field Ising model; edge_noise=None gives the noiseless circuit."""
    qc = QuantumCircuit(num_qubits)
    for _ in range(num_steps):
        qc.rx(rx_angle, range(num_qubits))
        for layer in layers:
            for edge in layer:
                if edge_noise is not None:
                    qc.append(
                        edge_noise[edge], edge
                    )  # inject synthetic gate noise
                qc.rzz(rzz_angle, *edge)
    return qc


num_qubits = 10

# Two entangling layers per Trotter step: even and odd bonds of a 1D chain
layers = [
    [(i, i + 1) for i in range(0, num_qubits - 1, 2)],
    [(i, i + 1) for i in range(1, num_qubits - 1, 2)],
]
edges = [edge for layer in layers for edge in layer]

# Random 2-local Pauli-Lindblad noise, one instance per entangling gate
two_qubit_paulis = SparsePauliOp(
    [p for p in pauli_basis(2) if np.sum(p.x + p.z)]
).paulis
edge_noise = {
    edge: random_pauli_lindblad_noise(two_qubit_paulis, seed=1234 + j)
    for j, edge in enumerate(edges)
}

noisy_circuit = ising_circuit(num_qubits, layers, edge_noise)

# A single weight-4 observable: <Z3 Z4 Z5 Z6>
observable = SparsePauliOp.from_sparse_list(
    [("ZZZZ", [3, 4, 5, 6], 1.0)], num_qubits=num_qubits
)

noisy_circuit.draw("mpl", fold=-1, scale=0.6)

Output:

Output of the previous code cell

2. Generar la observable de mitigación del ruido

«generate_noise_mitigating_observable» propaga cada generador de Pauli del canal de ruido inverso hacia adelante hasta el final del circuito. A continuación, la observable se propaga hacia atrás a través del canal de ruido inverso, lo que devuelve una nueva observable O~\tilde{O}. Hay tres parámetros clave que influyen en el coste computacional:

  • max_err_terms: el número de términos que se conservan en cada generador antirruido a medida que se propaga hacia adelante.
  • max_obs_terms: el número de términos que se conservan en O~\tilde{O}.
  • atol: los términos cuyo coeficiente sea inferior a este umbral se descartan.

atolPara este pequeño circuito cercano a Clifford, fijamos los límites de los términos en valores elevados y utilizamos un valor modesto, de modo que O~\tilde{O} sigue siendo pequeño y podemos medir todos sus términos.

Nota: Esta función utiliza Python multiprocessing. Si lo ejecutas como script, llámalo dentro de un if __name__ == "__main__": guard.

from qiskit_addon_pna import generate_noise_mitigating_observable

mitigating_observable = generate_noise_mitigating_observable(
    noisy_circuit,
    observable,
    max_err_terms=100_000,
    max_obs_terms=100_000,
    atol=1e-5,
    num_processes=4,
)

print(f"Original observable:         {len(observable)} term")
print(f"Noise-mitigating observable: {len(mitigating_observable)} terms")

Output:

Original observable:         1 term
Noise-mitigating observable: 207 terms

3. Mitigar los errores de puerta midiendo el observable de mitigación del ruido

Aquí vemos que el nuevo observable mitiga de forma efectiva el ruido de la puerta que afecta al experimento.

import matplotlib.pyplot as plt
from qiskit_aer.primitives import EstimatorV2

noiseless_circuit = ising_circuit(num_qubits, layers)

# density_matrix method at zero precision -> exact expectation values (no shot noise)
estimator = EstimatorV2(
    options={
        "backend_options": {"method": "density_matrix"},
        "default_precision": 0.0,
    }
)

ideal, noisy, mitigated = (
    result.data.evs
    for result in estimator.run(
        [
            (noiseless_circuit, observable),
            (noisy_circuit, observable),
            (noisy_circuit, mitigating_observable),
        ]
    ).result()
)

print(f"Ideal (noiseless):   {ideal:.4f}")
print(f"Noisy (unmitigated): {noisy:.4f}")
print(f"Mitigated (PNA):     {mitigated:.4f}")

fig, ax = plt.subplots()
ax.bar(
    ["Noisy", "Mitigated"],
    [noisy, mitigated],
    width=0.6,
    color=["#b0b0b0", "#4c4c4c"],
)
ax.axhline(ideal, color="green", linestyle="--", label="Ideal (noiseless)")
ax.set_ylabel(r"$\langle Z_3 Z_4 Z_5 Z_6 \rangle$")
ax.legend()
plt.show()

Output:

Ideal (noiseless):   0.8073
Noisy (unmitigated): 0.6431
Mitigated (PNA):     0.8071
Output of the previous code cell
¿Le ha resultado útil esta página?
Informe de un error, de una errata o solicite contenido en GitHub.