Есть две функции
Есть две булевы функции аргументов, одна — константная, другая — сбалансированная. На какую сам сядешь, на какую фронтендера посадишь? Вот только функции неизвестны, а вызвать их разрешается лишь один раз.
Если не знаешь, как решить подобную задачу, добро пожаловать под кат. Там я расскажу про квантовые алгоритмы и покажу как их эмулировать на самом народном языке — на Python.
I«ve come to talk with you again
Давайте чуть более формально поставим задачу о двух функциях. Пусть дана булева функция и о ней априорно известно, что она или константна, то есть для любого из своих аргументов всегда возвращает либо 0, либо 1, или сбалансирована, то есть ровно на половине своих аргументов возвращает 0, а ровно на половине 1. Требуется определить, константна функция или сбалансирована. При этом считается, что время вызова функции несоизмеримо больше любых других операций, поэтому сложность алгоритма определяется количеством вызовов функции.
Пример:
- сбалансирована:
0 0 0 0 1 1 1 0 1 1 1 0 - константна:
0 0 1 0 1 1 1 0 1 1 1 1 - ни сбалансирована, ни константна:
0 0 0 0 1 0 1 0 0 1 1 1
Задача, безусловно, искусственная и навряд ли когда-нибудь кому-нибудь встретится на практике, однака она — классический проводник в дивный новый мир квантовых вычислений, а нарушать традиции я не осмелюсь.
Классическое детерминированное решение
Давайте, для начала, решим задачу в классической модели вычислений. Для этого в худшем случае понадобится вызвать функцию на аргументах: ровно на половине и ещё одном. Если все вычисленные значения одинаковы, то функция, очевидно, константна. Если же существуют хотя-бы два различных результата, функция сбалансирована. Сложность детерминированного алгоритма экспоненциальна и составляет .
Алгоритм на Python:
from itertools import product, starmap, tee
def pairwise(xs):
a, b = tee(xs)
next(b, None)
return zip(a, b)
def is_constant(f, n):
m = 2 ** (n - 1)
for i, (x, y) in enumerate(pairwise(starmap(f, product({0, 1}, repeat=n)))):
if i > m:
break
if x != y:
return False
return True
Классическое вероятностное решение
А что, если вместо половины аргументов мы проверим меньшее их число и вынесем вердикт? Точным ответ уже не будет, но с какой вероятностью мы ошибёмся? Допустим, мы вычислили функцию на аргументах. Если среди значений функции есть два различных, то всё просто — функция сбалансирована. Иначе, мы объявляем её константной с вероятностью . Предположим, что мы ошиблись и функция на самом деле сбалансирована. Посчитаем вероятность ошибки . Если мы выбирали аргументы равномерно, то вероятность того, что два подряд идущих значения функции одинаковы, равна , а вероятность же встретить одинаковых подряд идущих значений равна . Таким образом:
Обратная функция:
При фиксированном сложность классического вероятностного алгоритма константна и равна Чтобы быть уверенным в ответе на 99.99%, необходимо вызвать функцию всего 14 раз.
Алгоритм на Python:
import random
from itertools import product, starmap, tee
def pairwise(xs):
a, b = tee(xs)
next(b, None)
return zip(a, b)
def is_constant(f, n, k=14):
xs = list(product({0, 1}, repeat=n))
random.shuffle(xs)
xs = xs[:k]
for x, y in pairwise(starmap(f, xs)):
if x != y:
return False
return True
А если я скажу вам, что существует константное детермининированное решение со сложностью , позволяющее вызвать функцию всего один раз?
Правда, прежде чем его рассмотреть, придётся отвлечься…
Because a vision softly creeping
Мифы
Пережде чем начать, хотелось бы обсудить несколько расхожих мифов, связанных с квантовыми вычислениями:
- Квантовые алгоритмы — это сложно.
Да, их сложно синтезировать, ибо требуется для этого математическое воображение и проницательность. Их сложно реализовывать на настоящих квантовых компьютерах: для этого необходимо превосходно знать физику и засиживаться каждый день допоздна в лабаратории на кафедре. Но что точно не требует никаких особых знаний и невероятного количества усердия, так это их понимание. Я утверждаю, что каждый может понимать квантовые алгоритмы: они опираются на крайне простую математику, доступную любому первокурснику. Всё, что от вас требуется — лишь немного времени на изучение.
- Уже существуют квантовые компьютеры на тысячи кубитов от D-Wave
Нет, это не настоящие квантовые компьютеры. - Не существует ни одного настоящего квантового компьютера
Нет, существуют. В лабораторных условиях и располагают они лишь несколькими кубитами. - Квантовые компьютеры позволят решать задачи, недоступные ранее
Нет, множество задач, вычислимых в классической и квантовой моделях, совпадают. Квантовые вычисления позволяют лишь снизить сложность небольшого подмножества этих задач. - На квантовом компьютере Crysis на максималках будет летать
За исключением некоторого подмножества задач, которые квантовая модель вычислений способна ускорить, остальные могут быть решены лишь эмуляцией классического компьютера. Что, как вы понимаете, очень медленно. Crysis, скорее всего, будет лагать.
- Квантовый компьютер — это чёрная коробочка с входом и выходом, заглянув в которую можно всё испортить
Если вам 12 лет, такая аналогия сгодится. В любом другом случае она, как и все другие аналогии с коробками, котами, лупами и «связанными» нитками электронами, так активно продвигаемые во всех научно-популярных источниках, только лишь запутывает, создаёт иллюзию ложного понимания и скорее вредна, чем полезна. Откажитесь от этих аналогий.
Зачем?
Зачем прикладному математику (программисту) уметь разбираться в квантовых алгоритмах на прикладном уровне? Тут всё просто, я готов предложить вам два довода:
- Для саморазвития. Почему бы и нет?
- Они уже идут. Они, квантовые компьютеры. Они уже рядом. Моргнуть не успеете, как парочка появится в серверной вашей компании, а ещё через несколько лет и в виде сопроцессора в вашем ноутбуке. И бежать уже будет некуда. Придётся под них программировать, вызывать квантовые сопрограммы. А без понимания это делать сложно, согласитесь.
Left its seeds while I was sleeping
Самой базовой составляющей квантовых вычислений является квантовая система. Квантовая система — физическая система, все действия которой сравнимы по величине с постоянной Планка. Это определение и тот факт, что квантовые системы подчиняются законам матричной механики — все знания, которые нам потребуются из физики. Дальше — только математика.
Как и любая другая физическая система, квантовая система может находиться в определённом состоянии. Все возможные состояния квантовой системы образуют гильбертово пространство над полем комплексных чисел. Надеюсь, с концепцией комплексных чисел читатель знаком — их понимание необходимо везде в дальнейшем. Если нет, советую познакомиться и возвращаться. Гильбертово пространство же является полным нормированным метрическим линейным пространством с нормой , где — скалярное произведение. По порядку с конца:
- Линейное (векторное) пространство — множество элементов с введёнными на нём операциями сложения элементов и умножения на элемент поля (в нашем случае поля комплексных чисел). Операции эти должны быть замкнуты (результат должен принадлежать множеству ) и должны выполняться 8 аксиом. Посмотреть полный их список, а так же познакомиться подробнее с линейными пространствами рекомендую здесь.
- В метрическом пространстве для любых элементов определено расстояние , которое удовлетворяет требованиям (аксиомам метрического
пространства):- , при этом тогда и только тогда, когда и совпадают;
- ;
- — неравенство треугольника.
- , при этом тогда и только тогда, когда и совпадают;
- В нормированном пространстве для любого элемента существует вещественное число , называемое его нормой и удовлетворяюещее, опять же, трём аксиомам:
- , если же , то — нулевой элемент;
- ;
- .
- , если же , то — нулевой элемент;
Введём в полученном пространстве скалярное произведение, удовлетворяющее обычным требованиям скалярного произведения, введём норму как показано выше и получим пространство Гильберта.
Обсудим ещё понятие сопряжённого пространства. Пространством, сопряжённым к называется пространство линейных операторов над . Что такое линейный оператор? Можно думать о нём как об обобщении линейной функции: для линейноного оператора должно выполняться:
где , . (На самом деле, ещё и его норма должна быть ограничена на единичной гиперсфере, но, дабы избежать ещё десятка громоздких определений, ограничимся таким интуитивным представлением.)
В квантовой информатике по историческим причинам используются обозначения Дирака. Они могут казаться необоснованно громоздкими и вычурными, но они — стандарт, которого стоит придерживаться. В этих обозначениях элемент нашего гильбертова пространства, описывающий состояние системы, называется кет-вектором и обозначается
Бра-вектором называется элемент сопряжённого пространства
такой что
То есть, это линейный оператор, применение которого к нашему вектору состояния аналогично скалярному произведению на соответствующий ему элемент «оригинального» гильбертова пространства. Для удобства записи при приминении бра-вектора к кет-вектору две вертикальные черты сливаются в одну, что показано в выражении выше.
Теперь можно сделать важную поправку: квантовую систему может описывать не любое гильбертово пространство, а лишь такое, что
то есть норма каждого элемента равна единице.
Если мы выделим в нашем гильбертовом пространстве состояний некоторый базис , то любой кет-вектор сможем записать в виде вектора комплексных чисел — коэффициентов его разложения по этому базису:
при этом матричная механика говорит нам, что квадраты модулей коэффициентов разложения физически означают вероятности нахождения квантовой системы в соответствующем базисном состоянии при измерении в этом базисе.
Вот оно — первое и основное свойство квантовых систем, которое так часто мусолят в популярных статьях: если измерить систему в некотором базисе, то она перейдёт в одно из базисных состояний, потеряет информацию и не сможет вернуться назад. Вот только при прочтении складывается ощущение, что всё происходит абсолютно случайно и повлиять на это никак нельзя, тогда как на самом деле вероятности перехода известны заранее и, более того, зависят от измерительного базиса. Если бы всё было так случайно, как нам представляют, детерменированные квантовые алгоритмы были бы невозможны.
Если мы можем представить элемент Гильбертова пространства вектором при некотором фиксированном базисе, то линейный оператор над этим пространством мы можем представить матрицей.
Действительно,
эквивалентно
где получается поочерёдным применением оператора к базисным элементам и выписыванием получившихся элементов по строкам, а — разложение в этом же базисе.
Пусть оператор представляется матрицей
Элементы матрицы — комплексные числа. Давайте возьмём каждый элемент и заменим его комплексно сопряжённым (комплексно сопряжённым к называется число ) и, заодно, транспонируем всю матрицу:
Такая матрица называется эрмитово-сопряжённой к . Если , где — единичный оператор (с единичной матрицей), то соответствующий оператор называется унитарным.
Второе правило, которое диктует нам матричная механика: на квантовую систему могут действовать только унитарные операторы. Почему? Потому что такие преобразования обратимы во времени и не теряют информацию. Действительно, если
то можно применить обратное преобразование
и получить исходное состояние системы.
Напоследок самое важное: тензорное произведение. Тензорным произведением двух гильбертовых пространств и называется гильбертово пространство, обозначаемое . Я не буду приводить формальное определение, лишь отмечу важные нам свойства:
- Размерность получившегося пространства равна произведению размерностей исходных пространств:
; - Если — базис , а — базис , то — порождающий базис .
Тензорным же произведенем операторов из и из (оператор представлен матрицей, показанной выше) называется оператор из с матрицей
Такое произведение ещё называется произведением Кронекера: мы умножаем вторую матрицу на каждый элемент первой матрицы и из получившихся блоков составляем блочную матрицу. Если размерность равнялась , а размерность равнялась , то размерность матрицы, полученной в ходе тензорного произведения, будет равна .
Пример:
Третье важное свойство квантовых систем: две квантовые системы могут находиться в состоянии суперпозиции, при этом новое пространство состояний представляет собой тензорное произведение исходных пространств, а состояние новой системы будет являться тензорным произведением состояний исходных систем. Так, суперпозицией систем в состояниях и будет новая система в состоянии , описываемая гильбертовым пространством .
And the vision that was planted in my brain
Вот и вся математика, что нам понадобится. На всякий случай, резюмируя:
- При фиксированном базисе квантовую систему можно описать комплексным вектором, а эволюцию этой системы — унитарной комплексной матрицей;
- Квантовую систему можно измерить в каком-либо базисе и она перейдёт в одно из базисных состояний в соответствии с заранее определёнными вероятностями.
Получается, чтобы описывать, изучать, понимать и эмулировать на классическом компьютере квантовые алгоритмы, достаточно лишь умножать матрицы на вектора — это даже проще, чем нейронные сети: здесь нет нелинейностей!
Кубит
Давайте рассмотрим некоторую квантовую систему, описываемую двумерным гильбертовым пространством и выделим в ней некоторый базис, вектора которого обозначим как и . Внутри скобок записывается индекс базисного вектора в двоичной системе счисления, начиная с нуля без дополнительных символов. Такие обозначения окажутся очень удобными. Таким образом,
и произвольный вектор можно выразить следующим образом:
где и — некоторые комплексные числа, такие что (всплмните интерпретацию коэффициентов разложения и условие нормировки из предыдущего параграфа). Так вот, такая простая квантовая система называется кубитом (quantum bit, qbit). Кубит — аналог классического бита в квантовой модели вычислений. Нетрудно видеть, что пространство всевозможных состояний одного кубита представляет из себя трёхмерную сферу, называемую сферой Блоха, где соответствует нижнему полюсу, а — верхнему.
Регистр
Один кубит, как и один бит — слишком скучно, поэтому сразу рассмотрим суперпозицию нескольких кубитов. Такая суперпозиция называется квантовым регистром (quantum register, qregister) из кубитов. Например, квантовый регистр из 2 кубитов будет описываться пространством и иметь 4 базисных состояния:
Соответственно, любое состояние такого регистра можно представить в виде
где . Заметьте, что в наших обозначениях базисный вектор с единицей на -ом месте обозначется числом , записанным в двоичном виде.
Далее аналогично. Квантовый регистр из кубитов будет описываться -мерным гильбертовым пространством , иметь базисных состояний, формируемых аналогичным образом. Не откладывая надолго, научимся эмулировать квантовые регистры:
import numpy as np
class QRegister:
def __init__(self, n_qbits, init):
self._n = n_qbits
assert len(init) == self._n
self._data = np.zeros((2 ** self._n), dtype=np.complex64)
self._data[int('0b' + init, 2)] = 1
3 строчки кода для создания квантового регистра — совсем не сложно, согласитесь. Использовать можно таким образом:
a = QRegister(1, '0') # |0>
b = QRegister(1, '1') # |1>
c = QRegister(3, '010') # |010>
Квантовый алгоритм включает в себя:
- Инициализацию квантового регистра;
- Набор унитарных преобразований над ним;
- Измерение результата.
Измерение
С первым пунктом разобрались и научились его эмулировать, давайте теперь научимся эмулировать последний: измерение. Как вы помните, квадраты коэффициентов вектора состояния физически означают вероятности перехода в это состояние. В соответствии с этим реализуем новый метод в классе QRegister:
def measure(self):
probs = np.real(self._data) ** 2 + np.imag(self._data) ** 2
states = np.arange(2 ** self._n)
mstate = np.random.choice(states, size=1, p=probs)[0]
return f'{mstate:>0{self._n}b}'
Генерируем вероятности
probs
выбора одного из состояний states
и случайно выбираем его с помощью np.random.choice
. Остаётся только вернуть бинарную строку с соответствующим количеством дополняющих нулей. Очевидно, что для базисных состояний ответ всегда будет одинаков и равен самому этому состоянию. Проверим: >>> QRegister(1, '0').measure()
'0'
>>> QRegister(2, '10').measure()
'10'
>>> QRegister(8, '01001101').measure()
'01001101'
Почти всё готово, чтобы решить нашу задачу! Осталось лишь научиться влиять на квантовые регистры. Мы уже знаем, что сделать это можно унитарными преобразованиями. В квантовой информатике унитарное преобразование называется гейтом (quantum gate, qgate, gate).
Гейты
В рамках данной статьи рассмотрим лишь малое число самых основных гейтов, которые нам пригодятся. На самом деле, их намного больше.
Единичный
Единичный гейт — самый простой, какой только можно рассмотреть. Его матрица выглядит следующим образом:
Он никак не изменяет кубит, на который действует:
однако не стоит считать его бесполезным — он нам понадобится, и не раз.
Гейт Адамара
Не составляет труда проверить, что матрица унитарна:
Рассмотрим действие гейта Адамара на базисные кубиты:
Или в общем виде [1]:
Как можно заметить, гейт Адамара любое базисное состояние переводит в равновероятное — при измерении с равной вероятностью можно получить любой результат.
Гейты Паули
Три карйне важных гейта, которым соответствуют матрицы, введённые Вольфгангом Паули:
Гейт ещё называется NOT-гейтом:
, а геометрически его применение эквивалентно повороту на сфере Блоха на радиан вокруг оси .
Гейты и аналогичны гейту за тем исключением, что вращение производится вокруг соответствующей оси.
Существует теорема, согласно которой с помощью гейтов , , и можно выразить любой