Мы рассмотрели подготовку квантового состояния 1 кубита и провели оптимизацию с использованием классической техники оптимизации.



Теперь мы рассмотрим еще немного оптимизации состояния 1 кубита.

Настоящий номер

Мы провели оптимизацию создания любого квантового состояния на трехмерной блох-сфере. Теперь мы думаем только о действительном числе. Обычно при машинном обучении нам нужно только реальное число.

Раньше мы использовали вентиль u3 для создания квантового состояния, а теперь мы используем вентиль Ry в диапазоне от 0 до pi.

Инструменты

Мы используем blueqat и байесовскую оптимизацию на python.

!pip install blueqat
!pip install bayesian-optimization

Рай ротация

Мы просто пробуем поворот. Теперь у нас есть случайный угол для пробы. В качестве симулятора бэкэнда по умолчанию используется бэкэнд numpy, на этот раз я просто выбираю бэкэнд numba в качестве симулятора.

from blueqat import Circuit
from bayes_opt import BayesianOptimization
from blueqat import BlueqatGlobalSetting
BlueqatGlobalSetting.set_default_backend('numba')
import time
import math
import numpy as np

angle = math.pi * np.random.random()
start = time.time()
a = Circuit(1).ry(angle)[0].run()
end = time.time()
print(end - start)
print(a)

У нас есть,

0.001172780990600586
[0.81528649+0.j 0.5790578 +0.j]

Теперь мы знаем, что это работает.

Оптимизация

Мы делаем оптимизацию, используя байесовскую оптимизацию, которая проверяет приоритет данных.

Пример показывает, что нам нужно целевое квантовое состояние как суперпозиция |0› и |1›, а вектор состояния будет [0,707…, 0,707…]

def f(angle, target = np.array([np.sqrt(0.5),np.sqrt(0.5)])):
  a = Circuit(1).ry(angle)[0].run()
  return -(a[0].real - target[0])**2 - (a[1].real - target[1])**2

pbounds = {'angle': (0, math.pi)}
optimizer = BayesianOptimization(f=f, pbounds=pbounds)

start = time.time()
optimizer.maximize(init_points=10, n_iter=10)
print(time.time() - start)

print(optimizer.max)

Мы получили

|   iter    |  target   |   angle   |
-------------------------------------
|  1        | -0.2953   |  2.672    |
|  2        | -0.3306   |  2.737    |
|  3        | -0.2533   |  2.588    |
|  4        | -0.299    |  2.679    |
|  5        | -0.5585   |  0.03892  |
|  6        | -0.04497  |  1.996    |
|  7        | -0.5805   |  0.007542 |
|  8        | -0.1332   |  2.305    |
|  9        | -0.1585   |  2.372    |
|  10       | -0.1206   |  2.269    |
|  11       | -0.01659  |  1.313    |
|  12       | -6.594e-0 |  1.587    |
|  13       | -8.6e-06  |  1.565    |
|  14       | -1.051e-0 |  1.57     |
|  15       | -3.189e-0 |  1.574    |
|  16       | -3.774e-0 |  1.559    |
|  17       | -0.000250 |  1.602    |
|  18       | -0.000131 |  1.548    |
|  19       | -0.000179 |  1.598    |
|  20       | -0.000117 |  1.549    |
=====================================
47.76689958572388
{'target': -1.0507579819273144e-07, 'params': {'angle': 1.5701480188461168}}

Давайте проверим результат, и у нас есть хорошее приближение к целевому значению.

Circuit(1).ry(1.5701480188461168)[0].run()

#=>array([0.70733596+0.j, 0.70687753+0.j])

и затем мы пробуем |1› как цель

def f(angle, target = np.array([0,1])):
  a = Circuit(1).ry(angle)[0].run()
  return -(a[0].real - target[0])**2 - (a[1].real - target[1])**2

pbounds = {'angle': (0, math.pi)}
optimizer = BayesianOptimization(f=f, pbounds=pbounds)

start = time.time()
optimizer.maximize(init_points=10, n_iter=10)
print(time.time() - start)

print(optimizer.max)

У нас есть,

|   iter    |  target   |   angle   |
-------------------------------------
|  1        | -0.4881   |  1.714    |
|  2        | -0.04444  |  2.719    |
|  3        | -0.00382  |  3.018    |
|  4        | -1.097    |  0.9368   |
|  5        | -0.002545 |  3.041    |
|  6        | -0.09438  |  2.525    |
|  7        | -0.02024  |  2.857    |
|  8        | -0.001584 |  3.062    |
|  9        | -1.22     |  0.8011   |
|  10       | -1.81     |  0.1901   |
|  11       | -3.749e-3 |  3.142    |
|  12       | -3.749e-3 |  3.142    |
|  13       | -1.257e-1 |  3.142    |
|  14       | -3.511e-1 |  3.142    |
|  15       | -1.284e-1 |  3.142    |
|  16       | -1.284e-1 |  3.142    |
|  17       | -1.551e-1 |  3.142    |
|  18       | -1.551e-1 |  3.142    |
|  19       | -6.033e-1 |  3.142    |
|  20       | -7.728e-1 |  3.142    |
=====================================
24.23820424079895
{'target': -3.749399456654644e-33, 'params': {'angle': 3.141592653589793}}

Ускорьте байесовскую оптимизацию

Узким местом схемы оптимизации является не квантовая схема, а явно процесс оптимизации БО.

Теперь мы попробуем использовать гиперопт, чтобы получить гораздо больше скорости.

from blueqat import Circuit
import time
import math
import numpy as np
from hyperopt import hp, tpe, Trials, fmin

def f(angle, target = np.array([0,1])):
  a = Circuit(1).ry(angle)[0].run()
  return (a[0].real - target[0])**2 + (a[1].real - target[1])**2

start = time.time()
best = fmin(f, space = hp.uniform('angle', 0, math.pi), algo=tpe.suggest, max_evals=100, verbose=1)
print(time.time() - start)

print(best)

Да, это очень хорошо.

100%|██████████| 100/100 [00:00<00:00, 293.91it/s, best loss: 4.2970620825684156e-08]
0.3623378276824951
{'angle': 3.141178066465152}

И как суперпозиция

from blueqat import Circuit
import time
import math
import numpy as np
from hyperopt import hp, tpe, Trials, fmin

def f(angle, target = np.array([np.sqrt(0.5),np.sqrt(0.5)])):
  a = Circuit(1).ry(angle)[0].run()
  return (a[0].real - target[0])**2 + (a[1].real - target[1])**2

start = time.time()
best = fmin(f, space = hp.uniform('angle', 0, math.pi), algo=tpe.suggest, max_evals=100, verbose=1)
print(time.time() - start)

print(best)

Это также имеет хорошее приближение в данный момент.

100%|██████████| 100/100 [00:00<00:00, 330.35it/s, best loss: 8.988237686812778e-06]
0.3093442916870117
{'angle': 1.576792406987552}

Нам удалось оптимизировать и создать квантовый вектор состояния с помощью классической схемы оптимизации.