Побудова моделей шуму
Версії пакетів
Код на цій сторінці розроблено з використанням наведених нижче залежностей. Рекомендуємо використовувати ці версії або новіші.
qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1
qiskit-aer~=0.17
На цій сторінці показано, як використовувати модуль noise бібліотеки Qiskit Aer для побудови моделей шуму при симуляції квантових схем в умовах наявності помилок. Це корисно для емуляції «галасливих» квантових процесорів та для вивчення впливу шуму на виконання квантових алгоритмів.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-aer qiskit-ibm-runtime
import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Kraus, SuperOp
from qiskit.visualization import plot_histogram
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_aer import AerSimulator
# Import from Qiskit Aer noise module
from qiskit_aer.noise import (
NoiseModel,
QuantumError,
ReadoutError,
depolarizing_error,
pauli_error,
thermal_relaxation_error,
)
Модуль noise у Qiskit Aer
Модуль noise бібліотеки Qiskit Aer містить Python-класи для побудови налаштованих моделей шуму для симуляції. Є три ключові класи:
-
Клас
NoiseModel— зберігає модель шуму, що використовується під час «галасливої» симуляції. -
Клас
QuantumError— описує CPTP-помилки гейтів. Їх можна застосовувати:- Після інструкцій gate (гейт) або reset (скидання)
- Перед інструкціями measure (вимірювання).
-
Клас
ReadoutError— описує класичні помилки зчитування.
Ініціалізація моделі шуму з бекенду
Модель шуму можна ініціалізувати з параметрами, отриманими з найновіших даних калібрування фізичного бекенду:
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
backend = service.backend("ibm_fez")
noise_model = NoiseModel.from_backend(backend)
Це дасть модель шуму, що приблизно відтворює помилки, з якими можна зіткнутися під час використання цього бекенду. Якщо тобі потрібен детальніший контроль над параметрами моделі шуму, доведеться створити власну модель шуму — як описано в решті цієї сторінки.
Квантові помилки
Замість того щоб напряму працювати з об'єктом QuantumError, зручніше користуватися численними допоміжними функціями, які автоматично генерують конкретний тип параметризованої квантової помилки. Вони містяться в модулі noise і охоплюють багато поширених типів помилок, що використовуються у дослідженнях квантових обчислень. Назви функцій і типи пом илок, які вони повертають:
| Стандартна функція помилки | Деталі |
|---|---|
kraus_error | загальний n-кубітний CPTP-канал помилки, заданий у вигляді списку матриць Крауса . |
mixed_unitary_error | n-кубітна змішана унітарна помилка, задана у вигляді списку унітарних матриць та ймовірностей . |
coherent_unitary_error | n-кубітна когерен тна унітарна помилка, задана у вигляді єдиної унітарної матриці . |
pauli_error | n-кубітний канал помилки Паулі (змішана унітарна) у вигляді списку операторів Паулі та ймовірностей |
depolarizing_error | n-кубітний деполяризуючий канал помилки, параметризований імовірністю деполяризації . |
reset_error | одно-кубітна помилка скидання, параметризована ймовірностями скидання до стану , . |
thermal_relaxation_error | одно-кубітний канал теплової релаксації, параметризований константами часу релаксації , , часом гейту та тепловою заселеністю збудженого стану . |
phase_amplitude_damping_error | одно-кубітний узагальнений комбінований канал загасання фази та амплітуди, заданий параметром загасання амплітуди , параметром загасання фази та тепловою заселеністю збудженого стану . |
amplitude_damping_error | одно-кубітний узагальнений канал загасання амплітуди, заданий параметром загасання амплітуди та тепловою заселеністю збудженого стану . |
phase_damping_error | одно-кубітний канал загасання фази, заданий параметром загасання фази . |
Комбінування квантових помилок
Екземпляри QuantumError можна комбінувати за допомогою композиції, тензорного добутку та розгорнутого тензорного добутку (тензорний добуток у зворотному порядку), щоб отримувати нові QuantumError:
- Композиція: —
error = error1.compose(error2) - Тензорний добуток: —
error = error1.tensor(error2) - Розгорнутий добуток: —
error = error1.expand(error2)
Приклад
Побудова 5% одно-кубітної помилки перевертання біту:
# Construct a 1-qubit bit-flip and phase-flip errors
p_error = 0.05
bit_flip = pauli_error([("X", p_error), ("I", 1 - p_error)])
phase_flip = pauli_error([("Z", p_error), ("I", 1 - p_error)])
print(bit_flip)
print(phase_flip)
QuantumError on 1 qubits. Noise circuits:
P(0) = 0.05, Circuit =
┌───┐
q: ┤ X ├
└───┘
P(1) = 0.95, Circuit =
┌───┐
q: ┤ I ├
└───┘
QuantumError on 1 qubits. Noise circuits:
P(0) = 0.05, Circuit =
┌───┐
q: ┤ Z ├
└───┘
P(1) = 0.95, Circuit =
┌───┐
q: ┤ I ├
└───┘
# Compose two bit-flip and phase-flip errors
bitphase_flip = bit_flip.compose(phase_flip)
print(bitphase_flip)
QuantumError on 1 qubits. Noise circuits:
P(0) = 0.0025000000000000005, Circuit =
┌───┐┌───┐
q: ┤ X ├┤ Z ├
└───┘└───┘
P(1) = 0.0475, Circuit =
┌───┐┌───┐
q: ┤ X ├┤ I ├
└───┘└───┘
P(2) = 0.0475, Circuit =
┌───┐┌───┐
q: ┤ I ├┤ Z ├
└───┘└───┘
P(3) = 0.9025, Circuit =
┌───┐┌───┐
q: ┤ I ├┤ I ├
└───┘└───┘
# Tensor product two bit-flip and phase-flip errors with
# bit-flip on qubit-0, phase-flip on qubit-1
error2 = phase_flip.tensor(bit_flip)
print(error2)
QuantumError on 2 qubits. Noise circuits:
P(0) = 0.0025000000000000005, Circuit =
┌───┐
q_0: ┤ X ├
├───┤
q_1: ┤ Z ├
└───┘
P(1) = 0.0475, Circuit =
┌───┐
q_0: ┤ I ├
├───┤
q_1: ┤ Z ├
└───┘
P(2) = 0.0475, Circuit =
┌───┐
q_0: ┤ X ├
├───┤
q_1: ┤ I ├
└───┘
P(3) = 0.9025, Circuit =
┌───┐
q_0: ┤ I ├
├───┤
q_1: ┤ I ├
└───┘
Перетворення до та з операторів QuantumChannel
Можна також перетворювати між об'єктами QuantumError у Qiskit Aer та об'єктами QuantumChannel у Qiskit і навпаки.
# Convert to Kraus operator
bit_flip_kraus = Kraus(bit_flip)
print(bit_flip_kraus)
Kraus([[[-9.74679434e-01+0.j, 0.00000000e+00+0.j],
[ 0.00000000e+00+0.j, -9.74679434e-01+0.j]],
[[ 0.00000000e+00+0.j, 2.23606798e-01+0.j],
[ 2.23606798e-01+0.j, -4.96506831e-17+0.j]]],
input_dims=(2,), output_dims=(2,))
# Convert to Superoperator
phase_flip_sop = SuperOp(phase_flip)
print(phase_flip_sop)
SuperOp([[1. +0.j, 0. +0.j, 0. +0.j, 0. +0.j],
[0. +0.j, 0.9+0.j, 0. +0.j, 0. +0.j],
[0. +0.j, 0. +0.j, 0.9+0.j, 0. +0.j],
[0. +0.j, 0. +0.j, 0. +0.j, 1. +0.j]],
input_dims=(2,), output_dims=(2,))
# Convert back to a quantum error
print(QuantumError(bit_flip_kraus))
# Check conversion is equivalent to original error
QuantumError(bit_flip_kraus) == bit_flip
QuantumError on 1 qubits. Noise circuits:
P(0) = 1.0, Circuit =
┌───────┐
q: ┤ kraus ├
└───────┘
True
Помилка зчитування
Класичні помилки зчитування задаються списком векторів імовірностей присвоєння :
- — записане значення класичного біту
- — справжнє значення біту, отримане з вимірювання
Наприклад, для одного кубіту: .
# Measurement misassignment probabilities
p0given1 = 0.1
p1given0 = 0.05
ReadoutError([[1 - p1given0, p1given0], [p0given1, 1 - p0given1]])
ReadoutError([[0.95 0.05]
[0.1 0.9 ]])
Помилки зчитування також можна комбінувати за допомогою compose, tensor та expand, як і квантові помилки.
Додавання помилок до моделі шуму
Коли додаємо квантову помилку до моделі шуму, потрібно вказати тип інструкції, на яку вона діє, та кубіти, до яких її застосовувати. Є два варіанти квантових помилок:
- Помилка для всіх кубітів
- Помилка для конкретних кубітів
1. Помилка для всіх кубітів
Застосовує однакову помилку до кожного входження інструкції, незалежно від того, на які кубіти вона діє.
Додається як noise_model.add_all_qubit_quantum_error(error, instructions):
# Create an empty noise model
noise_model = NoiseModel()
# Add depolarizing error to all single qubit u1, u2, u3 gates
error = depolarizing_error(0.05, 1)
noise_model.add_all_qubit_quantum_error(error, ["u1", "u2", "u3"])
# Print noise model info
print(noise_model)
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']
Instructions with noise: ['u3', 'u2', 'u1']
All-qubits errors: ['u1', 'u2', 'u3']
2. Помилка для конкретних кубітів
Застосовує помилку до кожного входження інструкції, що діє на зазначений список кубітів. Зверни увагу: порядок кубітів має значення — наприклад, помилка, застосована до кубітів [0, 1] для двокубітного гей ту, відрізняється від тієї, що застосована до кубітів [1, 0].
Додається як noise_model.add_quantum_error(error, instructions, qubits):
# Create an empty noise model
noise_model = NoiseModel()
# Add depolarizing error to all single qubit u1, u2, u3 gates on qubit 0 only
error = depolarizing_error(0.05, 1)
noise_model.add_quantum_error(error, ["u1", "u2", "u3"], [0])
# Print noise model info
print(noise_model)
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']
Instructions with noise: ['u3', 'u2', 'u1']
Qubits with noise: [0]
Specific qubit errors: [('u1', (0,)), ('u2', (0,)), ('u3', (0,))]
Примітка про нелокальні квантові помилки для кубітів
NoiseModel не підтримує додавання нелокальних квантових помилок для кубітів. Їх слід обробляти поза NoiseModel. Це означає, що тобі потрібно написати власний transpiler pass (TransformationPass) і запустити його безпосередньо перед запуском симулятора, якщо ти хочеш вставити свої квантові помилки в схему за власними умовами.
Виконання симуляції з шумом на основі моделі шуму
Команда AerSimulator(noise_model=noise_model) повертає симулятор, налаштова ний відповідно до заданої моделі шуму. Окрім встановлення моделі шуму симулятора, вона також перевизначає базові гейти симулятора згідно з гейтами моделі шуму.
Приклади моделей шуму
Розглянемо кілька прикладів моделей шуму. Для демонстрації використовуємо просту тестову схему, що генерує n-кубітний стан ГГЦ (GHZ):
# System Specification
n_qubits = 4
circ = QuantumCircuit(n_qubits)
# Test Circuit
circ.h(0)
for qubit in range(n_qubits - 1):
circ.cx(qubit, qubit + 1)
circ.measure_all()
print(circ)
┌───┐ ░ ┌─┐
q_0: ┤ H ├──■─────────────░─┤M├─────────
└───┘┌─┴─┐ ░ └╥┘┌─┐
q_1: ─────┤ X ├──■────────░──╫─┤M├──────
└───┘┌─┴─┐ ░ ║ └╥┘┌─┐
q_2: ──────────┤ X ├──■───░──╫──╫─┤M├───
└───┘┌─┴─┐ ░ ║ ║ └╥┘┌─┐
q_3: ───────────────┤ X ├─░──╫──╫──╫─┤M├
└───┘ ░ ║ ║ ║ └╥┘
meas: 4/════════════════════════╩══╩══╩══╩═
0 1 2 3
Ідеальна симуляція
# Ideal simulator and execution
sim_ideal = AerSimulator()
result_ideal = sim_ideal.run(circ).result()
plot_histogram(result_ideal.get_counts(0))
Приклад шуму 1: проста модель шуму з помилками перекидання бітів
Розглянемо простий іграшковий приклад моделі шуму, поширений у дослідженнях з теорії квантової інформації:
- При застосуванні одно-кубітного гейту — перекинути стан кубіта з імовірністю
p_gate1. - При застосуванні дво-кубітного гейту — застосувати одно-кубітні помилки до кожного кубіта.
- При скиданні кубіта — скинути до 1 замість 0 з імовірністю
p_reset. - При вимірюванні кубіта — перекинути стан кубіта з імовірністю
p_meas.
# Example error probabilities
p_reset = 0.03
p_meas = 0.1
p_gate1 = 0.05
# QuantumError objects
error_reset = pauli_error([("X", p_reset), ("I", 1 - p_reset)])
error_meas = pauli_error([("X", p_meas), ("I", 1 - p_meas)])
error_gate1 = pauli_error([("X", p_gate1), ("I", 1 - p_gate1)])
error_gate2 = error_gate1.tensor(error_gate1)
# Add errors to noise model
noise_bit_flip = NoiseModel()
noise_bit_flip.add_all_qubit_quantum_error(error_reset, "reset")
noise_bit_flip.add_all_qubit_quantum_error(error_meas, "measure")
noise_bit_flip.add_all_qubit_quantum_error(error_gate1, ["u1", "u2", "u3"])
noise_bit_flip.add_all_qubit_quantum_error(error_gate2, ["cx"])
print(noise_bit_flip)
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']
Instructions with noise: ['u3', 'u2', 'measure', 'cx', 'reset', 'u1']
All-qubits errors: ['reset', 'measure', 'u1', 'u2', 'u3', 'cx']
Виконання зашумленої симуляції
# Create noisy simulator backend
sim_noise = AerSimulator(noise_model=noise_bit_flip)
# Transpile circuit for noisy basis gates
passmanager = generate_preset_pass_manager(
optimization_level=3, backend=sim_noise
)
circ_tnoise = passmanager.run(circ)
# Run and get counts
result_bit_flip = sim_noise.run(circ_tnoise).result()
counts_bit_flip = result_bit_flip.get_counts(0)
# Plot noisy output
plot_histogram(counts_bit_flip)
Приклад 2: термічна релаксація T1/T2
Тепер розглянемо більш реалістичну модель помилок на основі термічної релаксації з оточенням кубіта:
- Кожен кубіт характеризується сталою термічної релаксації та сталою часу дефазування .
- Зауваж, що обов'язково має виконуватись умова .
- Швидкості помилок для інструкцій визначаються часом виконання гейту та значеннями , кубітів.
# T1 and T2 values for qubits 0-3
T1s = np.random.normal(
50e3, 10e3, 4
) # Sampled from normal distribution mean 50 microsec
T2s = np.random.normal(
70e3, 10e3, 4
) # Sampled from normal distribution mean 50 microsec
# Truncate random T2s <= T1s
T2s = np.array([min(T2s[j], 2 * T1s[j]) for j in range(4)])
# Instruction times (in nanoseconds)
time_u1 = 0 # virtual gate
time_u2 = 50 # (single X90 pulse)
time_u3 = 100 # (two X90 pulses)
time_cx = 300
time_reset = 1000 # 1 microsecond
time_measure = 1000 # 1 microsecond
# QuantumError objects
errors_reset = [
thermal_relaxation_error(t1, t2, time_reset) for t1, t2 in zip(T1s, T2s)
]
errors_measure = [
thermal_relaxation_error(t1, t2, time_measure) for t1, t2 in zip(T1s, T2s)
]
errors_u1 = [
thermal_relaxation_error(t1, t2, time_u1) for t1, t2 in zip(T1s, T2s)
]
errors_u2 = [
thermal_relaxation_error(t1, t2, time_u2) for t1, t2 in zip(T1s, T2s)
]
errors_u3 = [
thermal_relaxation_error(t1, t2, time_u3) for t1, t2 in zip(T1s, T2s)
]
errors_cx = [
[
thermal_relaxation_error(t1a, t2a, time_cx).expand(
thermal_relaxation_error(t1b, t2b, time_cx)
)
for t1a, t2a in zip(T1s, T2s)
]
for t1b, t2b in zip(T1s, T2s)
]
# Add errors to noise model
noise_thermal = NoiseModel()
for j in range(4):
noise_thermal.add_quantum_error(errors_reset[j], "reset", [j])
noise_thermal.add_quantum_error(errors_measure[j], "measure", [j])
noise_thermal.add_quantum_error(errors_u1[j], "u1", [j])
noise_thermal.add_quantum_error(errors_u2[j], "u2", [j])
noise_thermal.add_quantum_error(errors_u3[j], "u3", [j])
for k in range(4):
noise_thermal.add_quantum_error(errors_cx[j][k], "cx", [j, k])
print(noise_thermal)
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u2', 'u3']
Instructions with noise: ['u3', 'u2', 'measure', 'cx', 'reset']
Qubits with noise: [0, 1, 2, 3]
Specific qubit errors: [('reset', (0,)), ('reset', (1,)), ('reset', (2,)), ('reset', (3,)), ('measure', (0,)), ('measure', (1,)), ('measure', (2,)), ('measure', (3,)), ('u2', (0,)), ('u2', (1,)), ('u2', (2,)), ('u2', (3,)), ('u3', (0,)), ('u3', (1,)), ('u3', (2,)), ('u3', (3,)), ('cx', (0, 0)), ('cx', (0, 1)), ('cx', (0, 2)), ('cx', (0, 3)), ('cx', (1, 0)), ('cx', (1, 1)), ('cx', (1, 2)), ('cx', (1, 3)), ('cx', (2, 0)), ('cx', (2, 1)), ('cx', (2, 2)), ('cx', (2, 3)), ('cx', (3, 0)), ('cx', (3, 1)), ('cx', (3, 2)), ('cx', (3, 3))]
Виконання зашумленої симуляції
# Run the noisy simulation
sim_thermal = AerSimulator(noise_model=noise_thermal)
# Transpile circuit for noisy basis gates
passmanager = generate_preset_pass_manager(
optimization_level=3, backend=sim_thermal
)
circ_tthermal = passmanager.run(circ)
# Run and get counts
result_thermal = sim_thermal.run(circ_tthermal).result()
counts_thermal = result_thermal.get_counts(0)
# Plot noisy output
plot_histogram(counts_thermal)
Наступні кроки
- Щоб симулювати зашумлені схеми, дивись Точна та зашумлена симуляція з примітивами Qiskit Aer.
- Переглянь довідник модуля шуму Qiskit Aer.