Pornire rapidă
Acest ghid prezintă un exemplu funcțional minimal al pachetului qiskit-addon-pna. Folosim absorbția zgomotului propagat (PNA) pentru a construi un observabil care atenuează zgomotul. Dat fiind un circuit și un model de zgomot Pauli-Lindblad, PNA propagă clasic observabilul prin canalul de zgomot invers. Măsurarea observabilului rezultat pe QPU-ul zgomotos atenuează zgomotul de porți învățat.
Pentru a vedea cum să construiești un flux de lucru realist și să rulezi pe hardware cuantic cu modelul de execuție dirijată, inclusiv învățarea modelului de zgomot cu NoiseLearnerV3, consultă tutorialul PNA de pe IBM Quantum Platform.
1. Pregătește intrările pentru PNA
PNA primește ca intrare un circuit, un model de zgomot și un observabil. Aici construim un model Ising cu câmp transversal trotterizat, de 10 qubiți, pe un lanț 1D. Generăm un model aleatoriu de zgomot Pauli-Lindblad 2-local pentru fiecare poartă de încâlcire și îl încorporăm ca instrucțiune PauliLindbladError din Qiskit Aer chiar înaintea porții respective. Alegem de măsurat un observabil Pauli-Z cu pondere 4.
# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util
_needed = {"matplotlib": "matplotlib", "numpy": "numpy", "qiskit": "qiskit", "qiskit_addon_pna": "qiskit-addon-pna", "qiskit_aer": "qiskit-aer"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
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)

2. Generează observabilul care atenuează zgomotul
generate_noise_mitigating_observable propagă înainte, până la sfârșitul circuitului, fiecare generator Pauli al canalului de zgomot invers. Observabilul este apoi retropropagat prin canalul de zgomot invers, returnând un nou observabil . Trei parametri cheie afectează costul de calcul:
-
max_err_terms: numărul de termeni păstrați în fiecare generator anti-zgomot pe măsură ce este propagat înainte. -
max_obs_terms: numărul de termeni păstrați în . -
atol: termenii cu magnitudinea coeficientului sub acest prag sunt eliminați.
Pentru acest circuit mic, aproape Clifford, setăm limitele de termeni la valori mari și folosim un atol modest, astfel încât rămâne mic și îi putem măsura toți termenii.
Notă: această funcție folosește multiprocessing din Python. Când rulezi ca script, apeleaz-o în interiorul unui bloc de protecție if __name__ == "__main__":.
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")
Original observable: 1 term
Noise-mitigating observable: 207 terms
3. Atenuează erorile de porți măsurând observabilul care atenuează zgomotul
Aici vedem că noul observabil atenuează eficient zgomotul de porți care afectează experimentul.
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()
Ideal (noiseless): 0.8073
Noisy (unmitigated): 0.6431
Mitigated (PNA): 0.8071