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

Квантові біти, вентилі та схеми

примітка

Kifumi Numata (19 Apr 2024)

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

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

1. Вступ

Біти, вентилі та схеми — це основні будівельні блоки квантових обчислень. Ти навчишся квантовим обчисленням із використанням моделі схем на основі квантових бітів і вентилів, а також повториш поняття суперпозиції, вимірювання й заплутаності.

У цьому уроці ти вивчиш:

  • Однокубітові вентилі
  • Сферу Блоха
  • Суперпозицію
  • Вимірювання
  • Двокубітові вентилі та стан заплутаності

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

2. Обчислення у вигляді діаграми

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

Рисунок унизу ліворуч — приклад класичної схеми, а рисунок унизу праворуч — приклад квантової схеми. В обох випадках вхідні дані розміщені ліворуч, а вихідні — праворуч; операції зображені символами. Ці символи операцій називаються «вентилями» — здебільшого з історичних причин.

"Класична логічна та квантова схема"

3. Однокубітовий квантовий вентиль

3.1 Квантовий стан і сфера Блоха

Стан кубіта представляється як суперпозиція 0|0\rangle та 1|1\rangle. Довільний квантовий стан записується так:

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

де α\alpha і β\beta — комплексні числа, для яких α2+β2=1|\alpha|^2+|\beta|^2=1.

0|0\rangle та 1|1\rangle — вектори в двовимірному комплексному векторному просторі:

0=(10),1=(01)|0\rangle = \begin{pmatrix} 1 \\0 \end{pmatrix}, |1\rangle = \begin{pmatrix} 0\\1 \end{pmatrix}

Тому довільний квантовий стан також можна записати як

ψ=α(10)+β(01)=(αβ)|\psi\rangle = \alpha\begin{pmatrix} 1 \\ 0 \end{pmatrix} + \beta\begin{pmatrix}0\\ 1 \end{pmatrix} = \begin{pmatrix} \alpha \\ \beta \end{pmatrix}

З цього випливає, що стан квантового біта — це одиничний вектор у двовимірному комплексному просторі зі скалярним добутком, де ортонормований базис утворюють 0|0\rangle та 1|1\rangle. Він нормований до 1.

ψψ=(αβ)(αβ)=1\langle\psi|\psi\rangle = \begin{pmatrix} \alpha^* & \beta^* \end{pmatrix} \begin{pmatrix} \alpha \\ \beta \end{pmatrix} = 1

|\psi\rangle =\begin\{pmatrix\} \alpha \\ \beta \end\{pmatrix\} також називають вектором стану (statevector).

Однокубітовий квантовий стан можна також записати як

ψ=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{pmatrix} \cos\frac{\theta}{2}\\ e^{i\varphi}\sin\frac{\theta}{2} \end{pmatrix}\right)

де θ\theta і φ\varphi — кути сфери Блоха на наступному рисунку.

Сфера Блоха

У наступних кількох комірках коду ми побудуємо базові обчислення з окремих складових у Qiskit. Ми створимо порожню схему, а потім додамо квантові операції, обговорюючи вентилі й візуалізуючи їх вплив у міру роботи. Запустити комірку можна натисканням «Shift» + «Enter». Спочатку імпортуй бібліотеки.

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-aer qiskit-ibm-runtime
# Import the qiskit library
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_bloch_multivector
from qiskit_ibm_runtime import Sampler
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.visualization import plot_histogram

Підготовка квантової схеми

Ми створимо та намалюємо однокубітову схему.

# Create the single-qubit quantum circuit
qc = QuantumCircuit(1)

# Draw the circuit
qc.draw("mpl")

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

Вентиль X

Вентиль X — це поворот на π\pi навколо осі xx сфери Блоха. Застосування вентиля X до 0|0\rangle дає 1|1\rangle, а застосування до 1|1\rangle дає 0|0\rangle, тому він подібний до класичного вентиля NOT і також відомий як бітовий зворот (bit flip). Матрична форма вентиля X подана нижче.

X=(0110)X = \begin{pmatrix} 0 & 1 \\ 1 & 0 \\ \end{pmatrix}
qc = QuantumCircuit(1)  # Prepare the single-qubit quantum circuit

# Apply a X gate to qubit 0
qc.x(0)

# Draw the circuit
qc.draw("mpl")

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

В IBM Quantum® початковий стан встановлено в 0|0\rangle, тому наведена вище квантова схема в матричній формі виглядає так:

X0=(0110)(10)=(01)=1X|0\rangle= \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix} \begin{pmatrix} 1 \\ 0 \end{pmatrix} =\begin{pmatrix} 0 \\ 1 \end{pmatrix} = |1\rangle

Тепер запустимо цю схему за допомогою симулятора вектора стану.

# See the statevector
out_vector = Statevector(qc)
print(out_vector)

# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([0.+0.j, 1.+0.j],
dims=(2,))

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

Вертикальний вектор відображається як рядковий вектор, де комплексні числа мають уявну частину, позначену jj.

Вентиль H

Вентиль Адамара (H) — це поворот на π\pi навколо осі, що проходить рівно між осями xx і zz на сфері Блоха. Застосування вентиля H до 0|0\rangle створює стан суперпозиції 0+12\frac{|0\rangle + |1\rangle}{\sqrt{2}}. Матрична форма вентиля H подана нижче.

H=12(1111)H = \frac{1}{\sqrt{2}}\begin{pmatrix} 1 & 1 \\ 1 & -1 \\ \end{pmatrix}
qc = QuantumCircuit(1)  # Create the single-qubit quantum circuit

# Apply an Hadamard gate to qubit 0
qc.h(0)

# Draw the circuit
qc.draw(output="mpl")

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

# See the statevector
out_vector = Statevector(qc)
print(out_vector)

# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([0.70710678+0.j, 0.70710678+0.j],
dims=(2,))

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

Це відповідає:

H0=12(1111)(10)=12(11)=(0.7070.707)=12(0+1)H|0\rangle= \frac{1}{\sqrt{2}} \begin{pmatrix} 1 & 1 \\ 1 & -1 \end{pmatrix} \begin{pmatrix} 1 \\0 \end{pmatrix} =\frac{1}{\sqrt{2}}\begin{pmatrix} 1 \\ 1 \end{pmatrix} =\begin{pmatrix} 0.707 \\ 0.707 \end{pmatrix} =\frac{1}{\sqrt{2}}(|0\rangle+|1\rangle)

Цей стан суперпозиції настільки поширений і важливий, що для нього введено власний символ:

+12(0+1).|+\rangle \equiv \frac{1}{\sqrt{2}}(|0\rangle+|1\rangle).

Застосувавши вентиль HH до 0|0\rangle, ми створили суперпозицію 0|0\rangle та 1|1\rangle, де вимірювання в обчислювальному базисі (вздовж осі z на сфері Блоха) дасть кожен зі станів із рівною ймовірністю.

Стан |-\rangle

Можливо, ти вже здогадався, що існує відповідний стан |-\rangle:

012.|-\rangle \equiv \frac{|0\rangle -|1\rangle}{\sqrt{2}}.

Щоб отримати цей стан, спочатку застосуй вентиль X, щоб підготувати 1|1\rangle, а потім застосуй вентиль H.

qc = QuantumCircuit(1)  # Create the single-qubit quantum circuit

# Apply a X gate to qubit 0
qc.x(0)

# Apply an Hadamard gate to qubit 0
qc.h(0)

# draw the circuit
qc.draw(output="mpl")

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

# See the statevector
out_vector = Statevector(qc)
print(out_vector)

# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([ 0.70710678+0.j, -0.70710678+0.j],
dims=(2,))

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

Це відповідає:

H1=12(11 11)(0 1)=12(1 1)=(0.707 0.707)=12(01)=H|1\rangle= \frac{1}{\sqrt{2}} \begin{pmatrix} 1 & 1 \\\ 1 & -1 \end{pmatrix} \begin{pmatrix} 0 \\\ 1 \end{pmatrix} =\frac{1}{\sqrt{2}}\begin{pmatrix} 1 \\\ -1 \end{pmatrix} =\begin{pmatrix} 0.707 \\\ -0.707 \end{pmatrix} =\frac{1}{\sqrt{2}}(|0\rangle-|1\rangle) = |-\rangle

Застосування вентиля HH до 1|1\rangle дає рівну суперпозицію 0|0\rangle та 1|1\rangle, але знак перед 1|1\rangle від'ємний.

3.2 Однокубітовий квантовий стан та унітарна еволюція

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

ψ=Uψ|\psi^{'}\rangle = U|\psi\rangle

Унітарна матриця задовольняє умову

UU=UU=I.U^{\dagger}U =U U^{\dagger} = I.

З точки зору роботи квантового комп'ютера, кажуть, що застосування квантового вентиля до кубіта еволюціонує квантовий стан. Типові однокубітові вентилі наведено нижче.

Вентилі Паулі:

X=(0110)=01+10X = \begin{pmatrix} 0 & 1 \\ 1 & 0 \\ \end{pmatrix} = |0\rangle \langle 1|+|1\rangle \langle 0| Y=(0ii0)=i01+i10Y = \begin{pmatrix} 0 & -i \\ i & 0 \\ \end{pmatrix} = -i|0\rangle \langle 1|+i|1\rangle \langle 0| Z=(1001)=0011Z = \begin{pmatrix} 1 & 0 \\ 0 & -1 \\ \end{pmatrix} = |0\rangle \langle 0|-|1\rangle \langle 1|

де зовнішній добуток обчислюється так:

00=[10][10]=[1000],10=[01][10]=[0010],|0\rangle \langle 0|= \begin{bmatrix} 1 \\ 0 \end{bmatrix} \begin{bmatrix} 1 & 0 \end{bmatrix} =\begin{bmatrix} 1 & 0 \\ 0 & 0 \\ \end{bmatrix}, \quad |1\rangle \langle 0|= \begin{bmatrix} 0 \\ 1 \end{bmatrix} \begin{bmatrix} 1 & 0 \end{bmatrix} =\begin{bmatrix} 0 & 0 \\ 1 & 0 \\ \end{bmatrix}, \quad 01=[10][01]=[0100],11=[01][01]=[0001],|0\rangle \langle 1|= \begin{bmatrix} 1 \\ 0 \end{bmatrix} \begin{bmatrix} 0 & 1 \end{bmatrix} =\begin{bmatrix} 0 & 1 \\ 0 & 0 \\ \end{bmatrix}, \quad |1\rangle \langle 1|= \begin{bmatrix} 0 \\ 1 \end{bmatrix} \begin{bmatrix} 0 & 1 \end{bmatrix} =\begin{bmatrix} 0 & 0 \\ 0 & 1 \\ \end{bmatrix}, \quad

Інші типові однокубітові вентилі:

H=12[1111],S=[100i],T=[100exp(iπ/4)]H= \frac{1}{\sqrt{2}}\begin{bmatrix} 1 & 1 \\ 1 & -1 \\ \end{bmatrix},\quad S = \begin{bmatrix} 1 & 0 \\ 0 & i \\ \end{bmatrix}, \quad T = \begin{bmatrix} 1 & 0 \\ 0 & exp(i\pi/4) \\ \end{bmatrix} Rx(θ)=eiθX/2=cosθ2Iisinθ2X=[cosθ2isinθ2isinθ2cosθ2]R_x(\theta) = e^{-i\theta X/2} = cos\frac{\theta}{2}I - i sin \frac{\theta}{2}X = \begin{bmatrix} cos\frac{\theta}{2} & -i sin \frac{\theta}{2} \\ -i sin \frac{\theta}{2} & cos\frac{\theta}{2} \\ \end{bmatrix} Ry(θ)=eiθY/2=cosθ2Iisinθ2Y=[cosθ2sinθ2sinθ2cosθ2]R_y(\theta) = e^{-i\theta Y/2} = cos\frac{\theta}{2}I - i sin \frac{\theta}{2}Y = \begin{bmatrix} cos\frac{\theta}{2} & - sin \frac{\theta}{2} \\ sin \frac{\theta}{2} & cos\frac{\theta}{2} \\ \end{bmatrix} Rz(θ)=eiθZ/2=cosθ2Iisinθ2Z=[eiθ/200eiθ/2]R_z(\theta) = e^{-i\theta Z/2} = cos\frac{\theta}{2}I - i sin \frac{\theta}{2}Z = \begin{bmatrix} e^{-i\theta /2} & 0 \\ 0 & e^{i\theta /2} \\ \end{bmatrix}

Детальніше про значення та застосування цих вентилів розповідається в курсі Основи квантової інформації.

Вправа 1

Використай Qiskit, щоб створити квантові схеми, які готують стани, описані нижче. Потім запусти кожну схему за допомогою симулятора вектора стану та відобрази отриманий стан на сфері Блоха. Як бонус, спробуй передбачити, яким має бути кінцевий стан, спираючись на інтуїцію про вентилі та обертання у сфері Блоха.

(1) XX0XX|0\rangle

(2) HH0HH|0\rangle

(3) HZH0HZH|0\rangle

Підказки: Gate Z можна застосувати так:

qc.z(0)

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

### (1) XX|0> ###

# Create the single-qubit quantum circuit
qc = QuantumCircuit(1) ##your code goes here##

# Add a X gate to qubit 0
qc.x(0) ##your code goes here##

# Add a X gate to qubit 0
qc.x(0) ##your code goes here##

# Draw a circuit
qc.draw(output="mpl")

Output of the previous code cell

# See the statevector
out_vector = Statevector(qc)
print(out_vector)

# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([1.+0.j, 0.+0.j],
dims=(2,))

Output of the previous code cell

### (2) HH|0> ###
##your code goes here##
qc = QuantumCircuit(1)
qc.h(0)
qc.h(0)
qc.draw("mpl")

Output of the previous code cell

# See the statevector
out_vector = Statevector(qc)
print(out_vector)

# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([1.+0.j, 0.+0.j],
dims=(2,))

Output of the previous code cell

### (3) HZH|0> ###
##your code goes here##
qc = QuantumCircuit(1)
qc.h(0)
qc.z(0)
qc.h(0)
qc.draw("mpl")

Output of the previous code cell

# See the statevector
out_vector = Statevector(qc)
print(out_vector)

# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([0.+0.j, 1.+0.j],
dims=(2,))

Output of the previous code cell

3.3 Вимірювання

Вимірювання — теоретично дуже складна тема. Але на практиці вимірювання вздовж zz (саме так роблять усі квантові комп'ютери IBM®) просто змушує стан кубіта α0+β1(s.t.α2+β2=1)\alpha|0\rangle+\beta|1\rangle \quad (s.t.|\alpha|^2+|\beta|^2=1) перейти або в 0|0\rangle, або в 1|1\rangle, і ми спостерігаємо результат.

  • α2|\alpha|^2 — це ймовірність отримати 0|0\rangle при вимірюванні.
  • β2|\beta|^2 — це ймовірність отримати 1|1\rangle при вимірюванні.

Тому α\alpha і β\beta називаються амплітудами ймовірності. (див. «правило Борна»)

Наприклад, 220+221\frac{\sqrt{2}}{2}|0\rangle+\frac{\sqrt{2}}{2}|1\rangle при вимірюванні стане 0|0\rangle або 1|1\rangle з однаковою ймовірністю. 32012i1\frac{\sqrt{3}}{2}|0\rangle-\frac{1}{2}i|1\rangle з ймовірністю 75% стане 0|0\rangle.

Симулятор Qiskit Aer

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

# Create a new circuit with one qubits (first argument) and one classical bits (second argument)
qc = QuantumCircuit(1, 1)
qc.h(0)
qc.measure(0, 0) # Add the measurement gate

qc.draw(output="mpl")

Output of the previous code cell

Тепер ми готові запустити схему на симуляторі Aer. У цьому прикладі ми використаємо стандартне значення shots=1024, тобто виконаємо 1024 вимірювання. Потім відобразимо підрахунки у вигляді гістограми.

# Run the circuit on a simulator to get the results
# 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])
result = job.result()

# Print the results
counts = result[0].data.c.get_counts()
print(counts)

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

Output of the previous code cell

Ми бачимо, що 0 і 1 були виміряні з імовірністю приблизно по 50% кожне. Хоча шум тут не моделювався, стани все одно залишаються імовірнісними. Тому, очікуючи розподіл приблизно 50 на 50, ми рідко отримаємо його точно. Так само як при 100 підкиданнях монети рідко випаде рівно по 50 разів кожна сторона.

4. Багатокубітні квантові вентилі та заплутаність

4.1 Багатокубітна квантова схема

Двокубітну квантову схему можна створити за допомогою наступного коду. Ми застосуємо Gate H до кожного кубіта.

# Create the two qubits quantum circuit
qc = QuantumCircuit(2)

# Apply an H gate to qubit 0
qc.h(0)

# Apply an H gate to qubit 1
qc.h(1)

# Draw the circuit
qc.draw(output="mpl")

Output of the previous code cell

# See the statevector
out_vector = Statevector(qc)
print(out_vector)
Statevector([0.5+0.j, 0.5+0.j, 0.5+0.j, 0.5+0.j],
dims=(2, 2))

Примітка: порядок бітів у Qiskit

Qiskit використовує нотацію Little Endian для впорядкування кубітів і бітів, тобто кубіт 0 є крайнім правим бітом у бітових рядках. Наприклад: 01|01\rangle означає, що q0 — це 1|1\rangle, а q1 — це 0|0\rangle. Будь уважний, оскільки деяка наукова література з квантових обчислень використовує нотацію Big Endian (кубіт 0 — крайній лівий біт), і значна частина літератури з квантової механіки теж.

Також зверни увагу, що при зображенні квантової схеми q0|q_0\rangle завжди розміщується у верхній частині схеми. З урахуванням цього, квантовий стан наведеної схеми можна записати як тензорний добуток однокубітних квантових станів.

q1q0=(a0+b1)(c0+d1)|q1\rangle \otimes|q0\rangle = (a|0\rangle+b|1\rangle) \otimes (c|0\rangle+d|1\rangle)

=ac00+ad01+bc10+bd11= ac|0\rangle|0\rangle+ad|0\rangle|1\rangle+bc|1\rangle|0\rangle+bd|1\rangle|1\rangle

=ac00+ad01+bc10+bd11= ac|00\rangle+ad|01\rangle+bc|10\rangle+bd|11\rangle

( ac2+ad2+bc2+bd2=1|ac|^2+ |ad|^2+ |bc|^2+ |bd|^2=1 )

Початковий стан Qiskit — 00=00|0\rangle|0\rangle=|00\rangle, тому після застосування HH до кожного кубіта він переходить у стан рівномірної суперпозиції.

H0H0=12(0+1)12(0+1)=12(00+01+10+11)H|0\rangle \otimes H|0\rangle=\frac{1}{\sqrt{2}}(|0\rangle+|1\rangle) \otimes \frac{1}{\sqrt{2}}(|0\rangle+|1\rangle) = \frac{1}{2}(|00\rangle+|01\rangle+|10\rangle+|11\rangle)

=12((11)(11))=12(1111)=12((1000)+(0100)+(0010)+(0001))=\frac{1}{2}\left( \begin{pmatrix} 1 \\ 1 \end{pmatrix} \otimes \begin{pmatrix} 1 \\ 1 \end{pmatrix}\right) = \frac{1}{2}\begin{pmatrix} 1 \\ 1 \\ 1 \\ 1 \end{pmatrix}=\frac{1}{2}\left(\begin{pmatrix} 1 \\ 0 \\ 0 \\ 0 \end{pmatrix}+\begin{pmatrix} 0 \\ 1 \\ 0 \\ 0 \end{pmatrix}+\begin{pmatrix} 0 \\ 0 \\ 1 \\ 0 \end{pmatrix}+\begin{pmatrix} 0 \\ 0 \\ 0 \\ 1 \end{pmatrix}\right)

Правило вимірювання таке ж, як і для одного кубіта: ймовірність виміряти 00|00\rangle дорівнює ac2|ac|^2.

# Draw a Bloch sphere
plot_bloch_multivector(out_vector)

Output of the previous code cell

Тепер виміряємо цю схему.

# Create a new circuit with two qubits (first argument) and two classical bits (second argument)
qc = QuantumCircuit(2, 2)

# Apply the gates
qc.h(0)
qc.h(1)

# Add the measurement gates
qc.measure(0, 0) # Measure qubit 0 and save the result in bit 0
qc.measure(1, 1) # Measure qubit 1 and save the result in bit 1

# Draw the circuit
qc.draw(output="mpl")

Output of the previous code cell

Тепер ми знову використаємо симулятор Aer, щоб експериментально підтвердити, що відносні ймовірності всіх можливих вихідних станів приблизно рівні.

# Run the circuit on a simulator to get the results
# 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])
result = job.result()

# Print the results
counts = result[0].data.c.get_counts()
print(counts)

# Plot the counts in a histogram
plot_histogram(counts)
{'10': 262, '01': 246, '00': 265, '11': 251}

Output of the previous code cell

Як і очікувалось, стани 00|00\rangle, 01|01\rangle, 10|10\rangle, 11|11\rangle були виміряні приблизно по 25% кожен.

4.2 Багатокубітні квантові вентилі

Gate CNOT

Gate CNOT («controlled NOT» або CX) — це двокубітний вентиль, тобто його дія охоплює одразу два кубіти: керуючий кубіт і цільовий кубіт. CNOT перевертає цільовий кубіт лише тоді, коли керуючий кубіт перебуває у стані 1|1\rangle.

Вхід (цільовий, керуючий)Вихід (цільовий, керуючий)
0000
0111
1010
1101

Спочатку змоделюємо дію цього двокубітного вентиля, коли q0 і q1 обидва знаходяться у стані 0|0\rangle, та отримаємо вихідний вектор стану. Синтаксис Qiskit для цього: qc.cx(control qubit, target qubit).

# Create a circuit with two quantum registers and two classical registers
qc = QuantumCircuit(2, 2)

# Apply the CNOT (cx) gate to a |00> state.
qc.cx(0, 1) # Here the control is set to q0 and the target is set to q1.

# Draw the circuit
qc.draw(output="mpl")

Output of the previous code cell

# See the statevector
out_vector = Statevector(qc)
print(out_vector)
Statevector([1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
dims=(2, 2))

Як і очікувалось, застосування Gate CNOT до 00|00\rangle не змінило стан, оскільки керуючий кубіт перебував у стані 0|0\rangle. Повернімося до нашої операції CNOT. Цього разу застосуємо Gate CNOT до 01|01\rangle і подивимося, що відбудеться.

qc = QuantumCircuit(2, 2)

# q0=1, q1=0
qc.x(0) # Apply a X gate to initialize q0 to 1
qc.cx(0, 1) # Set the control bit to q0 and the target bit to q1.

# Draw the circuit
qc.draw(output="mpl")

Output of the previous code cell

# See the statevector
out_vector = Statevector(qc)
print(out_vector)
Statevector([0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
dims=(2, 2))

Після застосування Gate CNOT стан 01|01\rangle перетворився на 11|11\rangle.

Перевіримо ці результати, запустивши схему на симуляторі.

# Add measurements
qc.measure(0, 0)
qc.measure(1, 1)

# Draw the circuit
qc.draw(output="mpl")

Output of the previous code cell

# Run the circuit on a simulator to get the results
# 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(backend)
job = sampler.run([isa_qc])
result = job.result()

# Print the results
counts = result[0].data.c.get_counts()
print(counts)

# Plot the counts in a histogram
plot_histogram(counts)
{'11': 1024}

Output of the previous code cell

Результати показують, що 11|11\rangle було виміряно зі 100% імовірністю.

4.3 Квантова заплутаність та виконання на реальному квантовому пристрої

Почнімо з представлення конкретного заплутаного стану, який є особливо важливим у квантових обчисленнях, а потім дамо визначення поняттю «заплутаний»:

1200+1211\frac{1}{\sqrt{2}}|00\rangle + \frac{1}{\sqrt{2}}|11\rangle

цей стан називається станом Белла.

Заплутаний стан — це стан ψAB|\psi_{AB}\rangle, що складається з квантових станів ψA|\psi_A\rangle та ψB|\psi_B\rangle, який не можна представити як тензорний добуток окремих квантових станів.

Якщо ψAB|\psi_{AB}\rangle нижче має два стани ψA|\psi\rangle_A і ψB|\psi\rangle_B:

ψAB=12(00+11)=12(0A0B+1A1B)|\psi_{AB}\rangle = \frac{1}{\sqrt{2}}(|00\rangle +|11\rangle) = \frac{1}{\sqrt{2}}(|0\rangle_A|0\rangle_B +|1\rangle_A|1\rangle_B) ψA=a00+a11|\psi\rangle_A = a_0|0\rangle+a_1|1\rangle ψB=b00+b11|\psi\rangle_B = b_0|0\rangle+b_1|1\rangle

тоді тензорний добуток цих двох станів має вигляд:

ψAψB=a0b000+a0b101+a1b010+a1b111|\psi\rangle _A\otimes |\psi\rangle _B = a_0 b_0|00\rangle+a_0 b_1|01\rangle+a_1 b_0|10\rangle+a_1 b_1|11\rangle

але не існує коефіцієнтів a0,a1,b0,a_0, a_1, b_0, і b1b_1, які б задовольняли ці два рівняння. Отже, ψAB|\psi_{AB}\rangle не можна представити як тензорний добуток окремих квантових станів ψA|\psi\rangle_A і ψB|\psi\rangle_B, а це означає, що ψAB=12(00+11)|\psi_{AB}\rangle = \frac{1}{\sqrt{2}}(|00\rangle +|11\rangle) є заплутаним станом.

Створімо стан Белла і запустимо його на реальному квантовому комп'ютері. Ми будемо дотримуватися чотирьох кроків написання квантової програми, які називаються Qiskit patterns:

  1. Map problem to quantum circuits and operators
  2. Optimize for target hardware
  3. Execute on target hardware
  4. Post-process the results

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

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

Наступна клітинка коду створює схему, що породжує стан Белла — конкретний двокубітний заплутаний стан, описаний вище.

qc = QuantumCircuit(2, 2)

qc.h(0)
qc.cx(0, 1)

qc.measure(0, 0)
qc.measure(1, 1)

qc.draw("mpl")

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

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

Qiskit перетворює абстрактні схеми на схеми QISA (Quantum Instruction Set Architecture — архітектура набору квантових інструкцій), що відповідають обмеженням цільового апаратного забезпечення, та оптимізує їхню продуктивність. Тому перед оптимізацією слід вказати цільове апаратне забезпечення. Якщо у тебе не встановлено qiskit-ibm-runtime, спочатку потрібно його встановити. Докладніше про Qiskit Runtime можна дізнатися в довіднику API.

# Install
# !pip install qiskit-ibm-runtime

Вкажемо цільове апаратне забезпечення.

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
service.backends()
# You can specify the device
# backend = service.backend('ibm_kingston')
# You can also identify the least busy device
backend = service.least_busy(operational=True)
print("The least busy device is ", backend)

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

# Transpile the circuit into basis gates executable on the hardware
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
target_circuit = pm.run(qc)

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

Ти можеш побачити, що під час транспіляції схема була переписана з використанням нових вентилів. Для отримання додаткової інформації зверніться до документації ECRGate.

Крок 3. Виконання цільової схеми

Тепер запустимо цільову схему на реальному пристрої.

sampler = Sampler(backend)
job_real = sampler.run([target_circuit])

job_id = job_real.job_id()
print("job id:", job_id)

Виконання на реальному пристрої може вимагати очікування в черзі, оскільки квантові комп'ютери є цінним ресурсом з великим попитом. job_id використовується для перевірки статусу виконання та результатів завдання пізніше.

# Check the job status (replace the job id below with your own)
job_real.status(job_id)

Також можна перевірити статус завдання на панелі керування IBM Quantum:https://quantum.cloud.ibm.com/workloads

# 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_id) # Input your job-id between the quotations
job_real.status()
# Execute after job has successfully run
result_real = job_real.result()
print(result_real[0].data.c.get_counts())

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

Нарешті, потрібно постобробити результати, щоб отримати вихідні дані в очікуваному форматі — у вигляді значень або графіків.

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

Як видно, 00|00\rangle та 11|11\rangle спостерігаються найчастіше. Є кілька результатів, відмінних від очікуваних даних — вони зумовлені шумом та декогеренцією кубітів. Детальніше про помилки та шум у квантових комп'ютерах ми дізнаємося в наступних уроках цього курсу.

4.4 Стан GHZ

Концепцію заплутаності можна поширити на системи з більш ніж двома кубітами. Стан GHZ (стан Грінбергера–Горна–Цайлінгера) — це максимально заплутаний стан трьох або більше кубітів. Стан GHZ для трьох кубітів визначається як

12(000+111)\frac{1}{\sqrt 2}(|000\rangle + |111\rangle)

Його можна створити за допомогою такої квантової схеми.

qc = QuantumCircuit(3, 3)

qc.h(0)
qc.cx(0, 1)
qc.cx(1, 2)

qc.measure(0, 0)
qc.measure(1, 1)
qc.measure(2, 2)

qc.draw("mpl")

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

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

Використовуючи QuantumCircuit.depth(), можна перевірити глибину квантової схеми. Глибина наведеної вище схеми дорівнює 4. Верхній кубіт має лише три вентилі, включаючи вимірювання. Але існує шлях від верхнього кубіта до кубіта 1 або кубіта 2, який включає ще один вентиль CNOT.

qc.depth()
4

Вправа 2

Стан GHZ системи з 8 кубітів має вигляд

12(00000000+11111111)\frac{1}{\sqrt 2}(|00000000\rangle + |11111111\rangle)

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

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

# Step 1
qc = QuantumCircuit(8, 8)

##your code goes here##
qc.h(0)
qc.cx(0, 4)
qc.cx(4, 6)
qc.cx(6, 7)

qc.cx(4, 5)

qc.cx(0, 2)
qc.cx(2, 3)

qc.cx(0, 1)
qc.barrier() # for visual separation

# measure
for i in range(8):
qc.measure(i, i)

qc.draw("mpl")
# print(qc.depth())

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

print(qc.depth())
5
from qiskit.visualization import plot_histogram
# Step 2
# For this exercise, the circuit and operators are simple, so no optimizations are needed.

# Step 3
# Run the circuit on a simulator to get the results
backend = AerSimulator()

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

sampler = Sampler(mode=backend)
job = sampler.run([isa_qc], shots=1024)
result = job.result()

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

# Step 4
# Plot the counts in a histogram

plot_histogram(counts)
{'11111111': 535, '00000000': 489}

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

5. Підсумок

Ти вивчив(-ла) квантові обчислення за допомогою схемної моделі з використанням квантових бітів і вентилів, а також розглянув(-ла) суперпозицію, вимірювання та заплутаність. Крім того, ти дізнав(-лась) про метод виконання квантової схеми на реальному квантовому пристрої.

У заключній вправі зі створення схеми GHZ ти намагав(-лась) зменшити глибину схеми — це важливий фактор для отримання рішення корисного масштабу на шумному квантовому комп'ютері. У наступних уроках цього курсу ти детальніше дізнаєшся про шум і методи усунення помилок. У цьому уроці, як вступ, ми розглянули зменшення глибини схеми на ідеальному пристрої, але насправді необхідно враховувати обмеження реального пристрою, зокрема зв'язність кубітів. Про це ти дізнаєшся більше в наступних уроках цього курсу.

# See the version of Qiskit
import qiskit

qiskit.__version__
'2.0.2'