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

Квантова телепортація та надгустке кодування

примітка

Kifumi Numata (26 квітня 2024 р.)

Завантажити PDF оригінальної лекції. Зверни увагу, що деякі фрагменти коду можуть бути застарілими, оскільки це статичні зображення.

Приблизний час роботи QPU для цього експерименту — 10 секунд.

1. Вступ

Щоб розв'язувати будь-які квантові задачі на рівні корисного масштабу, нам потрібно переміщувати інформацію в квантовому комп'ютері з одного кубіту на інший. Для цього існують добре відомі протоколи, проте деякі з найфундаментальніших були розроблені в контексті передачі інформації між віддаленими сторонами. Упродовж цього уроку ми інколи будемо використовувати мову, притаманну цьому контексту, наприклад «віддалені друзі, що обмінюються інформацією». Але майте на увазі, що ці протоколи мають ширше значення у квантових обчисленнях. У цьому уроці розглядаються такі квантові комунікаційні протоколи:

  • Квантова телепортація Використання спільного заплутаного стану (що іноді називають e-бітом) для передачі невідомого квантового стану віддаленому другу, що потребує додаткового класичного зв'язку.
  • Квантове надгустке кодування Як передати два біти інформації, надіславши один кубіт віддаленому другу (знову ж таки використовуючи попередньо розподілені заплутані кубіти).

Для більш детального ознайомлення з цими темами рекомендуємо урок 4 з «Основ квантової інформації» на сторінці Заплутаність у дії.

У наведеному вище описі «невідомий квантовий стан» просто означає стан виду, описаного в попередньому уроці:

ψ=α0+β1|\psi\rangle =\alpha|0\rangle+\beta|1\rangle

де α\alpha та β\beta — комплексні числа такі, що α2+β2=1|\alpha|^2+|\beta|^2 = 1. Це дозволяє записати квантовий стан як

ψ=cosθ20+eiφsinθ21=(cosθ2eiφsinθ2)|\psi\rangle =\cos\frac{\theta}{2}|0\rangle+e^{i\varphi}\sin\frac{\theta}{2}|1\rangle= \left( \begin{matrix} \cos\frac{\theta}{2}\\ e^{i\varphi}\sin\frac{\theta}{2} \end{matrix} \right)

Оскільки ми хочемо мати можливість передавати інформацію в довільному квантовому стані, з цього і почнемо урок.

2. Матриці густини

Квантовий стан ψ|\psi \rangle також можна записати у вигляді його матриці густини. Ця форма корисна для позначення ймовірнісної суміші чистих квантових станів. У випадку одного кубіту можна записати

ψψρ=((cosθ2eiφsinθ2))((cosθ2eiφsinθ2))=12((1+cosθeiφsinθeiφsinθ1cosθ))|\psi \rangle \langle \psi| \equiv \rho = \left( \begin{pmatrix} \cos\frac{\theta}{2}\\ e^{i\varphi}\sin\frac{\theta}{2} \end{pmatrix} \right) \left( \begin{pmatrix} \cos\frac{\theta}{2} & e^{-i\varphi}\sin\frac{\theta}{2} \end{pmatrix} \right) =\frac{1}{2}\left(\begin{pmatrix} 1+\cos\theta & e^{-i\varphi}\sin\theta\\ e^{-i\varphi}\sin\theta & 1-\cos\theta \end{pmatrix}\right)

Зауваж, що матриця густини ρ\rho є лінійною комбінацією матриць Паулі, як показано нижче:

ρ=12(I+(sinθcosφ)X+(sinθsinφ)Y+(cosθ)Z)\rho = \frac{1}{2}\bigl( \textbf{I} + (\sin{\theta}\cos{\varphi})\textbf{X}+ (\sin{\theta}\sin{\varphi})\textbf{Y} + (\cos{\theta})\textbf{Z} \bigr)

Або, у загальному вигляді,

ρ=12(I+rxX+ryY+rzZ)\rho = \frac{1}{2}(\textbf{I} + r_{x}\textbf{X}+ r_{y}\textbf{Y} + r_{z}\textbf{Z})

де rx2+ry2+rz2=1r_{x}^2+r_{y}^2+r_{z}^2=1.

А вектор Блоха має вигляд r=(rx,ry,rz)\textbf{r} = (r_{x}, r_{y}, r_{z}).

Тепер створимо довільний квантовий стан за допомогою випадкових чисел.

# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-aer qiskit-ibm-runtime
import numpy as np

# create a random 1-qubit state from a random (theta, varphi) to define r vector
np.random.seed(1) # fixing seed for repeatibility

theta = np.random.uniform(0.0, 1.0) * np.pi # from 0 to pi
varphi = np.random.uniform(0.0, 2.0) * np.pi # from 0 to 2*pi

def get_r_vec(theta, varphi):
rx = np.sin(theta) * np.cos(varphi)
ry = np.sin(theta) * np.sin(varphi)
rz = np.cos(theta)
return (rx, ry, rz)

# get r vector
rx, ry, rz = get_r_vec(theta, varphi)

print("theta=" + str(theta), ",varphi=" + str(varphi))
print("(rx, ry, rz) = (" + str(rx) + ", " + str(ry) + ", " + str(rz) + ")")
theta=1.3101132663588946 ,varphi=4.525932273597346
(rx, ry, rz) = (-0.1791150283307452, -0.9494670044331133, 0.2577405946274022)

Цей вектор Блоха можна відобразити на сфері Блоха.

from qiskit.visualization import plot_bloch_vector

r = [rx, ry, rz]
plot_bloch_vector(r)

Результат попередньої комірки коду

3. Томографія квантових станів

Якщо вимірювати квантовий стан лише у обчислювальному базисі (0|0 \rangle та 1|1 \rangle), фазова інформація (інформація про комплексні числа) буде втрачена. Але якщо у нас є багато копій ψ|\psi \rangle, отриманих шляхом повторення процесу підготовки (клонувати стани не можна, але можна повторювати процес підготовки), ми можемо оцінити значення rx,ry,rzr_{x}, r_{y}, r_{z}, виконавши томографію квантового стану для матриці густини ρ\rho. З урахуванням форми:

ρ=12(I+rxX+ryY+rzZ)\rho = \frac{1}{2}(\textbf{I} + r_{x}\textbf{X}+ r_{y}\textbf{Y} + r_{z}\textbf{Z})

виконується таке:

Tr(Xρ)=rx,Tr(Yρ)=ry,Tr(Zρ)=rzTr(\textbf{X} \rho) = r_{x}, \quad Tr(\textbf{Y} \rho) = r_{y}, \quad Tr(\textbf{Z} \rho) = r_{z}

У випадку rzr_{z}:

Tr(Zρ)=0Zρ0+1Zρ1Tr(\textbf{Z} \rho) = \langle 0|\textbf{Z} \rho|0 \rangle + \langle 1|\textbf{Z} \rho|1 \rangle =0(0011)ρ0+1(0011)ρ1= \langle 0|(|0 \rangle\langle 0|-|1 \rangle\langle 1|) \rho|0 \rangle +\langle 1|(|0 \rangle\langle 0|-|1 \rangle\langle 1|) \rho|1 \rangle =0ρ01ρ1=\langle 0|\rho|0 \rangle- \langle 1| \rho|1 \rangle =0ψψ01ψψ1=\langle 0|\psi\rangle\langle \psi|0 \rangle - \langle 1| \psi\rangle\langle \psi|1 \rangle =α2β2=|\alpha|^2-|\beta|^2

Останнє перетворення рівняння стосується ψ=α0+β1|\psi \rangle =\alpha|0\rangle+\beta|1\rangle. Отже, rzr_{z} можна отримати як ймовірність 0|0 \rangle мінус ймовірність 1|1 \rangle.

Вправа 1: оцінка значення rzr_z

Щоб оцінити rzr_z, ми створюємо квантовий стан і вимірюємо його. Потім повторюємо підготовку та вимірювання багато разів. Нарешті, використовуємо статистику вимірювань для оцінки наведених вище ймовірностей і, таким чином, оцінки rzr_z.

Для створення випадкового квантового стану ми скористаємося загальним унітарним гейтом UU з параметрами θ,φ \theta, \varphi. (Докладніше про U-gate.)

from qiskit import QuantumCircuit

# create a 1-qubit quantum state psi from theta, varphi parameters
qc = QuantumCircuit(1, 1)
qc.u(theta, varphi, 0.0, 0)

# measure in computational basis
qc.measure(0, 0)

qc.draw(output="mpl")

Результат попередньої комірки коду

Використовуючи AerSimulator, виміряємо стан у обчислювальному базисі для оцінки rzr_z.

# see if the expected value of measuring in the computational basis
# approaches the limit of rz
from qiskit_aer import AerSimulator
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import Sampler
from qiskit.visualization import plot_histogram

# Define backend
backend = AerSimulator()
nshots = 1000 # or 10000
# nshots = 10000

# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)

# Run the job
sampler = Sampler(mode=backend)
job = sampler.run([isa_qc], shots=nshots)
result = job.result()

# Extract counts data
counts = result[0].data.c.get_counts()
print(counts)

# Plot the counts in a histogram

plot_histogram(counts)
{'1': 375, '0': 625}

Результат попередньої комірки к�оду

rz_approx = (counts["0"] - counts["1"]) / nshots

print("rz = ", rz, " and approx of rz = ", rz_approx)
rz =  0.2577405946274022  and approx of rz =  0.25

Використовуючи метод томографії квантових станів, ми оцінили значення rzr_z. У цьому випадку, оскільки ми самі вибирали параметри «випадкового» стану, нам відоме значення rzr_z і можна перевірити результат. Але за своєю природою задачі корисного масштабу не завжди так просто перевірити. Пізніше в цьому курсі ми детальніше обговоримо перевірку квантових результатів. Поки що просто зауважимо, що наша оцінка була достатньо точною.

Вправа 1: оцінка значення rxr_x

Нагадаємо, що квантові комп'ютери IBM® вимірюють уздовж осі zz (іноді це формулюють як «у базисі zz» або «у обчислювальному базисі»). Однак за допомогою обертань перед вимірюванням ми також можемо вимірювати проєкцію квантового стану на вісь x. Якщо точніше: якщо ми обернемо систему так, щоб те, що раніше вказувало вздовж xx, тепер вказувало вздовж zz, то зможемо залишити те саме вимірювальне обладнання вздовж zz, але дізнатися про стан, який щойно вказував уздовж xx. Саме так більшість квантових комп'ютерів (і всі квантові комп'ютери IBM) виконують вимірювання вздовж кількох осей.

З огляду на це, спробуй написати код для оцінки значення rxr_x за допомогою томографії квантових станів.

Розв'язання:

# create a 1-qubit quantum state psi from theta, varphi parameters
qc = QuantumCircuit(1, 1)
qc.u(theta, varphi, 0.0, 0)

qc.h(0)
qc.measure(0, 0)

qc.draw(output="mpl")

Результат попередньої комірки коду

# Define backend
backend = AerSimulator()
nshots = 10000

# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)

# Run the job
sampler = Sampler(mode=backend)
job = sampler.run([isa_qc], shots=nshots)
result = job.result()

# Extract counts data
counts = result[0].data.c.get_counts()
print(counts)

# Plot the counts in a histogram
plot_histogram(counts)
{'1': 5925, '0': 4075}

Результат попередньої комірки коду

rx_approx = (counts["0"] - counts["1"]) / nshots

print("rx = ", rx, " and approx of rx = ", rx_approx)
rx =  -0.1791150283307452  and approx of rx =  -0.185

Вправа 2: оцінка значення ryr_y

Використовуючи ту саму логіку, що й раніше, ми можемо обернути систему перед вимірюванням, щоб дізнатися про ryr_y. Спробуй самостійно написати код для оцінки значення ryr_y за допомогою томографії квантових станів. Можеш відштовхуватися від попереднього прикладу, але застосувати інші обертання. (Докладніше про різні гейти, зокрема sdg, дивись у довіднику API.)

Розв'язання:

# create a 1-qubit quantum state psi from theta, varphi parameters
qc = QuantumCircuit(1, 1)
qc.u(theta, varphi, 0.0, 0)

qc.sdg(0)
qc.h(0)
qc.measure(0, 0)

qc.draw(output="mpl")

Результат попередньої комірки коду

# Define backend
backend = AerSimulator()
nshots = 10000

# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)

# Run the job
sampler = Sampler(mode=backend)
job = sampler.run([isa_qc], shots=nshots)
result = job.result()

# Extract counts data
counts = result[0].data.c.get_counts()
print(counts)

# Plot the counts in a histogram
plot_histogram(counts)
{'1': 9759, '0': 241}

Результат попередньої комірки коду

ry_approx = (counts["0"] - counts["1"]) / nshots

print("ry = ", ry, " and approx of ry = ", ry_approx)
ry =  -0.9494670044331133  and approx of ry =  -0.9518

Тепер ми оцінили всі компоненти r\vec{r} і можемо записати повний вектор.

print("Estimated vector is (", rx_approx, ",", ry_approx, ",", rz_approx, ").")
print("Original random vector was (" + str(rx) + ", " + str(ry) + ", " + str(rz) + ").")
Estimated vector is ( -0.185 , -0.9518 , 0.25 ).
Original random vector was (-0.1791150283307452, -0.9494670044331133, 0.2577405946274022).

Ти досить точно оцінив оригінальний випадковий вектор за допомогою методу томографії квантових станів.

4. Квантова телепортація

Розглянемо ситуацію, коли персонаж Аліса хоче надіслати невідомий квантовий стан ψ|\psi \rangle своєму другу Бобу, який перебуває далеко. Припустимо, що вони можуть спілкуватися лише за допомогою класичного зв'язку (наприклад, електронної пошти або телефону). Аліса не може скопіювати квантовий стан (через теорему про заборону клонування). Якби вона повторювала той самий процес підготовки багато разів, вона могла б зібрати статистику, як ми щойно робили. Але що, якщо існує лише один невідомий стан? Цей стан міг виникнути в результаті фізичного процесу, який ти хочеш дослідити. Або він може бути частиною більшого квантового обчислення. У такому разі як Аліса могла б передати стан Бобу? Вона може це зробити, якщо вони з Бобом розподілять між собою цінний квантовий ресурс — спільний заплутаний стан, наприклад стан Белла, введений у попередньому уроці: 00+112.\frac {|00\rangle + |11\rangle}{\sqrt 2}. Іноді його також називають «парою ЕПР» або «e-бітом» (фундаментальною одиницею заплутаності). Якщо Аліса розподілить такий заплутаний стан із Бобом, вона може телепортувати невідомий квантовий стан до Боба, виконавши серію квантових операцій і надіславши йому два біти класичної інформації.

4.1 Протокол квантової телепортації

Припущення: у Аліси є невідомий квантовий стан ψ|\psi \rangle, який вона хоче надіслати Бобу. Аліса та Боб розподіляють між собою двокубітний заплутаний стан (e-біт), причому кожен із них фізично тримає один із кубітів.

Ось загальний опис процедури без пояснень. Деталі реалізації розглянемо нижче.

  1. Аліса заплутує ψ|\psi \rangle зі своєю частиною e-біта за допомогою гейта CNOT.
  2. Аліса застосовує гейт Адамара до ψ|\psi \rangle і вимірює обидва своїх кубіти у обчислювальному базисі.
  3. Аліса надсилає Бобу результати своїх вимірювань (або «00», або «01», або «10», або «11»).
  4. Боб виконує операцію корекції на своїй частині пари e-бітів на основі двох бітів інформації від Аліси.
    • Якщо «00», Боб нічого не робить
    • Якщо «01», Боб застосовує гейт X
    • Якщо «10», Боб застосовує гейт Z
    • Якщо «11», Боб застосовує iY = ZX гейт
  5. Частина e-біта Боба стає ψ|\psi \rangle.

Це також детальніше розглянуто в Основах квантової інформації. Але ситуація стане зрозумілішою, коли ми реалізуємо це в Qiskit.

4.2 Квантова схема для симуляції квантової телепортації

Як завжди, ми застосовуватимемо фреймворк патернів Qiskit. У цьому підрозділі зосередимося лише на відображенні.

Крок 1: відображення задачі на квантові схеми та оператори

Щоб описати наведений вище сценарій, нам потрібна схема з трьома кубітами: два для заплутаної пари, розподіленої між Алісою та Бобом, і один для невідомого квантового стану ψ|\psi\rangle.

from qiskit import QuantumCircuit
import numpy as np
# create 3-qubits circuit
qc = QuantumCircuit(3, 3)

qc.draw(output="mpl")

Результат попередньої комірки коду

На початку у Аліси є невідомий квантовий стан ψ|\psi \rangle. Ми створимо його за допомогою гейта UU.

# Create the unknown quantum state using the u-gate. Alice has this.
qc.u(theta, varphi, 0.0, 0)
qc.barrier() # for visual separation

qc.draw(output="mpl")

Результат попередньої комірки коду

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

# show the quantum state on bloch sphere
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_bloch_multivector

out_vector = Statevector(qc)

plot_bloch_multivector(out_vector)

Результат попередньої комірки коду

Ще до початку протоколу ми припускаємо, що Аліса та Боб уже мають спільну заплутану пару. Якщо вони справді перебувають у різних місцях, вони могли встановити цей спільний стан ще до того, як невідомий стан ψ|\psi\rangle взагалі було створено. Оскільки ці дії відбуваються з різними кубітами, порядок тут не має значення, а такий порядок зручний для візуалізації.

# Alice and Bob are together in the same place and set up an entangled pair.
qc.h(1)
qc.cx(1, 2)
qc.barrier() # for visual separation.
# We can consider that Alice and Bob might move their qubits to different physical locations, now.

qc.draw(output="mpl")

Результат попередньої комірки коду

Далі Аліса заплутує ψ|\psi \rangle зі своєю частиною спільного e-біта за допомогою гейта CXCX та гейта HH, а потім вимірює їх у обчислювальному базисі.

# Alice entangles the unknown state with her part of the e-bit, using the CNOT gate and H gate.
qc.cx(0, 1)
qc.h(0)
qc.barrier()

# Alice measures the two qubits.
qc.measure(0, 0)
qc.measure(1, 1)

qc.draw(output="mpl")

Результат попередньої комірки коду

Аліса надсилає Бобу результати своїх вимірювань (або «00», або «01», або «10», або «11»), і Боб виконує операцію корекції на своїй частині спільного e-біта на основі двох бітів інформації від Аліси. Після цього частина Боба стає ψ|\psi \rangle.

# Alice sent the results to Bob. Bob applies correction
with qc.if_test((0, 1)):
qc.z(2)
with qc.if_test((1, 1)):
qc.x(2)
qc.barrier()

qc.draw(output="mpl")

Результат попередньої комірки коду

Ти завершив побудову схеми квантової телепортації! Подивімося на вихідний стан цієї схеми за допомогою симулятора statevector.

from qiskit_aer import StatevectorSimulator

backend = StatevectorSimulator()
out_vector = backend.run(qc, shots=1).result().get_statevector() # set shots = 1

plot_bloch_multivector(out_vector)

Результат попередньої комірки коду

Ти можеш бачити, що квантовий стан, створений гейтом UU для кубіта 0 (кубіт, що спочатку містив секретний стан), було перенесено на кубіт 2 (кубіт Боба).

Запусти наведену вище комірку кілька разів, щоб переконатися. Ти, мабуть, помітиш, що кубіти 0 та 1 змінюють стани, але кубіт 2 завжди перебуває у стані ψ|\psi\rangle.

4.3 Виконай та підтвердь результат, застосувавши обернений U

Вище ми візуально перевірили, що телепортований стан виглядає правильно. Ще один спосіб перевірити, чи квантовий стан було телепортовано коректно, — застосувати обернений вентиль UU до кубіта Боба, щоб виміряти '0'. Тобто, оскільки U1UU^{-1}U є тотожним перетворенням, якщо кубіт Боба перебуває у стані, створеному з U0,U|0\rangle, то після застосування оберненого вентиля отримаємо U1U0=0.U^{-1}U|0\rangle=|0\rangle.

# Apply the inverse of u-gate to measure |0>
qc.u(theta, varphi, 0.0, 2).inverse() # inverse of u(theta,varphi,0.0)
qc.measure(2, 2) # add measurement gate

qc.draw(output="mpl")

Output of the previous code cell

Спочатку ми виконаємо Circuit за допомогою AerSimulator, а потім перейдемо до справжнього квантового комп'ютера.

from qiskit_aer import AerSimulator
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import Sampler
from qiskit.visualization import plot_histogram

# Define backend
backend = AerSimulator()

# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)

# Run the job
sampler = Sampler(mode=backend)
job = sampler.run([isa_qc], shots=nshots)
result = job.result()

# Extract counts data
counts = result[0].data.c.get_counts()
print(counts)

# Plot the counts in a histogram
plot_histogram(counts)
{'011': 2510, '010': 2417, '000': 2635, '001': 2438}

Output of the previous code cell

Нагадаємо, що в little endian нотації кубіт 2 — це крайній лівий (або нижній, у підписах стовпців) кубіт. Зверни увагу: крайній лівий і нижній кубіт у підписах стовпців дорівнює 0 для всіх можливих результатів. Це свідчить про те, що ймовірність виміряти q2q_2 у стані 0|0\rangle становить 100%. Це очікуваний результат, який підтверджує, що протокол телепортації спрацював правильно.

4.4 Телепортація на справжньому квантовому комп'ютері

Далі ми виконаємо телепортацію на справжньому квантовому комп'ютері. За допомогою функції динамічних схем ми можемо здійснювати операції всередині Circuit, використовуючи результати вимірювань, і реалізовувати умовні операції в протоколі телепортації в режимі реального часу. Для розв'язання задач на реальних квантових комп'ютерах ми дотримуватимемось чотирьох кроків патернів Qiskit.

  1. Відобразити задачу на квантові схеми та оператори
  2. Оптимізувати під цільове апаратне забезпечення
  3. Виконати на цільовому апаратному забезпеченні
  4. Постобробити результати

Вправа 3: Побудуй Circuit телепортації

Спробуй побудувати весь Circuit телепортації з нуля, щоб перевірити своє розуміння. Прокрути вгору, якщо потрібне нагадування.

Розв'язання:

# Step 1: Map problem to quantum circuits and operators
# Create the circuit with 3-qubits and 1-bit
qc = QuantumCircuit(3, 3)

# Alice creates an unknown quantum state using the u-gate.
qc.u(theta, varphi, 0.0, 0)
qc.barrier() # for visual separation

# Eve creates EPR pair and sends q1 to Alice and q2 to Bob
##your code goes here##
qc.h(1)
qc.cx(1, 2)
qc.barrier()

# Alice entangles the unknown state with her EPR part, using the CNOT gate and H gate.
##your code goes here##
qc.cx(0, 1)
qc.h(0)
qc.barrier()

# Alice measures the two qubits.
##your code goes here##
qc.measure(0, 0)
qc.measure(1, 1)

# Alice sent the results to Bob. Now, Bob applies correction
##your code goes here##
with qc.if_test((0, 1)):
qc.z(2)
with qc.if_test((1, 1)):
qc.x(2)
qc.barrier()

# Apply the inverse of u-gate to measure |0>
qc.u(theta, varphi, 0.0, 2).inverse()
qc.measure(2, 2)

qc.draw(output="mpl")

Output of the previous code cell

Нагадаємо, що застосування оберненого вентиля UU потрібне лише для перевірки очікуваної поведінки. Це не є частиною передачі стану Бобу, і ми не використовували б обернений UU, якщо єдиною метою було б передати квантову інформацію.

Крок 2: Оптимізуй під цільове апаратне забезпечення

Щоб запустити на апаратному забезпеченні, імпортуй QiskitRuntimeService та завантаж збережені облікові дані. Вибери Backend з найменшою кількістю завдань у черзі.

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
service.backends()
[<IBMBackend('ibm_brisbane')>,
<IBMBackend('ibm_torino')>]
# You can also identify the least busy device
backend = service.least_busy(operational=True)
print("The least busy device is ", backend)
The least busy device is  <IBMBackend('ibm_brisbane')>
# You can specify the device
# backend = service.backend('ibm_brisbane')

Подивимося на карту зв'язків вибраного пристрою.

from qiskit.visualization import plot_gate_map

plot_gate_map(backend)

Output of the previous code cell

Різні пристрої можуть мати різні карти зв'язків, і кожен пристрій має кубіти та з'єднувачі з різною продуктивністю. Крім того, різні квантові комп'ютери можуть мати різні нативні вентилі (вентилі, які апаратне забезпечення може виконувати безпосередньо). Транспіляція Circuit перезаписує абстрактну квантову схему з використанням вентилів, які може виконати цільовий квантовий комп'ютер, і вибирає оптимальне відображення на фізичні кубіти (серед іншого). Транспіляція — це насичена й складна тема. Більше про транспіляцію читай у довідці API.

# Step 2: Optimize for target hardware
# Transpile the circuit into basis gates executable on the hardware
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

pm = generate_preset_pass_manager(backend=backend, optimization_level=2)
qc_compiled = pm.run(qc)

qc_compiled.draw("mpl", idle_wires=False, fold=-1)

Output of the previous code cell

Крок 3: Виконай Circuit

За допомогою примітиву Sampler Runtime ми виконаємо цільовий Circuit.

# Step 3: Execute the target circuit
sampler = Sampler(backend)
job = sampler.run([qc_compiled])
job_id = job.job_id()
print("job id:", job_id)
job id: d13nkhpn2txg008jt0d0
# Check the job status
job.status()
'DONE'

Також можна перевірити статус завдання у своєму дашборді IBM Quantum®.

# If the Notebook session got disconnected you can also check your job status by running the following code
from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
job_real = service.job(job.job_id()) # Input your job-id between the quotations
job_real.status()
'DONE'

Якщо відображається 'DONE', можна отримати результат, виконавши наступну комірку.

# Execute after 'DONE' is displayed
result_real = job_real.result()
print(result_real[0].data.c.get_counts())
{'001': 992, '110': 430, '011': 579, '010': 605, '111': 402, '000': 925, '100': 57, '101': 106}

Крок 4: Постобробка результатів

# Step 4: Post-process the results
from qiskit.visualization import plot_histogram

plot_histogram(result_real[0].data.c.get_counts())

Output of the previous code cell

Результати вище можна інтерпретувати безпосередньо. Або, використовуючи marginal_count, можна виокремити результати Боба на кубіті 2.

# trace out Bob's results on qubit 2
from qiskit.result import marginal_counts

bobs_qubit = 2
real_counts = result_real[0].data.c.get_counts()
bobs_counts = marginal_counts(real_counts, [bobs_qubit])
plot_histogram(bobs_counts)

Output of the previous code cell

Як бачимо, є кілька результатів, у яких ми виміряли 1|1 \rangle. Це пов'язано з шумом і похибками. Зокрема, динамічні схеми, як правило, мають вищий рівень похибок через тривале вимірювання всередині Circuit.

4.5 Ключові висновки щодо квантової телепортації

Ми можемо передати квантовий стан далекому другу, поділившись парою заплутаних кубітів (e-bit).

  1. Чи може квантова телепортація передавати квантовий стан швидше за світло? Ні, бо Аліса має повідомити Бобу результати вимірювань класичним способом.

  2. Чи порушує квантова телепортація «теорему про заборону клонування», яка забороняє копіювання квантового стану? Ні, бо вихідний квантовий стан, переданий Алісі на одному з її кубітів, було знищено під час вимірювання. Він колапсував до 0|0\rangle або 1|1\rangle.

5. Надщільне кодування

Майже те саме налаштування можна використати з іншою метою. Припустімо, Аліса хоче передати Бобу два біти класичної інформації, але не має засобів класичного зв'язку з Бобом. Проте вони разом із Бобом мають заплутану пару, і Аліса може надіслати свій кубіт до місця знаходження Боба. Зверни увагу на відмінність від протоколу квантової телепортації. При телепортації класичний зв'язок був доступний учасникам, а метою була передача квантового стану. Тут класичний зв'язок недоступний, і вони використовують передачу кубіта для обміну двома бітами класичної інформації.

5.1 Протокол надщільного кодування

Припущення: Аліса має два біти інформації, скажімо, a1a2{00,01,10,11}a_1a_2 \in \{00, 01, 10, 11\}. Аліса та Боб мають спільну заплутану пару (e-bit), але не можуть спілкуватися класично.

  1. Аліса виконує одну з наступних операцій над своєю частиною e-bit.
    • Якщо a1a2=00a_1a_2 = 00, вона нічого не робить
    • Якщо a1a2=01a_1a_2 = 01, вона застосовує Gate Z
    • Якщо a1a2=10a_1a_2 = 10, вона застосовує Gate X
    • Якщо a1a2=11a_1a_2 = 11, вона застосовує Gate Z та Gate X.
  2. Аліса надсилає свою частину e-bit до місця знаходження Боба.
  3. Боб застосовує Gate CNOT, де кубіт від Аліси — контрольний, а його кубіт — цільовий, потім застосовує Gate H до кубіта від Аліси та вимірює обидва кубіти. Можливі початкові стани та результати операцій Боба:
00+112CX01H000\frac {|00\rangle + |11\rangle}{\sqrt 2} \rightarrow CX_{01}\otimes H_0 \rightarrow |00\rangle 00112CX01H001\frac {|00\rangle - |11\rangle}{\sqrt 2} \rightarrow CX_{01}\otimes H_0 \rightarrow |01\rangle 10+012CX01H010\frac {|10\rangle + |01\rangle}{\sqrt 2} \rightarrow CX_{01}\otimes H_0 \rightarrow |10\rangle 10012CX01H011\frac {|10\rangle - |01\rangle}{\sqrt 2} \rightarrow CX_{01}\otimes H_0 \rightarrow -|11\rangle

Зверни увагу, що від'ємний знак у 11-|11\rangle — це глобальна фаза, тому вона не вимірювана.

5.2 Квантова схема, що симулює надщільне кодування

На основі протоколу надщільного кодування можна побудувати схему надщільного кодування, як показано нижче. Спробуй змінити повідомлення msg, яке Аліса хоче передати Бобу.

from qiskit import QuantumCircuit

Кроки патерну Qiskit зазначені в коментарях до коду.

# Step 1: Map problem to quantum circuits and operators
# Create 2-qubits circuit
qc = QuantumCircuit(2, 2)

# Eve creates EPR pair and send q0 to Alice and q1 to Bob
qc.h(0)
qc.cx(0, 1)
qc.barrier()

# set message which Alice wants to transform to Bob
msg = "11" # You can change the message

if msg == "00":
pass
elif msg == "10":
qc.x(0)
elif msg == "01":
qc.z(0)
elif msg == "11":
qc.z(0)
qc.x(0)

qc.barrier()
# Bob receives EPR qubit from Alice and performs unitary operations
qc.cx(0, 1)
qc.h(0)
qc.barrier()

# Bob measures q0 and q1
qc.measure(0, 0)
qc.measure(1, 1)

qc.draw(output="mpl")

Output of the previous code cell

# We will execute on a simulator first
from qiskit_aer import AerSimulator
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import Sampler

# Define backend
backend = AerSimulator()
shots = 1000

# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)

# Run the job
sampler = Sampler(mode=backend)
job_sim = sampler.run([isa_qc], shots=shots)
result_sim = job_sim.result()

# Extract counts data
counts = result_sim[0].data.c.get_counts()
print(counts)
{'11': 1000}
# Visualize the results
from qiskit.visualization import plot_histogram

plot_histogram(counts)

Output of the previous code cell

Бачимо, що Боб отримав повідомлення, яке Аліса хотіла йому надіслати.

Тепер спробуємо це на справжньому квантовому комп'ютері.

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
backend = service.least_busy(operational=True)
print("The least busy device is ", backend)
The least busy device is  <IBMBackend('ibm_brisbane')>
# Step 1 was already completed before the simulator job above.
# Step 2: Optimize for target hardware
# Transpile the circuit into basis gates executable on the hardware
pm = generate_preset_pass_manager(backend=backend, optimization_level=2)
qc_compiled = pm.run(qc)

qc_compiled.draw("mpl", idle_wires=False)

Output of the previous code cell

# Step 3:Execute the target circuit
sampler = Sampler(backend)
job = sampler.run([qc_compiled])
job_id = job.job_id()
print("job id:", job_id)
job id: d13nnyq3grvg008j0zag
# Check the job status
job.status()
'DONE'
# If the Notebook session got disconnected you can also check your job status by running the following code
# from qiskit_ibm_runtime import QiskitRuntimeService
# service = QiskitRuntimeService()
job = service.job(job_id) # Input your job-id between the quotations
job.status()
'DONE'
# Execute after job has successfully run
real_result = job.result()
print(real_result[0].data.c.get_counts())
{'11': 3942, '01': 107, '10': 41, '00': 6}
# Step 4: post-process the results
from qiskit.visualization import plot_histogram

plot_histogram(real_result[0].data.c.get_counts())

Output of the previous code cell

Результат відповідає очікуваному. Зверни увагу, що надщільне кодування на справжньому квантовому комп'ютері показало менше похибок, ніж квантова телепортація на справжньому квантовому комп'ютері. Одна з причин може полягати в тому, що квантова телепортація використовує динамічні схеми, а надщільне кодування — ні. Більше про похибки в квантових схемах ми дізнаємося на наступних уроках.

6. Підсумок

У цьому занятті ми реалізували два квантових протоколи. Хоча сценарії обох, що передбачають віддалених учасників, дещо відірвані від квантових обчислень на одному QPU, вони мають застосування в квантових обчисленнях і допомагають нам краще зрозуміти передачу квантової інформації.

  • Квантова телепортація: попри те, що ми не можемо копіювати квантові стани, ми можемо телепортувати невідомі квантові стани завдяки спільній заплутаності.
  • Квантове надщільне кодування: спільна заплутана пара та передача одного кубіта дозволяють передати два біти класичної інформації.
# See the version of Qiskit
import qiskit

qiskit.__version__
'2.0.2'