Швидкий старт
Цей посібник демонструє мінімальний робочий приклад пакета qiskit-addon-pna. Ми використовуємо поглинання поширеного шуму (PNA), щоб побудувати спостережувану, яка пом'якшує шум. Для заданої схеми та шумової моделі Паулі-Ліндбладa PNA класично поширює спостережувану крізь обернений шумовий канал. Вимірювання отриманої спостережуваної на шумному QPU пом'якшує вивчений шум гейтів.
Щоб побачити, як побудувати реалістичний робочий процес і виконати його на квантовій апаратурі за допомогою моделі спрямованого виконання, зокрема з навчанням моделі шуму за допомогою NoiseLearnerV3, ознайомся з туторіалом PNA на IBM Quantum Platform.
1. Підготуй вхідні дані для PNA
PNA приймає на вхід схему, модель шуму та спостережувану. Тут ми будуємо 10-кубітну тротеризовану модель Ізінга з поперечним полем на одновимірному ланцюжку. Ми генеруємо випадкову 2-локальну шумову модель Паулі-Ліндблада для кожного заплутувального гейта та вбудовуємо її як інструкцію Qiskit Aer PauliLindbladError безпосередньо перед цим гейтом. Для вимірювання ми обираємо спостережувану Паулі-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)

2. Згенеруй спостережувану, що пом'якшує шум
generate_noise_mitigating_observable поширює кожен генератор Паулі оберненого шумового каналу вперед до кінця схеми. Потім спостережувана зворотно поширюється крізь обернений шумовий канал, що повертає нову спостережувану . Три ключові параметри впливають на обчислювальну вартість:
-
max_err_terms: кількість членів, що зберігаються в кожному антишумовому генераторі під час його прямого поширення. -
max_obs_terms: кількість членів, що зберігаються в . -
atol: члени з модулем коефіцієнта нижче цього порога відкидаються.
Для цієї невеликої майже кліффордової схеми ми встановлюємо високі ліміти на кількість членів і використовуємо помірне atol, тож залишається малою, і ми можемо виміряти всі її члени.
Примітка: ця функція використовує Python multiprocessing. Під час запуску як скрипта викликай її всередині захисту 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