はじめに
量子コンピュータ(アニーリング)を勉強したのですが、
数学(数式)がよくわからず、諦めかけてました。
ところが、TYTANというライブラリを発見、
ビデオ付きのチュートリアルがあり、数学(数式)が苦手な私でも簡単にアニーリングプログラムが書けます。
TYTANは、ローカルPCのCPUで量子シミュレーションしているので、
簡単に使えるのですが、複雑なことをやると、遅くなったり、正しい答えがでなくなってきます。
TYTANからクラウドサービスのAmplifyを利用してみたら、早く正しい情報がでるようになりましたので、
やり方を紹介します。
アクセストークンの取得
今回のサンプルプログラム
プログラムは、公式チュートリアルの「温度計パズル」です
ソースコードは、下記の通り、元のソースはコメントにしていて
サンプリング部分をAmplifyで行うようにしています。
tutorial2.py
from tytan import *
import numpy as np
#量子ビットを用意する
q00 = symbols('q00')
q01 = symbols('q01')
q02 = symbols('q02')
q03 = symbols('q03')
q04 = symbols('q04')
q05 = symbols('q05')
q06 = symbols('q06')
q07 = symbols('q07')
q08 = symbols('q08')
q09 = symbols('q09')
q10 = symbols('q10')
q11 = symbols('q11')
q12 = symbols('q12')
q13 = symbols('q13')
q14 = symbols('q14')
q15 = symbols('q15')
#各行、「4個から指定の個数だけ1になる」
H = 0
H += (q00 + q01 + q02 + q03 - 2)**2
H += (q04 + q05 + q06 + q07 - 1)**2
H += (q08 + q09 + q10 + q11 - 3)**2
H += (q12 + q13 + q14 + q15 - 1)**2
#各列、「4個から指定の個数だけ1になる」
H += (q00 + q04 + q08 + q12 - 3)**2
H += (q01 + q05 + q09 + q13 - 1)**2
H += (q02 + q06 + q10 + q14 - 1)**2
H += (q03 + q07 + q11 + q15 - 2)**2
#各温度計、球部から降順になる
H += (1 - q08) * q04
H += (1 - q04) * q00 #8→4→0の連鎖
H += (1 - q05) * q01
H += (1 - q03) * q02
H += (1 - q07) * q06
H += (1 - q11) * q10
H += (1 - q10) * q09 #11→10→9の連鎖
H += (1 - q13) * q12
H += (1 - q15) * q14
#コンパイル
qubo, offset = Compile(H).get_qubo()
print(f'offset\n{offset}')
'''
-- ここから 下はTYTANオリジナルのコード --
#サンプラー選択
solver = sampler.SASampler()
#サンプリング
result = solver.run(qubo)
#上位5件
for r in result[:5]:
print(r)
print(np.array(list(r[0].values())).reshape(4, 4))
-- こまで TYTANオリジナルのコード --
-- ここから下がAmplify対応のコード --
'''
# 各量子ビットのラベルを用意する
sp = []
for i in range(16):
sp.append("q" + format(i, '02'))
# Amplifyの形式に変換
Q = {}
for i in range(16):
for j in range(16):
if ((sp[i], sp[j]) in qubo):
Q[(i, j)] = qubo[(sp[i], sp[j])]
from amplify import Solver
from amplify.client import FixstarsClient
from amplify import (BinaryPoly, BinaryQuadraticModel, Solver)
f = BinaryPoly(Q)
model0 = BinaryQuadraticModel(f)
# クライアントの設定
client = FixstarsClient() # Fixstars Amplify AE
client.parameters.timeout = 1000 # タイムアウト1秒
client.token = "" # ご自身のトークンを入力
# マシンを実行
solver = Solver(client) # ソルバーに使用するクライアントを設定
result = solver.solve(model0) # 問題を入力してマシンを実行
print(result)
for i in range(len(result)):
r = [result[i].values[j] for j in range(16)]
print(r)
print(np.array(r).reshape(4, 4))
解説
TYTANでコンパイル後のQUBO行列は、下記のようにキーにラベル(文字列)を使った形式になっています。
{('q04', 'q05'): 2.0, ('q05', 'q13'): 2.0, ('q13', 'q13'): -2.0, ('q06', 'q10'): 2.0, ('q00', 'q04'): 1.0, ('q01', 'q01'): -3.0, ('q06', 'q07'): 1.0, ('q15', 'q15'): -4.0, ('q07', 'q07'): -4.0, ('q00', 'q03'): 2.0, ('q08', 'q10'): 2.0, ('q02', 'q10'): 2.0, ('q04', 'q04'): -5.0, ('q04', 'q07'): 2.0, ...}
Amplifyでは、下記のようにキーは数値を使うようなので、ラベルのテーブルを作成して変換するようなコードを入れています。
{(0, 0): -7.0, (0, 1): 2.0, (0, 2): 2.0, (0, 3): 2.0, (0, 4): 1.0, (0, 8): 2.0, (0, 12): 2.0, (1, 1): -3.0, (1, 3): 2.0, (1, 5): 1.0, (1, 13): 2.0, (2, 1): 2.0, (2, 2): -3.0, (2, 3): 1.0, ...}
また、サンプリングの結果もTYTANの場合は、ラベル(文字列)を使った形式になっていますが
{'q00': 1, 'q01': 0, 'q02': 0, 'q03': 1, 'q04': 1, 'q05': 0, 'q06': 0, 'q07': 0, 'q08': 1, ...}
Amplifyでは、数値を使っています。
{2: 0, 1: 0, 10: 1, 14: 0, 11: 1, 8: 1, 15: 0, 9: 0, 7: 0, 6: 0, 5: 0, 13: 1, 3: 1, 4: 1, ...}
以上です。