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

Реалізація в Qiskit

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

# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit
from qiskit import __version__

print(__version__)
2.1.1

Почнемо з імпорту класів Statevector та Operator, а також функції квадратного кореня з NumPy. Надалі, як правило, ми будемо робити всі необхідні імпорти на початку кожного уроку.

from qiskit.quantum_info import Statevector, Operator
from numpy import sqrt

Тензорні добутки

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

Наприклад, нижче ми створюємо два вектори стану, що представляють 0\vert 0\rangle та 1,\vert 1\rangle, і використовуємо метод tensor для створення нового вектора ψ=01.\vert \psi\rangle = \vert 0\rangle \otimes \vert 1\rangle. Зверни увагу, що ми використовуємо метод from_label для визначення станів 0\vert 0\rangle та 1,\vert 1\rangle, а не визначаємо їх самостійно.

zero = Statevector.from_label("0")
one = Statevector.from_label("1")
psi = zero.tensor(one)
display(psi.draw("latex"))

01 |01\rangle

Інші допустимі мітки включають "+" та "-" для станів плюс і мінус, а також "r" та "l" (скорочення від "right" та "left" — "правий" та "лівий") для станів

+i=120+i21таi=120i21.\vert {+i} \rangle = \frac{1}{\sqrt{2}} \vert 0 \rangle + \frac{i}{\sqrt{2}} \vert 1 \rangle \qquad\text{та}\qquad \vert {-i} \rangle = \frac{1}{\sqrt{2}} \vert 0 \rangle - \frac{i}{\sqrt{2}} \vert 1 \rangle.

Тут "+", "-" або "right" та "left" походять із контексту квантово-механічного спіну, в якому компонент спіну може вказувати вліво або вправо в експерименті; це не стосується крайнього правого або крайнього лівого кубіта в системах із множинними кубітами. Ось приклад тензорного добутку +\vert {+} \rangle та i.\vert {-i} \rangle.

plus = Statevector.from_label("+")
minus_i = Statevector.from_label("l")
phi = plus.tensor(minus_i)
display(phi.draw("latex"))

1200i201+1210i211\frac{1}{2} |00\rangle- \frac{i}{2} |01\rangle+\frac{1}{2} |10\rangle- \frac{i}{2} |11\rangle

Альтернативою є використання операції ^ для тензорних добутків, що природно дає ті самі результати.

display((plus ^ minus_i).draw("latex"))

1200i201+1210i211\frac{1}{2} |00\rangle- \frac{i}{2} |01\rangle+\frac{1}{2} |10\rangle- \frac{i}{2} |11\rangle

Клас Operator також має метод tensor (а також метод from_label), як ми бачимо в наступних прикладах.

H = Operator.from_label("H")
Id = Operator.from_label("I")
X = Operator.from_label("X")
display(H.tensor(Id).draw("latex"))
display(H.tensor(Id).tensor(X).draw("latex"))
[220220022022220220022022] \begin{bmatrix} \frac{\sqrt{2}}{2} & 0 & \frac{\sqrt{2}}{2} & 0 \\ 0 & \frac{\sqrt{2}}{2} & 0 & \frac{\sqrt{2}}{2} \\ \frac{\sqrt{2}}{2} & 0 & - \frac{\sqrt{2}}{2} & 0 \\ 0 & \frac{\sqrt{2}}{2} & 0 & - \frac{\sqrt{2}}{2} \\ \end{bmatrix} [02200022002200022000000220002200220002200220002200220002200000022000220022000220] \begin{bmatrix} 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 \\ \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 \\ 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} \\ 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 \\ 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 & 0 \\ \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 & 0 & 0 \\ 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} \\ 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 \\ \end{bmatrix}

Знову ж таки, як і у випадку з векторами, операція ^ є еквівалентною.

display((H ^ Id ^ X).draw("latex"))
[02200022002200022000000220002200220002200220002200220002200000022000220022000220] \begin{bmatrix} 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 \\ \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 \\ 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} \\ 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 \\ 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 & 0 \\ \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 & 0 & 0 \\ 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} \\ 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 \\ \end{bmatrix}

Складені стани можна еволюціонувати за допомогою складених операцій, як і очікується, — так само, як ми бачили для одиночних систем у попередньому уроці. Наприклад, наступний код обчислює стан (HI)ϕ(H\otimes I)\vert\phi\rangle для ϕ=+i\vert\phi\rangle = \vert + \rangle \otimes \vert {-i}\rangle (вже визначеного вище).

display(phi.evolve(H ^ Id).draw("latex"))

22002i201\frac{\sqrt{2}}{2} |00\rangle- \frac{\sqrt{2} i}{2} |01\rangle

Ось код, що визначає операцію CXCX та обчислює CXψCX \vert\psi\rangle для ψ=+0.\vert\psi\rangle = \vert + \rangle \otimes \vert 0 \rangle. Для ясності: це операція CXCX, в якій лівий кубіт є керуючим, а правий — цільовим. Результатом є стан Белла ϕ+.\vert\phi^{+}\rangle.

CX = Operator([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])
psi = plus.tensor(zero)
display(psi.evolve(CX).draw("latex"))

2200+2211\frac{\sqrt{2}}{2} |00\rangle+\frac{\sqrt{2}}{2} |11\rangle

Часткові вимірювання

У попередньому уроці ми використовували метод measure для симуляції вимірювання вектора квантового стану. Цей метод повертає два елементи: симульований результат вимірювання та новий Statevector з урахуванням цього вимірювання.

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

w=001+010+1003\vert w\rangle = \frac{\vert 001\rangle + \vert 010\rangle + \vert 100\rangle}{\sqrt{3}}

і вимірює кубіт з номером 0, який є крайнім правим кубітом. (Qiskit нумерує кубіти починаючи з 0, справа наліво. До цієї конвенції нумерації ми повернемося в наступному уроці.)

w = Statevector([0, 1, 1, 0, 1, 0, 0, 0] / sqrt(3))
display(w.draw("latex"))

result, state = w.measure([0])
print(f"Measured: {result}\nState after measurement:")
display(state.draw("latex"))

result, state = w.measure([0, 1])
print(f"Measured: {result}\nState after measurement:")
display(state.draw("latex"))

33001+33010+33100\frac{\sqrt{3}}{3} |001\rangle+\frac{\sqrt{3}}{3} |010\rangle+\frac{\sqrt{3}}{3} |100\rangle

Measured: 0
State after measurement:

22010+22100\frac{\sqrt{2}}{2} |010\rangle+\frac{\sqrt{2}}{2} |100\rangle

Measured: 00
State after measurement:

100 |100\rangle