Avvio rapido
Questa guida illustra un esempio minimale funzionante del qiskit-addon-pna pacchetto. Utilizziamo l'assorbimento del rumore propagato (PNA) per costruire un osservabile di mitigazione del rumore. Dato un circuito e un modello di rumore di Pauli-Lindblad, il PNA propaga classicamente l’osservabile attraverso il canale di rumore inverso. La misurazione dell'osservabile risultante sulla QPU soggetta a rumore attenua il rumore dei gate appreso.
Per scoprire come creare un flusso di lavoro realistico ed eseguirlo su hardware quantistico con il modello di esecuzione diretta, compreso l’apprendimento del modello di rumore con NoiseLearnerV3, consulta il tutorial PNA su IBM Quantum Platform.
1. Preparare i dati di input per il PNA
PNA accetta come input un circuito, un modello di rumore e un osservabile. In questo lavoro realizziamo un modello di Ising a campo trasversale trotterizzato a 10 qubit su una catena di tipo “ 1D ”. Generiamo un modello di rumore di Pauli-Lindblad a 2 locali casuale per ogni gate di entanglement e lo inseriamo come istruzione Qiskit Aer PauliLindbladError proprio prima di quel gate. Scegliamo un osservabile di Pauli-Z weight-4 da misurare.
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:
2. Generare l'osservabile di mitigazione del rumore
generate_noise_mitigating_observable propaga in avanti ciascun generatore di Pauli del canale di rumore inverso fino alla fine del circuito. L'osservabile viene quindi sottoposto a retropropagazione attraverso il canale di rumore inverso, restituendo un nuovo osservabile . Tre parametri chiave influenzano il costo di calcolo:
max_err_terms: il numero di termini conservati in ciascun generatore anti-rumore man mano che la propagazione procede in avanti.max_obs_terms: il numero di termini presenti in .atol: i termini con un coefficiente inferiore a tale soglia vengono scartati.
atolPer questo piccolo circuito, simile a quello di Clifford, abbiamo fissato limiti elevati per i termini e utilizziamo un valore modesto, in modo che l' e rimanga piccolo e possiamo misurare tutti i suoi termini.
Nota: questa funzione utilizza Python multiprocessing. Quando lo si esegue come script, richiamarlo all'interno di 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. Ridurre gli errori di gate misurando l'osservabile di mitigazione del rumore
Qui vediamo che il nuovo osservabile mitiga efficacemente il rumore del gate che influisce sull'esperimento.
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