Алгоритм Дойча–Йожи — это детерминированный квантовый алгоритм, предложенный Дэвидом Дойчем и Ричардом Йожой в 1992 году с улучшениями Ричарда Клива , Артура Экерта , Кьяры Маккиавелло и Микеле Моски в 1998 году. [1] [2] Несмотря на небольшую практическую пользу, это один из первых примеров квантового алгоритма, который экспоненциально быстрее любого возможного детерминированного классического алгоритма. [3]
Задача Дойча–Йожи специально разработана так, чтобы быть простой для квантового алгоритма и сложной для любого детерминированного классического алгоритма. Это задача черного ящика , которая может быть эффективно решена квантовым компьютером без ошибок, тогда как детерминированному классическому компьютеру потребовалось бы экспоненциальное число запросов к черному ящику для решения задачи. Более формально, она дает оракул, относительно которого EQP , класс задач, которые могут быть решены точно за полиномиальное время на квантовом компьютере, и P различны. [4]
Поскольку задача легко решается на вероятностном классическом компьютере, она не дает оракульного разделения с BPP , классом задач, которые могут быть решены с ограниченной ошибкой за полиномиальное время на вероятностном классическом компьютере. Задача Саймона является примером задачи, которая дает оракульное разделение между BQP и BPP .
В задаче Дойча–Йожи нам дан черный ящик квантового компьютера, известный как оракул , который реализует некоторую функцию:
Функция принимает n-битные двоичные значения в качестве входных данных и выдает либо 0, либо 1 в качестве выходных данных для каждого такого значения. Нам обещают , что функция либо постоянна (0 на всех входных данных или 1 на всех входных данных), либо сбалансирована (1 для ровно половины входной области и 0 для другой половины). [1] Затем задача состоит в том, чтобы определить, является ли она постоянной или сбалансированной, используя оракул.
Для обычного детерминированного алгоритма, где — число бит, в худшем случае потребуются оценки . Чтобы доказать, что является константой, необходимо оценить чуть более половины набора входов и найти их выходы идентичными (потому что функция гарантированно будет либо сбалансированной, либо постоянной, а не где-то посередине). Лучший случай имеет место, когда функция сбалансирована, а первые два выходных значения различны. Для обычного рандомизированного алгоритма достаточно постоянной оценки функции, чтобы получить правильный ответ с высокой вероятностью (неудачный с вероятностью ) . Однако оценки все еще требуются, если мы хотим получить ответ, в котором нет возможности ошибки. Квантовый алгоритм Дойча-Йожи дает ответ, который всегда верен, с одной оценкой .
Алгоритм Дойча–Йожи обобщает более раннюю (1985) работу Дэвида Дойча, которая предоставила решение для простого случая, когда . В частности, если задана булева функция, вход которой составляет один бит, , является ли она константой? [5]
Алгоритм, как его изначально предложил Дойч, не был детерминированным. Алгоритм был успешным с вероятностью одна половина. В 1992 году Дойч и Йожа создали детерминированный алгоритм, который был обобщен до функции, принимающей биты на вход. В отличие от алгоритма Дойча, этот алгоритм требовал двух оценок функции вместо одной.
Дальнейшие усовершенствования алгоритма Дойча–Йожи были сделаны Клеве и др. [2], в результате чего был создан алгоритм, который является одновременно детерминированным и требует только одного запроса . Этот алгоритм до сих пор называют алгоритмом Дойча–Йожи в честь новаторских методов, которые они использовали. [2]
Для работы алгоритма Дойча-Йожи оракул, вычисляющий из , должен быть квантовым оракулом, который не декогерирует . В своих вычислениях он не может сделать копию , поскольку это нарушило бы теорему о запрете клонирования . Точка зрения алгоритма Дойча-Йожи как оракула означает, что неважно, что делает оракул, поскольку он просто должен выполнить обещанное преобразование.
Алгоритм начинается с битового состояния . То есть, первые n битов находятся в состоянии , а последний бит — . К каждому биту применяется вентиль Адамара для получения состояния
где пробегает все -битные строки, каждая из которых может быть представлена числом от до . У нас есть функция, реализованная как квантовый оракул. Оракул отображает свое входное состояние в , где обозначает сложение по модулю 2. Применение квантового оракула дает;
Для каждого из них есть либо 0, либо 1. Проверяя эти две возможности, мы видим, что указанное выше состояние равно
На этом этапе последний кубит можно проигнорировать, и останется следующее:
Далее мы пропустим каждый кубит через вентиль Адамара . Полное преобразование по всем кубитам можно выразить с помощью следующего тождества:
( это сумма побитового произведения). Это приводит к
Из этого мы видим, что вероятность измерения состояния равна
Вероятность измерения , соответствующая , равна
который оценивается как 1, если является постоянным ( конструктивная интерференция ) и 0, если является сбалансированным ( деструктивная интерференция ). Другими словами, окончательное измерение будет (все нули) тогда и только тогда, когда является постоянным, и даст некоторое другое состояние, если является сбалансированным.
Алгоритм Дойча является частным случаем общего алгоритма Дойча–Йожи, где n = 1 в . Нам нужно проверить условие . Это эквивалентно проверке (где — сложение по модулю 2, которое также можно рассматривать как квантовый вентиль XOR, реализованный как управляемый вентиль NOT ), если ноль, то константа, в противном случае константа не является.
Мы начинаем с двухкубитного состояния и применяем вентиль Адамара к каждому кубиту. Это дает
Нам дана квантовая реализация функции , которая отображается на . Применяя эту функцию к нашему текущему состоянию, получаем
Мы игнорируем последний бит и глобальную фазу и поэтому имеем состояние
Применяя к этому состоянию вентиль Адамара, мы имеем
если и только если мы измеряем и если и только если мы измеряем . Таким образом, мы с уверенностью знаем, является ли константой или сбалансированной.
Ниже приведен простой пример того, как алгоритм Дойча–Йожи может быть реализован на Python с использованием Qiskit , среды разработки программного обеспечения для квантовых вычислений с открытым исходным кодом от IBM. Мы пройдемся по каждой части кода шаг за шагом, чтобы показать, как он преобразует теорию в работающую квантовую схему.
из qiskit импорт QuantumCircuit , транспилирование из qiskit_aer импорт Aer
def create_constant_oracle ( n_qubits , output ): """ Создает «константный» оракул. Если `output` равен 0, оракул всегда возвращает 0. Если `output` равен 1, оракул всегда возвращает 1. Args: n_qubits (int): Количество входных кубитов. output (int): Постоянное выходное значение функции (0 или 1). Возвращает: QuantumCircuit: квантовая схема, реализующая константный оракул. """ oracle = QuantumCircuit ( n_qubits + 1 ) # Если оракул всегда должен выводить 1, мы инвертируем "выходной" кубит # с помощью X-вентиля (представьте его как вентиль НЕ на кубите). if output == 1 : oracle . x ( n_qubits ) обратный оракулdef create_balanced_oracle ( n_qubits ): """ Создает «сбалансированный» оракул. Половина входных битовых комбинаций выводит 0, а другая половина выводит 1. Для демонстрации эта функция реализует простую сбалансированную функцию, помещая X-вентили на первый кубит входа в качестве элемента управления, инвертируя выходной кубит для половины входов. Аргументы: n_qubits (int): Количество входных кубитов. Возвращает: QuantumCircuit: квантовая схема, реализующая сбалансированный оракул. """ oracle = QuantumCircuit ( n_qubits + 1 ) # Мы будем использовать простой шаблон: если первый кубит равен 1, инвертируем выход. # Это означает, что для половины возможных входов выход меняется. oracle . cx ( 0 , n_qubits ) обратный оракул
def deutsch_jozsa_circuit ( oracle , n_qubits ): """ Собирает полную квантовую схему Дойча-Йожи. Схема выполняет следующие шаги: 1. Запускает все «входные» кубиты в |0>. 2. Запускает «выходной» кубит в |1>. 3. Применяет вентили Адамара ко всем кубитам. 4. Применяет оракул. 5. Снова применяет вентили Адамара к входным кубитам. 6. Измеряет входные кубиты. Args: oracle (QuantumCircuit): Схема, кодирующая «загадочную» функцию f(x). n_qubits (int): Количество входных кубитов. Возвращает: QuantumCircuit: Полная схема Дойча-Йожи, готовая к запуску. """ # Общее количество n_qubits для ввода, плюс 1 для выходного кубита dj_circuit = QuantumCircuit ( n_qubits + 1 , n_qubits ) # 1. Входные кубиты уже установлены в |0>. # 2. Выходной кубит установлен в |1>. Мы достигаем этого с помощью X-вентиля. dj_circuit . x ( n_qubits ) # 3. Применить вентили Адамара ко всем кубитам (вход + выход). для кубита в диапазоне ( n_qubits + 1 ): dj_circuit . h ( qubit ) # 4. Добавить схему оракула. dj_circuit . compose ( oracle , inplace = True ) # 5. Применить вентили Адамара снова ТОЛЬКО к входным кубитам. для кубита в диапазоне ( n_qubits ): dj_circuit . h ( qubit ) # 6. Наконец, измерьте входные кубиты. для кубита в диапазоне ( n_qubits ): dj_circuit . measure ( qubit , qubit ) вернуть dj_circuit
def run_deutsch_jozsa_test ( n_qubits , oracle_type = 'constant' , constant_output = 0 ): """ Создает и запускает схему Дойча-Йожи для постоянного оракула или сбалансированного оракула, затем выводит результаты. Args: n_qubits (int): Количество входных кубитов. oracle_type (str): Указывает тип оракула, «константный» или «сбалансированный». constant_output (int): Если оракул константный, определяет, возвращает ли он 0 или 1. """ # Создать выбранный оракул if oracle_type == 'constant' : oracle = create_constant_oracle ( n_qubits , constant_output ) print ( f "Использование КОНСТАНТНОГО оракула, который всегда возвращает { constant_output } " ) else : oracle = create_balanced_oracle ( n_qubits ) print ( "Использование СБАЛАНСИРОВАННОГО оракула." ) # Создаем схему Дойча-Йожи dj_circ = deutsch_jozsa_circuit ( oracle , n_qubits ) # Нарисуйте схему для визуального отображения ( dj_circ . draw ()) # Используйте бэкэнд симулятора для запуска схемы simulator = Aer.get_backend ( ' aer_simulator ' ) transpiled_circ = transpile ( dj_circ , simulator ) job = simulator.run ( transpiled_circ , shots = 1 ) result = job.result ( ) counts = result.get_counts ( transpiled_circ ) print ( "Результаты измерений:" , counts ) # Интерпретировать измерение # Если все измеренные биты равны 0 (например, '000' для 3 кубитов), то # функция постоянна. В противном случае она сбалансирована. measured_result = max ( counts , key = counts . get ) # Наиболее вероятный результат , если measured_result == '0' * n_qubits : print ( "Вывод: f(x) КОНСТАНТА." ) else : print ( "Вывод: f(x) СБАЛАНСИРОВАНА." )
# Тест с 3 кубитами run_deutsch_jozsa_test ( n_qubits = 3 , oracle_type = 'constant' , constant_output = 0 )печать ( " \n " + "=" * 50 + " \n " )run_deutsch_jozsa_test ( n_qubits = 3 , oracle_type = 'balanced' )
Использование КОНСТАНТНОГО оракула, который всегда возвращает 0 ┌───┐┌───┐┌─┐ q_0: ┤ Ч ├┤ Ч ├┤М├────── ├───┤├───┤└╥┘┌─┐ q_1: ┤ Н ├┤ Н ├─╫─┤М├─── ├───┤├───┤ ║ └╥┘┌─┐q_2: ┤ Ч ├┤ Ч ├─╫──╫─┤М├ ├───┤├───┤ ║ ║ └╥┘q_3: ┤ Х ├┤ Ч ├─╫──╫──╫─ └───┘└───┘ ║ ║ ║с: 3/═══════════╩══╩══╩═ 0 1 2Результаты измерений: {'000': 1}Вывод: f(x) — ПОСТОЯННАЯ.===============================================Использование СБАЛАНСИРОВАННОГО оракула. ┌───┐ ┌───┐ ┌─┐q_0: ┤ Ч ├───────■──┤ Ч ├───┤М├ ├───┤┌───┐ │ └┬─┬┘ └╥┘q_1: ┤ H ├┤ H ├──┼───┤M├─────╫─ ├───┤├───┤ │ └╥┘ ┌─┐ ║q_2: ┤ H ├┤ H ├──┼────╫──┤M├─╫─ ├───┤├───┤┌─┴─┐ ║ └╥┘ ║q_3: ┤ X ├┤ H ├┤ X ├──╫───╫──╫─ └───┘└───┘└───┘ ║ ║ ║с: 3/═════════════════╩═══╩══╩═ 1 2 0Результаты измерения: {'001': 1}Вывод: f(x) СБАЛАНСИРОВАНА.
Мы используем основные элементы Qiskit:
QuantumCircuit
для создания квантовых схемAer
, transpile
и run
запустить нашу схему на классическом симулятореCNOT
вентиль ( cx
), который переворачивает выходной кубит, когда первый входной кубит равен 1.dj_circuit.h(qubit)
) ко всем кубитам. Напомним, что вентиль Адамара распределяет амплитуды «равномерно» между и , создавая суперпозиции.Мы запускаем схему с помощью встроенного в Aer aer_simulator. Поскольку алгоритму Deutsch–Jozsa требуется только одно выполнение (один набор выстрелов), чтобы со 100% уверенностью отличить константу от сбалансированной, запуск нескольких выстрелов всегда даст тот же результат.
Классически вам, возможно, придется «вызвать» функцию (f) (наш «таинственный» черный ящик) много раз — потенциально до раз — чтобы быть абсолютно уверенным, является ли она постоянной или сбалансированной. Однако квантовую версию этой проблемы можно решить всего одним вызовом оракула плюс несколькими дополнительными квантовыми вентилями. Хотя сам Дойч-Йожа считается скорее «учебным примером», чем практическим применением, он демонстрирует одну из ключевых идей квантовых алгоритмов: использование суперпозиции и интерференции для значительного сокращения количества требуемых вызовов функций.