דלג לתוכן הראשי
פרויקט זה בשלב בטא. מצאת באג? פתח issue ב-GitHub. יש שאלה או רעיון? שאל ב-Discussions — נשמח לשמוע ממך!
מה איכות התרגום בדף זה?

התחלה מהירה

המדריך הזה מדגים דוגמה מינימלית עובדת של החבילה qiskit-addon-pna. אנחנו משתמשים בספיגת רעש מופץ (PNA) כדי לבנות אובזרבבל שמפחית רעש. בהינתן מעגל ומודל רעש Pauli-Lindblad, PNA מפיצה קלאסית את האובזרבבל דרך ערוץ הרעש ההפוך. מדידת האובזרבבל שהתקבל על QPU רועש מפחיתה את רעש השערים שנלמד.

כדי לראות איך בונים תהליך עבודה מציאותי ומריצים על חומרה קוונטית עם מודל ההרצה המכוון, כולל לימוד מודל הרעש עם NoiseLearnerV3, עיינו במדריך PNA ב-IBM Quantum Platform.

1. הכנת הקלטים ל-PNA​

PNA מקבלת כקלט מעגל, מודל רעש ואובזרבבל. כאן אנחנו בונים מודל Ising עם שדה רוחבי בן 10 qubits בקירוב Trotter על שרשרת חד-ממדית. אנחנו יוצרים מודל רעש Pauli-Lindblad אקראי בן 2 מקומות לכל שער הסתבכות, ומטמיעים אותו כהוראת PauliLindbladError של Qiskit Aer ממש לפני אותו שער. אנחנו בוחרים למדידה אובזרבבל Pauli-Z במשקל 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)

Output of the previous code cell

2. יצירת האובזרבבל שמפחית רעש​

generate_noise_mitigating_observable מפיצה כל מחולל פאולי של ערוץ הרעש ההפוך קדימה עד סוף המעגל. לאחר מכן האובזרבבל מופץ לאחור דרך ערוץ הרעש ההפוך, ומוחזר אובזרבבל חדש O~\tilde{O}. שלושה פרמטרים מרכזיים משפיעים על עלות החישוב:

  • max_err_terms: מספר האיברים שנשמרים בכל מחולל אנטי-רעש בזמן שהוא מופץ קדימה.

  • max_obs_terms: מספר האיברים שנשמרים ב-O~\tilde{O}.

  • atol: איברים שגודל המקדם שלהם נמוך מהסף הזה מושמטים.

עבור המעגל הקטן הזה, הקרוב ל-Clifford, אנחנו קובעים מגבלות גבוהות על מספר האיברים ומשתמשים ב-atol צנוע, כך ש-O~\tilde{O} נשאר קטן ואפשר למדוד את כל האיברים שלו.

הערה: הפונקציה הזו משתמשת ב-multiprocessing של Python. כשמריצים כסקריפט, יש לקרוא לה בתוך שמירה של 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. הפחתת שגיאות שערים על ידי מדידת האובזרבבל שמפחית רעש​

כאן אנחנו רואים שהאובזרבבל החדש מפחית ביעילות את רעש השערים שמשפיע על הניסוי.

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

Output of the previous code cell