common.title

Docs
Quantum Circuit
TYTAN CLOUD

QUANTUM GAMING


Overview
Contact
Event
Project
Research

Terms of service (Web service)

Terms of service (Quantum and ML Cloud service)

Privacy policy


Sign in
Sign up
common.title

量子コンピュータや量子アニーリングのイジング定式化を機械学習で自動生成

Yuichiro Minato

2021/01/29 14:34

はじめに

研究者はずっと計算しているので計算に慣れてますが、一般人は定式化、二次関数と言われると蕁麻疹が出ます。量子アニーリング使いたいけど、定式化がめんどくさい、人材が獲得できないという人のために、定式化をデータから自動化する仕組みを考えてみたいと思います。

モチベーション

量子コンピュータでの量子断熱計算、QAOA、最近ではGrover Adaptive Searchなど、イジングモデルと呼ばれる物理モデルに社会問題を実装し、それを数理最適化していきます。また、量子アニーリングマシンでも定式化はとても課題のようです。

天才的に適当に定式化ができる人がいる一方で、そんなに都合よく量子アニーリングに人材を割けないという人もいると思うので、定式化を自動化してみます。

定式化

イジングモデルは、符号はプラス、マイナスありますが、

E = -\sum h_iq_i - \sum J_{ij}q_iq_j

の形に定式化します。この定式化は、

コスト関数
制約条件

にわけて設計して組み合わせます。コスト関数だけの問題、制約条件だけの問題、両方組み合わせる問題などもあります。

また、それらを組み合わせるときに調整変数というハイパーパラメータも出ますが、これも曲者ですが、その解決方法は今度紹介します。

定式化をデータで自動設計

パンがなければケーキを食べればいいじゃない。人がいなければAIで自動化すればいいじゃないですかということです。トライしてみます。正直アドリブで記事を書いてるので、制約条件が出るような難しい問題ではなく、簡単な問題で再現してみたいです。

適当な式を

まず3量子ビットの適当な式を別のイジング式に移してみます。

E = 2q_0 + q_2 -3 q_0 q_1

みたいな式を移してみます。

1.初期化

まずは移す先の式を用意します。こちらはランダムで係数を準備

E_{trial} = aq_0+bq_1+cq_2+dq_0q_1+eq_0q_2+fq_1q_2

となりました。課題は係数が多いことですかね。今後はこの問題を解決できるよう頑張りますが、今回は量子ビット数3に対して、3+3c2 = 3+3 = 6個の係数が出ます。

そして、ランダムでやります。

E_{trial} = 0.2q_0+0.4q_1+0.5q_2+0.2q_0q_1+0.3q_0q_2+0.4q_1q_2

はい。適当な式ができました。

2.最適化

SGDで最適化します。入力データは量子ビットの0か1。ラベルは移す元のエネルギー値です。最適化パラメータはaからfまでのイジング係数になります。

数値微分でSGDやってみます。

まずは、適当な入力データを作り、01を量子ビットに入力し、元のイジング式のエネルギー値を出します。

E = 2q_0 + q_2 -3 q_0 q_1

なので、001とかを入れると、

E=1

になります。

次に、移す先のイジング式にも01を入れます。

E_{trial} = 0.2q_0+0.4q_1+0.5q_2+0.2q_0q_1+0.3q_0q_2+0.4q_1q_2

に入れたものと、係数を一つ選びそれを微小変化させて数値微分を取ります。それを勾配として係数を更新してみましょう。

読み込み

ツールを読み込みます

import numpy as np
import matplotlib.pyplot as plt

コピー元のイジング式とランダムで用意したものを準備します。

#元のイジング式
E = np.array([2,-3,0,0,0,0,0,0,1])

#更新するもの
Et = np.array([0.2,0.2,0.3,0,0.4,0.4,0,0,0.5])

次に学習データを作ります。

量子ビットの数値配列を準備し、それに対応するエネルギーを準備しておきます。

#量子ビットの数字配列を準備し、それに対応するコストも求めておく
q = np.array([[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]])
Eq = np.zeros(8)

for i in range(8):
    Eq[i] = q[i]@E.reshape(3,3)@q[i]

Eq
array([ 0.,  1.,  0.,  1.,  2.,  3., -1.,  0.])

これは、こんな感じに

array([ 0.,  1.,  0.,  1.,  2.,  3., -1.,  0.])

SGD

数値微分を使ってSGD。f'(x) = (f(x+h) - f(x)) / h 学習率を決めて、更新をかける。
f(x)はイジングのエネルギーを求めて、ラベルとの差を損失関数で誤差を計算 x = x - e*f'(x)

必要なパラメータを準備します。

h = 0.01
e = 0.0001
rep = 10000
arr = []

Eu = np.zeros(9)

そして、SGDをかけて、損失関数を計算しながら更新をかけます。

for k in range(rep):
    x = np.random.randint(0,8)
    loss = np.abs((q[x]@Et.reshape(3,3)@q[x]) - Eq[x])
    arr.append(loss)
    
    for i in range(9):
        Ett = np.copy(Et)
        Ett[i] += h
        Eu[i] = (np.abs((q[x]@Ett.reshape(3,3)@q[x]) - Eq[x]) - loss)/h
    
    for i in range(9):
        Et[i] -= Eu[i]*e 
        
plt.plot(arr)
plt.show()
<Figure size 432x288 with 1 Axes>

image

まぁまぁですかね。

np.round(Et, 2)
array([ 0.2 , -0.31,  0.3 , -0.51, -0.05,  0.28, -0.  , -0.12,  0.87])

多少相互作用のところに不満は残りますが、エネルギー値は近いものになったようです。

array([ 1.99, -1.4 ,  0.15, -1.6 ,  0.  ,  0.2 , -0.15, -0.2 ,  0.99])

確認

最後にちょっと確認をします。コピー元のイジング式とのエネルギー値を比較します。

#最後に[ 0.,  1.,  0.,  1.,  2.,  3., -1.,  0.]と比較します。
Ef = np.zeros(9)

for i in range(8):
    Ef[i] = q[i]@Et.reshape(3,3)@q[i]
Ef
array([ 0.        ,  0.87381312, -0.05109759,  0.99254179,  0.1951    ,
        1.36051312, -0.67279759,  0.66244179,  0.        ])

これは、ある程度コピーできていると思います。応用として、イジング式のわからない事象をイジング式に定式化できます。

今後の発展

最適化アルゴリズムはSGDでしたが、これもハイパラなので、より良いのもありそうです。是非色々試してみてください。以上です。

© 2025, blueqat Inc. All rights reserved