Перейти до основного вмісту
Цей проєкт у бета-версії. Знайшов(-ла) помилку? Відкрити issue на GitHub. Є запитання чи ідея? Запитати в Discussions — будемо раді твоєму відгуку!
Яка якість перекладу на цій сторінці?

Алгоритм Шора

Для цього модуля Qiskit у класі студенти повинні мати робоче середовище Python із встановленими такими пакетами:

  • qiskit v2.1.0 або новіша версія
  • qiskit-ibm-runtime v0.40.1 або новіша версія
  • qiskit-aer v0.17.0 або новіша версія
  • qiskit.visualization
  • numpy
  • pylatexenc

Щоб налаштувати та встановити зазначені пакети, ознайомся з посібником Встановлення Qiskit. Щоб запускати завдання на реальних квантових комп'ютерах, студентам потрібно створити обліковий запис IBM Quantum®, виконавши кроки з посібника Налаштування облікового запису IBM Cloud.

Цей модуль було протестовано та використано три секунди часу QPU. Це лише оцінка. Фактичне використання може відрізнятися.

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"numpy": "numpy", "qiskit": "qiskit", "qiskit_ibm_runtime": "qiskit-ibm-runtime"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
# Uncomment and modify this line as needed to install dependencies
#!pip install 'qiskit>=2.1.0' 'qiskit-ibm-runtime>=0.40.1' 'qiskit-aer>=0.17.0' 'numpy' 'pylatexenc'

Вступ​

На початку 1990-х років навколо потенціалу квантових комп'ютерів у розв'язанні задач, важких для класичних комп'ютерів, панувало дедалі більше ентузіазму. Кілька талановитих учених у галузі комп'ютерних наук розробили алгоритми, що демонстрували потужність квантових обчислень для деяких нішевих, штучних задач, але ніхто ще не знайшов «вбивчого застосування» квантових обчислень, яке точно революціонізувало б галузь. Так тривало аж до 1994 року, коли Пітер Шор запропонував те, що нині зветься алгоритмом Шора для факторизації великих чисел.

На той час було добре відомо, що знаходження простих множників великого числа — надзвичайно складне завдання для класичного комп'ютера. Більше того, саме на цій складності ґрунтувалися протоколи інтернет-безпеки. Шор знайшов спосіб знаходити ці множники експоненційно ефективніше, перекладаючи деякі найскладніші кроки на теоретичний майбутній квантовий комп'ютер.

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

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

Задача факторизації​

Мета задачі факторизації — знайти прості множники числа NN. Для деяких чисел NN це доволі просто. Наприклад, якщо NN парне, одним із його простих множників буде 2. Якщо NN є степенем простого числа, тобто N=pkN=p^k для деякого простого числа pp, знайти pp також нескладно: достатньо наблизити kk-й корінь із NN і пошукати поблизу прості числа, які могли б бути pp.

Класичні комп'ютери зазнають труднощів, коли NN непарне та не є степенем простого числа. Саме цей випадок і розв'язує алгоритм Шора. Алгоритм знаходить два множники pp та qq такі, що N=pqN=pq. Його можна застосовувати рекурсивно, поки всі множники не стануть простими. У наступних розділах ми побачимо, як підходити до цієї задачі.

Зв'язок із кібербезпекою​

Чимало криптографічних схем побудовано на тому, що факторизація великих чисел є складною задачею, зокрема одна з найпоширеніших сьогодні — RSA. В RSA відкритий ключ створюється множенням двох великих простих чисел, що дає N=p⋅qN = p\cdot q. Потім будь-хто може використовувати цей відкритий ключ для шифрування даних. Але розшифрувати їх може лише той, хто знає закритий ключ — pp та qq.

Якби NN легко факторизувалося, будь-хто міг би визначити pp та qq і зламати шифрування. Але це не так. Це загальновідомо складна задача. Зокрема, прості множники числа RSA1024 — довжиною 1024 двійкові цифри і 309 десяткових цифр — досі не знайдені, хоча за їхню факторизацію ще з 1991 року пропонується приз у розмірі $100 000.

Рішення Шора​

У 1994 році Пітер Шор зрозумів, що квантовий комп'ютер здатний факторизувати велике число експоненційно ефективніше, ніж класичний. Його ідея спиралася на зв'язок між задачею факторизації та модульною арифметикою. Ми коротко розглянемо основи модульної арифметики, а потім побачимо, як її застосувати для факторизації NN.

Модульна арифметика​

Модульна арифметика — це циклічна система підрахунку: лічба починається звичайним чином — цілими числами 0, 1, 2 тощо, — але після періоду NN лічба починається спочатку. Розглянемо це на прикладі. Нехай наш період дорівнює 5. Тоді там, де в звичайному підрахунку ми дійшли б до 5, ми натомість починаємо знову з 0:

0,1,2,3,4,0,1,2,3,4,0,1,2,...0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, ...

Це тому, що у світі «за модулем 5» число 5 еквівалентне 0. Кажуть, що 5 mod 5 =05\bmod 5 \ = 0. Насправді всі кратні 5 будуть еквівалентні 0 mod 50\bmod 5.

Перевір себе​

Використай модульну арифметику для розв'язання наступної задачі:

Ти вирушаєш у довгу трансконтинентальну подорож поїздом о 8:00 ранку. Поїздка триває 60 годин. Котра година буде, коли ти прибудеш?

Відповідь

Період дорівнює 24, оскільки в добі 24 години. Тож задачу можна записати у вигляді модульної арифметики:

(8+60)mod(24)=20(8+60)\text{mod}(24) = 20

Отже, ти прибудеш до пункту призначення о 20:00.

ZN\mathbb{Z}_N та ZN∗\mathbb{Z}_N^*​

Часто зручно ввести дві множини: ZN\mathbb{Z}_N та ZN∗\mathbb{Z}_N^*. ZN\mathbb{Z}_N — це просто множина чисел, що існують у світі «за модулем NN». Наприклад, коли ми рахували за модулем 5, множина мала вигляд Z5={0,1,2,3,4}\mathbb{Z}_5=\{0,1,2,3,4\}. Ще один приклад: Z15={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14}\mathbb{Z}_{15} = \{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14\}. Над елементами ZN\mathbb{Z}_N можна виконувати додавання та множення (за модулем NN), і результат кожної із цих операцій також є елементом ZN\mathbb{Z}_N, що робить ZN\mathbb{Z}_N математичним об'єктом, який називається кільцем.

Для алгоритму Шора особливий інтерес становить підмножина ZN\mathbb{Z}_N — множина чисел із ZN\mathbb{Z}_N, для яких найбільший спільний дільник кожного елемента та NN дорівнює 1, тобто кожен елемент є «взаємно простим» із NN. Якщо взяти цю множину разом із операцією модульного множення, отримаємо ще один математичний об'єкт — групу. Цю групу позначають ZN∗\mathbb{Z}_N^*. Виявляється, що в ZN∗\mathbb{Z}_N^* (і в скінченних групах загалом), якщо взяти будь-який елемент a∈ZN∗a \in \mathbb{Z}_N^* і послідовно множити aa на себе, ми завжди врешті-решт отримаємо число 11. Мінімальна кількість разів, яку потрібно помножити aa на себе, щоб отримати 11, називається порядком aa. Цей факт буде дуже важливим для нашого обговорення факторизації чисел нижче.

Перевір себе​

Чому дорівнює Z15∗\mathbb{Z}_{15}^*?

Відповідь

Z15∗={1,2,4,7,8,11,13,14}\mathbb{Z}_{15}^* = \{1,2,4,7,8,11,13,14\}

Ми виключили такі числа:

3:GCD(3,15)=35:GCD(5,15)=56:GCD(6,15)=39:GCD(9,15)=310:GCD(10,15)=512:GCD(12,15)=3\begin{aligned} 3: GCD(3,15)=3 \\ 5: GCD(5,15)=5 \\ 6: GCD(6,15)=3 \\ 9: GCD(9,15)=3 \\ 10: GCD(10,15)=5 \\ 12: GCD(12,15)=3 \\ \end{aligned}

Яким є порядок кожного з елементів у Z15∗\mathbb{Z}_{15}^*?

Відповідь

Порядок rr — це найменше число таке, що armod(15)=1a^r\text{mod}(15)=1 для кожного елемента aa.

11mod(15)=1,r=124mod(15)=1,r=442mod(15)=1,r=274mod(15)=1,r=484mod(15)=1,r=4112mod(15)=1,r=2134mod(15)=1,r=4142mod(15)=1,r=2\begin{aligned} 1^1\text{mod}(15) = 1, r=1 \\ 2^4\text{mod}(15) = 1, r=4 \\ 4^2\text{mod}(15) = 1, r=2 \\ 7^4\text{mod}(15) = 1, r=4 \\ 8^4\text{mod}(15) = 1, r=4 \\ 11^2\text{mod}(15) = 1, r=2 \\ 13^4\text{mod}(15) = 1, r=4 \\ 14^2\text{mod}(15) = 1, r=2 \\ \end{aligned}

Зауваж, що хоча нам вдалося знайти порядки чисел у Z15∗\mathbb{Z}_{15}^*, у загальному випадку для більших NN це НЕ легке завдання. Саме в цьому суть задачі факторизації і причина, чому нам потрібен квантовий комп'ютер. Ми побачимо чому, коли пройдемо решту ноутбука.

Застосування модульної арифметики до задачі факторизації​

Ключ до знаходження множників pp та qq таких, що N=pqN=pq, полягає у пошуку деякого іншого цілого числа xx такого, що

x2≡1 mod Nx^2 \equiv 1 \bmod N та x≢±1 mod N.x \not\equiv \pm 1 \bmod N.

Як знаходження xx допомагає нам знайти множники pp та qq? Розберемо аргумент. Оскільки x2≡1 mod Nx^2 \equiv 1 \bmod N, це означає, що x2−1≡0 mod Nx^2 - 1 \equiv 0 \bmod N . Іншими словами, x2−1x^2 - 1 є кратним NN. Отже, для деякого цілого числа ll:

x2−1=lNx^2 - 1 = l N

Розкладемо x2−1x^2 - 1 на множники:

(x+1)(x−1)=lN(x+1)(x-1) = l N

З початкових умов знаємо, що x≢±1 mod Nx \not\equiv \pm 1 \bmod N, тож ані x+1x+1, ані x−1x-1 не діляться націло на NN. Отже, два множники NN — pp та qq — мають ділити x−1x-1 та x+1x+1. Або pp є множником x−1x-1, а qq — x+1x+1, або навпаки. Тому якщо обчислити найбільші спільні дільники (НСД) між NN та обома x−1x-1 і x+1x+1, це дасть нам множники pp та qq. Обчислення НСД двох чисел — класично проста задача, яку можна розв'язати, наприклад, за допомогою алгоритму Евкліда.

Перевір себе​

Кожен крок наведеної вище логіки може бути нелегким для розуміння, тому спробуй пройти через нього на прикладі. Використай N=15N=15 та x=11x=11. Спочатку перевір, що x2≡1mod(N)x^2 \equiv 1 \text{mod}(N) та x≢±1 mod Nx \not\equiv \pm 1 \bmod N. Потім продовжуй перевіряти кожен крок. Нарешті, обчисли GCD(11±1,15)\text{GCD}(11\pm1,15) і переконайся, що ці значення є множниками 1515.

Відповідь

112=12111^2 = 121, що дорівнює 15∗8+115*8 + 1, тож 112 mod 15=111^2\bmod 15 = 1. ✓\checkmark

11−1=10 11 - 1 = 10, що не еквівалентно 0 mod 150\bmod 15. ✓\checkmark

11+1=12 11 + 1 = 12, що не еквівалентно 0 mod 150\bmod 15. ✓\checkmark

Тепер ми знаємо, що (x+1)(x−1)=lN(x+1)(x-1) = l N для деякого цілого числа ll. Це підтверджується, коли підставляємо xx та NN: (12)(10)=l15(12)(10) = l 15 при l=8l = 8. ✓\checkmark

Тепер потрібно обчислити GCD(12,15)\text{GCD}(12,15) та GCD(10,15)\text{GCD}(10,15).

GCD(12,15)=3GCD(10,15)=5\begin{aligned} \text{GCD}(12,15) = 3 \\ \text{GCD}(10,15) = 5 \end{aligned}

Отже, ми знайшли множники числа 1515!

Алгоритм​

Тепер, коли ми побачили, як знаходження цілого числа xx такого, що x2≡1 mod Nx^2 \equiv 1\bmod N, допомагає факторизувати NN, можемо розглянути алгоритм Шора. Він, по суті, зводиться до знаходження xx:

  1. Вибери випадкове ціле число Вибери випадкове ціле число aa таке, що 1<a<N1 < a < N.
  • Обчисли GCD(a,N)\text{GCD}(a, N) класично.
    • Якщо GCD(a,N)>1\text{GCD}(a, N) > 1, множник уже знайдено. Зупинись.
    • Інакше продовжуй.
  1. Знайди порядок rr числа aa за модулем NN Знайди найменше додатне ціле число rr, що задовольняє ar≡1(modN)a^r \equiv 1 \pmod N.

  2. Перевір, чи порядок парний

  • Якщо rr непарне, повернись до кроку 1 і вибери нове aa.

  • Якщо rr парне, переходь до кроку 4.

  1. Обчисли x=ar/2 mod Nx = a^{r/2} \bmod N
  • Перевір, що x≢1(modN)x \not\equiv 1 \pmod N та x≢−1(modN)x \not\equiv -1 \pmod N.

    • Якщо x≡±1(modN)x \equiv \pm 1 \pmod N, повернись до кроку 1 і вибери нове aa.
  • Інакше обчисли НСД для отримання множників:

p=GCD(x−1,N),q=GCD(x+1,N)p = \text{GCD}(x-1, N), \quad q = \text{GCD}(x+1, N)

Це будуть нетривіальні множники NN.

  1. Рекурсивно факторизуй за необхідності
  • Якщо pp та/або qq не є простими, рекурсивно застосуй алгоритм для їхньої повної факторизації.

  • Як тільки всі множники стануть простими, факторизацію завершено.

Виходячи з цієї процедури, може бути незрозуміло, навіщо для виконання цього завдання потрібен квантовий комп'ютер. Він необхідний тому, що крок 2 — знаходження порядку aa за модулем NN — є класично дуже складною задачею. Складність масштабується експоненційно відносно числа NN. Але за допомогою квантового комп'ютера ми можемо скористатися Квантовою оцінкою фази для її розв'язання. Крок 4 — знаходження НСД двох цілих чисел — насправді класично досить просте завдання. Тож єдиним кроком, який дійсно потребує потужності квантового комп'ютера, є крок пошуку порядку. Кажуть, що задача факторизації «зводиться» до задачі пошуку порядку.

Найскладніша частина: пошук порядку​

Тепер розглянемо, як можна використати квантовий комп'ютер для пошуку порядку. Спочатку уточнимо, що ми маємо на увазі під «порядком». Звісно, я вже пояснював математичний зміст порядку: це перше ненульове ціле число rr таке, що ar=1(modN)a^r = 1 \pmod N. Але спробуємо набути трохи більше інтуїції щодо цього поняття.

Для достатньо малого NN можна просто визначити порядок, послідовно обчислюючи кожний степінь aa, беручи залишок від ділення на NN, і зупиняючись, коли знайдено степінь rr такий, що ar=1mod(N)a^r = 1 \text{mod}(N). Саме це ми й робили у прикладі N=15N=15 вище. Подивімось на графіки цих модульних степенів для кількох значень aa та NN:

Значення a у степені k за модулем N залежно від степеня k, де a=2 та N=15. Видно, що зі збільшенням k виникає повторювана закономірність, яка показує, що a^k за модулем N є періодичним по k.

Значення a у степені k за модулем N залежно від степеня k, де a=5 та N=21. Видно, що зі збільшенням k виникає повторювана закономірність, яка показує, що a^k за модулем N є періодичним по k.

Помітив щось? Це — періодичні функції! А порядок rr — це той самий період! Отже, пошук порядку еквівалентний пошуку періоду.

Квантові комп'ютери дуже добре підходять для знаходження періоду функцій. Для цього ми можемо використати алгоритмічну підпрограму, що зветься Квантовою оцінкою фази. Ми обговорили QPE та її зв'язок із Квантовим перетворенням Фур'є у попередньому модулі. Для детального повторення звернись до модуля про QFT або до уроку Джона Ватруса з Квантової оцінки фази у його курсі з квантових алгоритмів. Ось стисло суть процедури:

У Квантовій оцінці фази (QPE) ми починаємо з унітарного оператора UU та власного стану цього унітарного оператора ∣ψ⟩|\psi\rangle. Потім використовуємо QPE для наближеного обчислення відповідного власного значення, яке, оскільки оператор є унітарним, матиме вигляд e2πiθe^{2\pi i \theta}. Таким чином, знаходження власного значення еквівалентне знаходженню значення θ\theta у цій періодичній функції. Схема виглядає так:

Діаграма процедури Квантової оцінки фази. Верхні m контрольних кубітів підготовлено в суперпозиції за допомогою вентиля Адамара, потім до нижніх кубітів, що знаходяться у власному стані унітарного, застосовуються керовані унітарні вентилі. Нарешті, до верхніх кубітів застосовується обернене квантове перетворення Фур&#39;є, і вони вимірюються.

де кількість контрольних кубітів (верхні mm кубітів на малюнку вище) визначає точність апроксимації.

В алгоритмі Шора ми застосовуємо QPE до унітарного оператора MaM_a:

Ma∣y⟩≡∣aymod  N⟩. M_a|y\rangle \equiv |ay \mod N \rangle .

Тут ∣y⟩|y\rangle позначає стан обчислювального базису багатокубітного регістра, де двійкове значення кубітів відповідає цілому числу yy. Наприклад, якщо N=15N=15 та y=2y = 2, то ∣y⟩|y\rangle представлено чотирикубітним базисним станом ∣0010⟩|0010\rangle, оскільки чотири кубіти потрібні для кодування чисел до 15. (Якщо ця концепція незнайома, звернись до вступного модуля Qiskit у класі для повторення двійкового кодування квантових станів.)

Тепер нам потрібно знайти власний стан цього унітарного. Якщо ми починаємо у стані ∣1⟩|1\rangle, то кожне наступне застосування UU множить стан нашого регістра на a(modN)a \pmod N, і після rr застосувань ми знову повернемося до стану ∣1⟩|1\rangle. Наприклад, при a=3a = 3 та N=35N = 35:

M3∣1⟩=∣3⟩M32∣1⟩=∣9⟩M33∣1⟩=∣27⟩⋮M3(r−1)∣1⟩=∣12⟩M3r∣1⟩=∣1⟩\begin{aligned} M_3|1\rangle &= |3\rangle & \\ M_3^2|1\rangle &= |9\rangle \\ M_3^3|1\rangle &= |27\rangle \\ & \vdots \\ M_3^{(r-1)}|1\rangle &= |12\rangle \\ M_3^r|1\rangle &= |1\rangle \end{aligned}

Тож суперпозиції станів із цього циклу (∣ψj⟩|\psi_j\rangle) вигляду:

∣ψj⟩=1r∑k=0r−1e2πijkr∣ak⟩|\psi_j\rangle = \tfrac{1}{\sqrt{r}}\sum_{k=0}^{r-1}{e^{\frac{2 \pi i j k}{r}} |a^k \rangle}

є власними станами MaM_a. (Власних станів більше, ніж наведено вище. Але нас цікавлять лише ті, що мають зазначений вигляд.)

Перевір себе​

Знайди власний стан унітарного оператора, що відповідає a=2a=2 та N=15N = 15.

Відповідь
M2∣1⟩=∣2⟩M22∣1⟩=∣4⟩M23∣1⟩=∣8⟩M24∣1⟩=∣1⟩\begin{aligned} M_2|1\rangle &= |2\rangle & \\ M_2^2|1\rangle &= |4\rangle \\ M_2^3|1\rangle &= |8\rangle \\ M_2^4|1\rangle &= |1\rangle \\ \end{aligned}

Отже, порядок r=4r=4. Власні стани, що нас цікавлять, будуть рівними суперпозиціями всіх станів, через які пройшов цикл вище, з різними фазами:

∣ψ0⟩=12(∣1⟩+∣2⟩+∣4⟩+∣8⟩)∣ψ1⟩=12(e2πi04∣1⟩+e2πi14∣2⟩+e2πi24∣4⟩+e2πi34∣8⟩)=12(∣1⟩+i∣2⟩−∣4⟩−i∣8⟩)∣ψ2⟩=12(e2πi04∣1⟩+e2πi24∣2⟩+e2πi44∣4⟩+e2πi64∣8⟩)=12(∣1⟩−∣2⟩+∣4⟩−∣8⟩)∣ψ3⟩=12(e2πi04∣1⟩+e2πi34∣2⟩+e2πi64∣4⟩+e2πi94∣8⟩)=12(∣1⟩−i∣2⟩−∣4⟩+i∣8⟩)\begin{aligned} |\psi_0\rangle &= \frac{1}{2}(|1\rangle+|2\rangle+|4\rangle+|8\rangle) \\ |\psi_1\rangle &= \frac{1}{2}(e^{2 \pi i \frac{0}{4}}|1\rangle+e^{2 \pi i \frac{1}{4}}|2\rangle+e^{2 \pi i \frac{2}{4}}|4\rangle+e^{2 \pi i \frac{3}{4}}|8\rangle) \\ &= \frac{1}{2}(|1\rangle+i|2\rangle-|4\rangle-i|8\rangle) \\ |\psi_2\rangle &= \frac{1}{2}(e^{2 \pi i \frac{0}{4}}|1\rangle+e^{2 \pi i \frac{2}{4}}|2\rangle+e^{2 \pi i \frac{4}{4}}|4\rangle+e^{2 \pi i \frac{6}{4}}|8\rangle) \\ &= \frac{1}{2}(|1\rangle-|2\rangle+|4\rangle-|8\rangle) \\ |\psi_3\rangle &= \frac{1}{2}(e^{2 \pi i \frac{0}{4}}|1\rangle+e^{2 \pi i \frac{3}{4}}|2\rangle+e^{2 \pi i \frac{6}{4}}|4\rangle+e^{2 \pi i \frac{9}{4}}|8\rangle) \\ &= \frac{1}{2}(|1\rangle-i|2\rangle-|4\rangle+i|8\rangle) \\ \end{aligned}

Припустімо, що ми змогли ініціалізувати стан нашого кубіта у один із цих власних станів (спойлер — ні, або принаймні не легко. Незабаром пояснимо чому і що натомість можна зробити). Тоді ми могли б використати QPE для оцінки відповідного власного значення ωj=e2πiθj\omega_j = e^{2 \pi i \theta_j}, де θj=jr\theta_j = \frac{j}{r}. Після цього порядок rr можна визначити з простого рівняння:

r=jθj.r = \frac{j}{\theta_j}.

Але пам'ятай: QPE оцінює θj\theta_j — вона не дає точного значення. Нам потрібно, щоб оцінка була достатньо точною для розрізнення між rr та r+1r+1. Чим більше контрольних кубітів mm, тим точнішою буде оцінка. У задачах наприкінці уроку тобі запропонують визначити мінімальне mm, необхідне для факторизації числа NN.

Тепер нам потрібно вирішити одну проблему. Усе наведене вище пояснення того, як знайти rr, починається з підготовки власного стану ∣ψj⟩=1r∑k=0r−1e2πijkr∣ak⟩|\psi_j\rangle = \tfrac{1}{\sqrt{r}}\sum_{k=0}^{r-1}{e^{\frac{2 \pi i j k}{r}} |a^k \rangle}. Але ми не знаємо, як це зробити, не знаючи заздалегідь rr. Виходить замкнене коло. Нам потрібен спосіб оцінити власне значення без ініціалізації власного стану.

Замість того щоб починати з власного стану MaM_a, ми можемо підготувати початковий стан у вигляді nn-кубітного стану, що відповідає ∣1⟩|1\rangle у двійковому записі (тобто ∣000...01⟩|000...01\rangle). Хоча сам цей стан явно не є власним станом MaM_a, він є суперпозицією всіх власних станів ∣ψk⟩|\psi_k\rangle:

∣1⟩=1r∑k=0r−1∣ψk⟩|1\rangle = \frac{1}{\sqrt{r}} \sum\limits_{k=0}^{r-1}{|\psi_k\rangle}

Перевір себе​

Переконайся, що ∣1⟩|1\rangle еквівалентне суперпозиції власних станів, знайдених тобою для N=15N=15 та a=2a=2 у попередньому запитанні для самоперевірки.

Відповідь

Чотири власні стани мали вигляд:

∣ψ0⟩=12(∣1⟩+∣2⟩+∣4⟩+∣8⟩)∣ψ1⟩=12(∣1⟩+i∣2⟩−∣4⟩−i∣8⟩)∣ψ2⟩=12(∣1⟩−∣2⟩+∣4⟩−∣8⟩)∣ψ3⟩=12(∣1⟩−i∣2⟩−∣4⟩+i∣8⟩)\begin{aligned} |\psi_0\rangle &= \frac{1}{2}(|1\rangle+|2\rangle+|4\rangle+|8\rangle) \\ |\psi_1\rangle &= \frac{1}{2}(|1\rangle+i|2\rangle-|4\rangle-i|8\rangle) \\ |\psi_2\rangle &= \frac{1}{2}(|1\rangle-|2\rangle+|4\rangle-|8\rangle) \\ |\psi_3\rangle &= \frac{1}{2}(|1\rangle-i|2\rangle-|4\rangle+i|8\rangle) \\ \end{aligned}

Тоді:

1r∑k=0r−1∣ψk⟩=12(∣ψ0⟩+∣ψ1⟩+∣ψ2⟩+∣ψ3⟩)=14(∣1⟩+∣2⟩+∣4⟩+∣8⟩+∣1⟩+i∣2⟩−∣4⟩−i∣8⟩+∣1⟩−∣2⟩+∣4⟩−∣8⟩+∣1⟩−i∣2⟩−∣4⟩+i∣8⟩)=14(4∣1⟩)=∣1⟩\begin{aligned} \frac{1}{\sqrt{r}} \sum\limits_{k=0}^{r-1}{|\psi_k\rangle} &= \frac{1}{2}(|\psi_0\rangle + |\psi_1\rangle + |\psi_2\rangle + |\psi_3\rangle ) \\ &= \frac{1}{4}(|1\rangle+|2\rangle+|4\rangle+|8\rangle+|1\rangle+i|2\rangle-|4\rangle-i|8\rangle+|1\rangle-|2\rangle+|4\rangle-|8\rangle + |1\rangle-i|2\rangle-|4\rangle+i|8\rangle) \\ &= \frac{1}{4}(4|1\rangle) = |1\rangle \end{aligned}

Як це допомагає знайти порядок rr? Оскільки початковий стан є суперпозицією всіх власних станів зазначеного вище вигляду, алгоритм QPE одночасно оцінює кожне із значень θk\theta_k, що відповідають цим власним станам. Тому вимірювання mm контрольних кубітів наприкінці дасть наближення до значення k/rk/r, де k∈{0,1,2,...,r−1}k \in \{0,1,2,...,r-1\} — одне з власних значень, вибране випадковим чином. Якщо повторити цю схему кілька разів і отримати кілька вибірок із різними значеннями kk, ми швидко зможемо визначити rr.

Реалізація у Qiskit​

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

Ми запустимо алгоритм, використовуючи наш стандартний фреймворк для розв'язання квантових задач — фреймворк Qiskit patterns. Він складається з чотирьох кроків:

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

  2. Оптимізація схеми для запуску на квантовому обладнанні

  3. Виконання схеми на квантовому комп'ютері

  4. Постобробка вимірювань

1. Відображення​

Давай факторизуємо N=15N=15, вибравши a=2a=2 як взаємно просте ціле число.

Спочатку нам потрібно побудувати схему, яка реалізує унітарний оператор модульного множення MaM_a. Насправді це найскладніша частина всієї реалізації і може бути дуже обчислювально витратною залежно від підходу. Тут ми трохи схитруємо: ми знаємо, що починаємо зі стану ∣1⟩|1\rangle, і з попереднього запитання для самоперевірки:

M2∣1⟩=∣2⟩M2∣2⟩=∣4⟩M2∣4⟩=∣8⟩M2∣8⟩=∣1⟩\begin{aligned} M_2|1\rangle &= |2\rangle & \\ M_2|2\rangle &= |4\rangle \\ M_2|4\rangle &= |8\rangle \\ M_2|8\rangle &= |1\rangle \\ \end{aligned}

Тому ми побудуємо унітарний оператор, що виконує правильні дії над цими чотирма станами, залишаючи всі інші стани незмінними. Це й є «шахрайство», оскільки ми використовуємо наше знання порядку 2 mod 152\bmod 15 для спрощення унітарного. Якби ми справді намагалися факторизувати число, множники якого нам невідомі, ми б не могли цього зробити.

Перевір себе​

Знаючи, як оператор M2M_2 перетворює стани вище, побудуй оператор із серії вентилів SWAP, що обмінюють стани двох кубітів. (Підказка: запис кожного стану ∣i⟩|i\rangle у двійковій формі допоможе.)

Відповідь

Перепишемо дію M2M_2 на стани у двійковому форматі:

M2∣0001⟩=∣0010⟩M2∣0010⟩=∣0100⟩M2∣0100⟩=∣1000⟩M2∣1000⟩=∣0001⟩\begin{aligned} M_2|0001\rangle &= |0010\rangle \\ M_2|0010\rangle &= |0100\rangle \\ M_2|0100\rangle &= |1000\rangle \\ M_2|1000\rangle &= |0001\rangle \\ \end{aligned}

Кожну з цих дій можна виконати простим вентилем SWAP. M2∣0001⟩M_2|0001\rangle досягається обміном станів кубітів 00 та 11. M2∣0010⟩M_2|0010\rangle — обміном станів кубітів 11 та 22. І так далі. Отже, матрицю M2M_2 можна розкласти на таку послідовність вентилів SWAP:

M2=SWAP(0,1)SWAP(1,2)SWAP(2,3)M_2 = SWAP(0,1)SWAP(1,2)SWAP(2,3)

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

M2∣0001⟩=SWAP(0,1)SWAP(1,2)SWAP(2,3)∣0001⟩=SWAP(0,1)SWAP(1,2)∣0001⟩=SWAP(0,1)∣0001⟩=∣0010⟩✓M2∣0010⟩=SWAP(0,1)SWAP(1,2)SWAP(2,3)∣0010⟩=SWAP(0,1)SWAP(1,2)∣0010⟩=SWAP(0,1)∣0100⟩=∣0100⟩✓M2∣0100⟩=SWAP(0,1)SWAP(1,2)SWAP(2,3)∣0100⟩=SWAP(0,1)SWAP(1,2)∣1000⟩=SWAP(0,1)∣1000⟩=∣1000⟩✓M2∣1000⟩=SWAP(0,1)SWAP(1,2)SWAP(2,3)∣1000⟩=SWAP(0,1)SWAP(1,2)∣0100⟩=SWAP(0,1)∣0010⟩=∣0001⟩✓\begin{aligned} M_2|0001\rangle &= SWAP(0,1)SWAP(1,2)SWAP(2,3)|0001\rangle \\ &= SWAP(0,1)SWAP(1,2)|0001\rangle \\ &= SWAP(0,1)|0001\rangle \\ &=|0010\rangle \checkmark \\ M_2|0010\rangle &= SWAP(0,1)SWAP(1,2)SWAP(2,3)|0010\rangle \\ &= SWAP(0,1)SWAP(1,2)|0010\rangle \\ &= SWAP(0,1)|0100\rangle \\ &=|0100\rangle \checkmark \\ M_2|0100\rangle &= SWAP(0,1)SWAP(1,2)SWAP(2,3)|0100\rangle \\ &= SWAP(0,1)SWAP(1,2)|1000\rangle \\ &= SWAP(0,1)|1000\rangle \\ &=|1000\rangle \checkmark \\ M_2|1000\rangle &= SWAP(0,1)SWAP(1,2)SWAP(2,3)|1000\rangle \\ &= SWAP(0,1)SWAP(1,2)|0100\rangle \\ &= SWAP(0,1)|0010\rangle \\ &=|0001\rangle \checkmark \\ \end{aligned}

Тепер можна закодувати схему, еквівалентну цьому оператору, у Qiskit.

Спочатку імпортуємо необхідні пакети:

# Import necessary packages

import numpy as np
from fractions import Fraction
from math import floor, gcd, log

from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.circuit.library import QFTGate
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.visualization import plot_histogram

from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import SamplerV2 as Sampler

Потім створимо оператор M2M_2:

def M2mod15():
"""
M2 (mod 15)
"""
b = 2
U = QuantumCircuit(4)

U.swap(2, 3)
U.swap(1, 2)
U.swap(0, 1)

U = U.to_gate()
U.name = f"M_{b}"

return U
# Get the M2 operator
M2 = M2mod15()

# Add it to a circuit and plot
circ = QuantumCircuit(4)
circ.compose(M2, inplace=True)
circ.decompose(reps=2).draw(output="mpl", fold=-1)

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

Алгоритм QPE використовує керований вентиль UU. Тому тепер, коли ми маємо схему M2M_2, нам потрібно зробити її керованою-M2M_2 схемою:

def controlled_M2mod15():
"""
Controlled M2 (mod 15)
"""
b = 2
U = QuantumCircuit(4)

U.swap(2, 3)
U.swap(1, 2)
U.swap(0, 1)

U = U.to_gate()
U.name = f"M_{b}"
c_U = U.control()

return c_U
# Get the controlled-M2 operator
controlled_M2 = controlled_M2mod15()

# Add it to a circuit and plot
circ = QuantumCircuit(5)
circ.compose(controlled_M2, inplace=True)
circ.decompose(reps=1).draw(output="mpl", fold=-1)

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

Тепер ми маємо наш керований вентиль UU. Але для запуску алгоритму Квантової оцінки фази нам знадобляться керований-U2U^2, керований-U4U^4 аж до керованого-U2m−1U^{2^{m-1}}, де mm — кількість кубітів, що використовуються для оцінки фази. Що більше кубітів, то точнішою буде оцінка фази. Для нашої процедури оцінки фази ми використаємо m=8m=8 контрольних кубітів. Отже, нам потрібно:

Ma2k∣y⟩≡∣a2ky mod N⟩M_{a^{2^k}}|y\rangle \equiv |a^{2^k} y \bmod N \rangle

де індекс kk з 0≤k≤m−1=70 \le k \le m-1 = 7 відповідає контрольному кубіту. Обчислимо a2k mod Na^{2^k}\bmod N для кожного значення kk:

def a2kmodN(a, k, N):
"""Compute a^{2^k} (mod N) by repeated squaring"""
for _ in range(k):
a = int(np.mod(a**2, N))
return a
k_list = range(8)
b_list = [a2kmodN(2, k, 15) for k in k_list]

print(b_list)
[2, 4, 1, 1, 1, 1, 1, 1]

Оскільки a2k mod N=1a^{2^k} \bmod N = 1 для k≥2k \ge 2, усі відповідні оператори (M8M_8 і вище) еквівалентні тотожному оператору. Тому нам потрібно побудувати лише ще одну матрицю — M4M_4.

Примітка: Це спрощення працює тут лише тому, що порядок 2 mod 152 \bmod 15 дорівнює 44. Щойно k=2k=2 (тобто 2k=42^k = 4), кожний наступний степінь оператора є тотожним. У загальному випадку для більших NN або інших значень aa пропустити побудову вищих степенів не вийде. Саме тому це вважається іграшковим прикладом: малі числа допускають скорочення, що не працюватимуть для більших.

def M4mod15():
"""
M4 (mod 15)
"""
b = 4
U = QuantumCircuit(4)

U.swap(1, 3)
U.swap(0, 2)

U = U.to_gate()
U.name = f"M_{b}"

return U
# Get the M4 operator
M4 = M4mod15()

# Add it to a circuit and plot
circ = QuantumCircuit(4)
circ.compose(M4, inplace=True)
circ.decompose(reps=2).draw(output="mpl", fold=-1)

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

І, як і раніше, зробимо його керованим-M4M_4 оператором:

def controlled_M4mod15():
"""
Controlled M4 (mod 15)
"""
b = 4
U = QuantumCircuit(4)

U.swap(1, 3)
U.swap(0, 2)

U = U.to_gate()
U.name = f"M_{b}"
c_U = U.control()

return c_U
# Get the controlled-M4 operator
controlled_M4 = controlled_M4mod15()

# Add it to a circuit and plot
circ = QuantumCircuit(5)
circ.compose(controlled_M4, inplace=True)
circ.decompose(reps=1).draw(output="mpl", fold=-1)

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

Тепер можна зібрати все докупи для знаходження порядку 2 mod 152\bmod 15 за допомогою квантової схеми, використовуючи оцінку фази:

# Order finding problem for N = 15 with a = 2
N = 15
a = 2

# Number of qubits
num_target = floor(log(N - 1, 2)) + 1 # for modular exponentiation operators
num_control = 2 * num_target # for enough precision of estimation

# List of M_b operators in order
k_list = range(num_control)
b_list = [a2kmodN(2, k, 15) for k in k_list]

# Initialize the circuit
control = QuantumRegister(num_control, name="C")
target = QuantumRegister(num_target, name="T")
output = ClassicalRegister(num_control, name="out")
circuit = QuantumCircuit(control, target, output)

# Initialize the target register to the state |1>
circuit.x(num_control)

# Add the Hadamard gates and controlled versions of the
# multiplication gates
for k, qubit in enumerate(control):
circuit.h(k)
b = b_list[k]
if b == 2:
circuit.compose(
M2mod15().control(), qubits=[qubit] + list(target), inplace=True
)
elif b == 4:
circuit.compose(
M4mod15().control(), qubits=[qubit] + list(target), inplace=True
)
else:
continue # M1 is the identity operator

# Apply the inverse QFT to the control register
circuit.compose(QFTGate(num_control).inverse(), qubits=control, inplace=True)

# Measure the control register
circuit.measure(control, output)

circuit.draw("mpl", fold=-1)

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

2. Оптимізація​

Після того як ми відобразили нашу схему, наступний крок — оптимізувати її для запуску на конкретному квантовому комп'ютері. Спершу потрібно завантажити бекенд.

service = QiskitRuntimeService()

backend = service.backend("ibm_marrakesh")

Якщо у тебе немає доступного часу на акаунті або ти хочеш з будь-якої причини скористатися симулятором, запусти клітинку нижче, щоб налаштувати симулятор, який відтворюватиме поведінку квантового пристрою, обраного вище:

pm = generate_preset_pass_manager(optimization_level=2, backend=backend)

transpiled_circuit = pm.run(circuit)

print(f"2q-depth: {transpiled_circuit.depth(lambda x: x.operation.num_qubits==2)}")
print(f"2q-size: {transpiled_circuit.size(lambda x: x.operation.num_qubits==2)}")
print(f"Operator counts: {transpiled_circuit.count_ops()}")
transpiled_circuit.draw(output="mpl", fold=-1, style="clifford", idle_wires=False)
2q-depth: 188
2q-size: 281
Operator counts: OrderedDict({'sx': 548, 'rz': 380, 'cz': 281, 'measure': 8, 'x': 6})

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

3. Виконання​

# Sampler primitive to obtain the probability distribution
sampler = Sampler(backend)

# Turn on dynamical decoupling with sequence XpXm
sampler.options.dynamical_decoupling.enable = True
sampler.options.dynamical_decoupling.sequence_type = "XpXm"
# Enable gate twirling
sampler.options.twirling.enable_gates = True

pub = transpiled_circuit
job = sampler.run([pub], shots=1024)
result = job.result()[0]
counts = result.data["out"].get_counts()
plot_histogram(counts, figsize=(35, 5))

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

Ми бачимо чотири чіткі піки при 00000000, 01000000, 10000000 та 11000000, а також певну кількість відліків в інших бітових рядках через шум у квантовому комп'ютері. Ми ігноруватимемо їх і залишимо лише домінуючу четвірку, встановивши поріг: враховуються лише ті відліки, що перевищують цей поріг і є справжнім сигналом над шумом.

# Dictionary of bitstrings and their counts to keep
counts_keep = {}
# Threshold to filter
threshold = np.max(list(counts.values())) / 2

for key, value in counts.items():
if value > threshold:
counts_keep[key] = value

print(counts_keep)

4. Постобробка​

В алгоритмі Шора значна частина обчислень виконується класично. Тому решту кроків ми винесемо в «постобробку» — після того як отримаємо результати вимірювань із квантового комп'ютера. Кожен із наведених вище результатів вимірювань можна перетворити на ціле число, яке після ділення на 2m2^m є наближенням для kr\frac{k}{r}, де kk — випадкове число щоразу.

a = 2
N = 15

FACTOR_FOUND = False
num_attempt = 0

while not FACTOR_FOUND:
print(f"\nATTEMPT {num_attempt}:")
# Here, we get the bitstring by iterating over outcomes
# of a previous hardware run with multiple shots.
# Instead, we can also perform a single-shot measurement
# here in the loop.
bitstring = list(counts_keep.keys())[num_attempt]
num_attempt += 1
# Find the phase from measurement
decimal = int(bitstring, 2)
phase = decimal / (2**num_control) # phase = k / r
print(f"Phase: theta = {phase}")

# Guess the order from phase
frac = Fraction(phase).limit_denominator(N)
r = frac.denominator # order = r
print(f"Order of {a} modulo {N} estimated as: r = {r}")

if phase != 0:
# Guesses for factors are gcd(a^{r / 2} ± 1, 15)
if r % 2 == 0:
x = pow(a, r // 2, N) - 1
d = gcd(x, N)
if d > 1:
FACTOR_FOUND = True
print(f"*** Non-trivial factor found: {x} ***")
ATTEMPT 0:
Phase: theta = 0.0
Order of 2 modulo 15 estimated as: r = 1

ATTEMPT 1:
Phase: theta = 0.75
Order of 2 modulo 15 estimated as: r = 4
*** Non-trivial factor found: 3 ***

Висновок​

Пройшовши цей модуль, ти, мабуть, по-новому оціниш геніальність Пітера Шора, якому вдалося придумати такий дотепний алгоритм. Але сподіваємось, ти також досяг нового рівня розуміння його оманливої простоти. Хоча алгоритм може здаватися вражаюче (або лякаюче) складним, якщо розбити його на кожен логічний крок і пройти повільно, ти теж зможеш запустити алгоритм Шора.

Хоча ми ще далекі від використання цього алгоритму для факторизації чисел на кшталт RSA1024, наші квантові комп'ютери стають кращими щодня, і щойно буде досягнуто порогу, який називають відмовостійкістю, такі алгоритми не змусять себе чекати. Зараз — захопливий час для вивчення квантових обчислень!

Завдання​

Ключові концепції:​

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

  • Модульна арифметика — зокрема структури ZN\mathbb{Z}_N та ZN∗\mathbb{Z}_N^* — є математичною основою алгоритму Шора.

  • Задачу факторизації цілого числа NN можна звести до задачі знаходження порядку числа за модулем NN.

  • Квантовий пошук порядку використовує методи квантової оцінки фази для визначення періоду функції axmod  Na^x \mod N.

  • Алгоритм Шора являє собою класично-квантовий гібридний робочий процес, який обирає основу, виконує квантовий пошук порядку, а потім класично обчислює множники з результату.

Правда/Хиба:​

  1. П/Х Ефективність алгоритму Шора загрожує безпеці RSA-шифрування.

  2. П/Х Алгоритм Шора можна ефективно виконати на будь-якому сучасному квантовому комп'ютері.

  3. П/Х Алгоритм Шора використовує квантову оцінку фази (QPE) як ключову підпрограму.

  4. П/Х Класична частина алгоритму Шора передбачає обчислення найбільшого спільного дільника (НСД).

  5. П/Х Алгоритм Шора працює лише для факторизації парних чисел.

  6. П/Х Успішний запуск алгоритму Шора завжди гарантує правильні множники.

Короткі відповіді:​

  1. Чому алгоритм Шора вважається потенційною майбутньою загрозою для RSA-шифрування?

  2. Чому знаходження періоду, або порядку, функції модульного піднесення до степеня допомагає факторизувати число в алгоритмі Шора?

Задачі підвищеної складності:​

  1. Скільки контрольних кубітів mm нам потрібно для заданого числа NN, яке ми намагаємося факторизувати, щоб отримати точність QPE, необхідну для знаходження правильного значення порядку rr?

  2. Дотримуючись описаної тут процедури факторизації 15, спробуй тепер факторизувати 21.