Перейти до основного вмісту

Точна та зашумлена симуляція за допомогою примітивів Qiskit Aer

Версії пакетів

Код на цій сторінці розроблено з використанням наведених нижче залежностей. Рекомендуємо використовувати ці або новіші версії.

qiskit[all]~=2.3.0
qiskit-aer~=0.17

У статті Точна симуляція за допомогою примітивів Qiskit показано, як використовувати референсні примітиви, що входять до складу Qiskit, для точної симуляції квантових схем. Сучасні квантові процесори схильні до помилок, або шуму, тому результати точної симуляції не обов'язково відповідають результатам, які очікуються при запуску схем на реальному обладнанні. Хоча референсні примітиви Qiskit не підтримують моделювання шуму, Qiskit Aer включає реалізації примітивів, які це підтримують. Qiskit Aer — це високопродуктивний симулятор квантових схем, який можна використовувати замість референсних примітивів для кращої продуктивності та розширених можливостей. Він є частиною екосистеми Qiskit. У цій статті ми демонструємо використання примітивів Qiskit Aer для точної та зашумленої симуляції.

Примітки
  • Потрібна версія qiskit-aer v0.14 або новіша.
  • Хоча примітиви Qiskit Aer реалізують інтерфейси примітивів, вони не надають ті самі параметри, що й примітиви Qiskit Runtime. Наприклад, рівень стійкості до помилок (resilience level) недоступний у примітивах Qiskit Aer.
  • Деталі про параметри методу симуляції, що підтримуються в Aer, дивись у документації AerSimulator.

Для дослідження точної та зашумленої симуляції створимо приклад схеми на восьми кубітах:

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-aer
from qiskit.circuit.library import efficient_su2

n_qubits = 8
circuit = efficient_su2(n_qubits)
circuit.draw("mpl")

Вивід попередньої комірки коду

Ця схема містить параметри, що представляють кути повороту для вентилів RyR_y та RzR_z. Під час симуляції цієї схеми потрібно задати конкретні значення для цих параметрів. У наступній комірці ми задаємо деякі значення для цих параметрів і використовуємо примітив Estimator з Qiskit Aer для обчислення точного очікуваного значення спостережуваної ZZZZZ \cdots Z.

from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_aer import AerSimulator
from qiskit_aer.primitives import EstimatorV2 as Estimator

observable = SparsePauliOp("Z" * n_qubits)
params = [0.1] * circuit.num_parameters

exact_estimator = Estimator()
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(3, AerSimulator())
isa_circuit = pass_manager.run(circuit)
pub = (isa_circuit, observable, params)
job = exact_estimator.run([pub])
result = job.result()
pub_result = result[0]
exact_value = float(pub_result.data.evs)
exact_value
0.8870140234256602

Тепер ініціалізуємо модель шуму, яка включає деполяризаційну помилку 2% на кожному вентилі CX. На практиці помилки, пов'язані з двокубітними вентилями (тут це вентилі CX), є основним джерелом помилок при запуску схеми. Огляд побудови моделей шуму в Qiskit Aer дивись у розділі Побудова моделей шуму.

У наступній комірці ми будуємо Estimator, що враховує цю модель шуму, та використовуємо його для обчислення очікуваного значення спостережуваної.

from qiskit_aer.noise import NoiseModel, depolarizing_error

noise_model = NoiseModel()
cx_depolarizing_prob = 0.02
noise_model.add_all_qubit_quantum_error(
depolarizing_error(cx_depolarizing_prob, 2), ["cx"]
)

noisy_estimator = Estimator(
options=dict(backend_options=dict(noise_model=noise_model))
)
job = noisy_estimator.run([pub])
result = job.result()
pub_result = result[0]
noisy_value = float(pub_result.data.evs)
noisy_value
0.7247404214143528

Як бачиш, очікуване значення в присутності шуму значно відрізняється від правильного значення. На практиці можна застосовувати різноманітні техніки пом'якшення помилок для протидії ефектам шуму, але їхній розгляд виходить за межі цієї статті.

Щоб отримати грубе уявлення про те, як шум впливає на кінцевий результат, розглянемо нашу модель шуму, яка додає деполяризаційну помилку 2% до кожного вентиля CX. Деполяризаційна помилка з ймовірністю pp визначається як квантовий канал EE, що діє на матрицю густини ρ\rho таким чином:

E(ρ)=(1p)ρ+pI2nE(\rho) = (1 - p) \rho + p\frac{I}{2^n}

де nn — кількість кубітів, у цьому випадку 2. Тобто з ймовірністю pp стан замінюється повністю змішаним станом, а з ймовірністю 1p1 - p стан зберігається. Після mm застосувань деполяризаційного каналу ймовірність збереження стану становитиме (1p)m(1 - p)^m. Отже, ми очікуємо, що ймовірність утримання правильного стану в кінці симуляції спадатиме експоненційно зі збільшенням кількості вентилів CX у нашій схемі.

Підрахуємо кількість вентилів CX у нашій схемі та обчислимо (1p)m(1 - p)^m. Викликаємо count_ops, щоб отримати словник, що відображає назви вентилів на їхню кількість, і отримаємо запис для вентиля CX.

cx_count = circuit.count_ops()["cx"]
(1 - cx_depolarizing_prob) ** cx_count
0.6542558123199923

Це значення, 65%, дає грубу оцінку ймовірності того, що наш кінцевий стан є правильним. Це консервативна оцінка, оскільки вона не враховує початковий стан симуляції.

Наступна комірка коду показує, як використовувати примітив Sampler з Qiskit Aer для вибірки зі зашумленої схеми. Перед запуском зі Sampler нам потрібно додати вимірювання до схеми.

from qiskit_aer.primitives import SamplerV2 as Sampler

measured_circuit = circuit.copy()
measured_circuit.measure_all()

noisy_sampler = Sampler(
options=dict(backend_options=dict(noise_model=noise_model))
)
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(3, AerSimulator())
isa_circuit = pass_manager.run(measured_circuit)
pub = (isa_circuit, params, 100)
job = noisy_sampler.run([pub])
result = job.result()
pub_result = result[0]
pub_result.data.meas.get_counts()
{'00100000': 1,
'00000000': 65,
'10101000': 1,
'10000000': 5,
'00001000': 1,
'00000110': 2,
'11110010': 1,
'00000011': 3,
'01010000': 3,
'11000000': 3,
'01111000': 1,
'01000000': 2,
'00000010': 1,
'01100000': 1,
'00011000': 1,
'00111100': 1,
'00010100': 1,
'00001111': 1,
'00110000': 1,
'01100101': 1,
'00000100': 1,
'10100000': 1,
'00000001': 1,
'11010000': 1}

Наступні кроки

Рекомендації