D-Waveと呼ばれるカナダのベンチャー企業の作った量子アニーリングマシンがあります。D-Waveはカナダをベースとしているのでドキュメントやツールがすべて英語で、かつ日本からの利用にはいくらかの壁があります。ということで、簡単にD-Waveへ問題が投げられる機能を作ってみました。簡単といっても、現状日本から問題を投げるにはD-Waveの契約が必要なのでまだ壁はありますが。。。
カナダのベンチャー企業で、量子アニーリングと言われる量子効果を活用したアルゴリズムをハードウェア実装したマシンです。
企業情報:
本社所在地:カナダブリティッシュコロンビア州バーナビー
設立:1999年
事業内容:量子コンピュータのハードウェアとソフトウェアを商用製品として提供
従業員数:160名(Ph.D 55名)
引用元:https://www.dwavesys.com/resources/media-resources
引用元:https://www.dwavesys.com/resources/media-resources
詳細はカナダのホームページを参照してくださいませ。
https://www.dwavesys.com/
日本語サイトもあります。
http://dwavejapan.com/
今回D-Waveがプロ向けのクラウド環境の他に、コミュニティ機能や無料使用時間を搭載した新しいLEAPのプラットフォームを並行して立ち上げました。
新しいLEAPの画面はLEAPやD-Waveマシンの紹介、そしてデモの使い方、SDKのインストールの仕方などが書いてあります。ダッシュボードは下記のようにアカウントのタイプやAPItoken、QPUの使用時間や残時間が細かく載っています。個人的なあれですので、ちょっと情報は削除させてもらっています。
下の方には、使用できるハードウェアとソフトウェアのマシンのリストや、APIのendpoint情報、マシンの稼働状況などが載っています。弊社は企業で借りているのでプランが違う可能性があり、表記は異なる可能性があります。みた感じ、有料プランには優先権などが付与されているような表記があります。
手前味噌ですが、MDRで作った量子アニーリングなどのイジングマシン向けのアプリケーション開発キットのSDKです。簡単にアプリケーションを作り、シミュレーションで計算したりできます。入手は簡単で無料で手に入りますし、pipがインストールされている際には簡単にワンステップで導入できます。
https://github.com/mdrft/Wildqat
使い方は簡単で、pipでインストールしたら数行で量子アニーリングやイジング問題を設定して解くことができます。
インストール
pip3 install wildqat
利用方法
import wildqat as wq
a = wq.opt()
a.qubo = [[4,-4,-4],[0,4,-4],[0,0,4]]
a.sa() #=> [1, 1, 1]
print(a.E[-1]) #=>[0.0]
これはなにかある問題を解いています。
さっそく本題です。現在D-Waveに問題を投げるにはOceanというツールを使います。
https://github.com/dwavesystems/dwave-ocean-sdk
これはこれで使いやすいので、描きやすさを優先しているWildqatほどは簡単ではないので、簡単なWildqatのインターフェイスを使ったまま、D-Waveにも問題を投げられたらいいかなと思っていました。また、日本語のドキュメントもWildqatは国内で作っているので充実していてわからないところにはそのまますぐにお応えできる環境があります。
D-Waveに問題を投げる際に一番問題になるのは、D-Waveがちょっと特殊なモデルを利用しているということです。D-Waveが利用しているのはキメラグラフと呼ばれる4*4の井形構造の量子ビット配列を基本としてそれを拡張した形を使っています。
こちらのキメラグラフは上記はハードウェアの配列ですが、プログラミングをする際に使用する論理回路構成は、
このような構成の表記の仕方などをされたりします。この特殊な接続をするためには、それぞれの量子ビットに割り振られた通し番号を確認しながら、どこが接続されているのかを確認してプログラミングをする必要があります。
実際D-Waveにクラウドサーバー経由で問題を投げる際に必要な情報は、問題を投げる量子ビットの通し番号と設定する値をセットで送る必要があります。それらのデータはフロントでバイナリデータにおきかわり、サーバーへ投げられます。
下記はそれらの接続と設定値を組み合わせた例になりますが、
2048 3
2 2 2
0 4 -1
1 5 1
このようになっています。1行目は量子ビット数2048とサーバーに送るデータの行数の合計です。今回は3行なので3が設定されています。
2行目以降は実際のデータ領域になっていて、2 2 2 は最初の2つの文字を読みます。2 2 は2という量子ビットにデータを送るという意味で、同じ数字が並ぶ場合には量子ビットに設定する局所磁場というデータを扱います。ここでは2 2 2なので2という量子ビットの局所磁場に2という値を設定することになります。
3行目、4行目は異なる量子ビット間に設定される相互作用というデータを扱います。
0 4 -1は0の量子ビットと4の量子ビットの間に-1というデータを割り振ります。
1 5 1 は1と5の量子ビットの間に1というデータを割り振ります。
このように量子ビットに対応する番号を割り振り、設定をします。ですので、今回WildqatにD-Waveへの問題送信機能を搭載するにはこれらのルールを使います。
D-waveにデータを投げるのに一からツールを作るのは大変なので簡単に導入できる方法を考えてみました。
A minimal implementation of the REST interface used to communicate with D-Wave Solver API (SAPI) servers.
https://github.com/dwavesystems/dwave-cloud-client
RESTの最低限機能を持ったdwave-cloud-clientというのがあります。こちらを使って実装をしてみたいと思います。D-waveのGithubにのっている例題は下記の通り、
import random
from dwave.cloud import Client
# Connect using the default or environment connection information
with Client.from_config() as client:
# Load the default solver
solver = client.get_solver()
# Build a random Ising model to exactly fit the graph the solver supports
linear = {index: random.choice([-1, 1]) for index in solver.nodes}
quad = {key: random.choice([-1, 1]) for key in solver.undirected_edges}
# Send the problem for sampling, include solver-specific parameter 'num_reads'
computation = solver.sample_ising(linear, quad, num_reads=100)
# Print the first sample out of a hundred
print(computation.samples[0])
使用方法はとても簡単です。solverというインスタンスを作成し、linearに局所磁場、quadに相互作用を実装すれば大丈夫そうです。そしてcoputationに計算結果を格納します。
今回Wildqatはこのdwave-cloud-clientを呼び出し、linearとquadにデータを格納し、D-waveの実機に問題を投げるようにしたいと思います。
シンプルに作りました。Wildqatでは内部にQUBOmatrixと呼ばれるmatrixを持っています。そしてそのQUBOmatrixからising matrixを作成しそれをシミュレーテッドアニーリングもしくは量子アニーリングで計算をします。今回は作成されたising matrixをそのままD-Waveに投げるようにmatrixから局所磁場と相互作用を抜き出して、データ形式を揃えて送るようにします。エラーハンドリングないですが、投げる機能はできました。
残念ながら誰もがD-Waveに問題を投げられるわけではありません。。。D-Waveに問題を投げるにはAPItokenが必要です。tokenを設定して問題を投げる機能を作ります。エンドポイントと投げるマシンはデフォルトで既知のものを設定します。tokenはインスタンスを作成して自分で設定する必要があります。
ちゃちゃっと出来上がったので使ってみます。まずは認証情報を設定して問題を作成します。そしてその問題をD-Waveに投げます。投げ方は簡単です。最後をdw()にするだけです。
from wildqat import *
a = opt()
a.dwavetoken = "YOUR TOKEN HERE"
a.qubo = [[0,0,0,0,-4],[0,2,0,0,-4],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,4]]
a.dw()
実行結果は、、、
[1,1,-1,1,1,0,0,0,0,0,0]
合っていますが、ちょっとわかりづらかったです。今回欲しいのは設定が生きている0番目、1番目、4番目の量子ビットで、答えはすべて111です。
試しに10回連続で投げてみて答えが合ってるかどうか確認してみたいと思います。
for i in range(10):
result = a.dw()
print(result[0],result[1],result[4])
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
このように無事サーバーからレスポンスを受けて計算が完了しました。
D-Waveのqubistというクラウドサイトで自分のジョブを確認できます。
きちんと連続して独立したジョブが投げられていました。中を見てみると、
きちんと問題が設定されて返されているのが確認できました。
今回は簡単な昨日に留めましたが、要望次第でより使いやすい機能を実装してみたいと思います。
問題を投げる機能はつけましたが、問題をキメラグラフに合わせるのは大変そうです。。。
以上です。
Tweetinfo@mdrft.com