概要
組み合わせ最適化問題に対するブレークスルーと思われる画期的な技術「量子アニーリング」が誰でも1分/月まで無料で使える環境「Leap」がD-Wave社から提供されました。早速使ってみようと思ったのですが、現時点ではあまり分かりやすいマニュアルや記事が見当たらなかったため、公式ドキュメントを中心にいろいろと調べ、まずはPythonを使ってAPIを叩き、サンプルプログラムが動作するところまで行きましたので、その内容をまとめておこうと思います。
手順
使うまでの手順は以下になります。
- Leapに登録する
- API Tokenのコードを取得する
- 組み合わせ最適化問題を定義すると共に、2次形式に式変形しておく
- 3の内容をLeapに認識させるためのPythonコードを作成する
- 4の内容をAPIに渡すためのPythonコードを作成する
- APIを叩き結果を取得する
3と4は大事なところですが、今回はサンプルコードを使うとして説明を省略します。
Leapに登録する
まず、Leapのページにアクセスしてサインアップしましょう。この時、国名にJapanを入れると登録させてくれない(アメリカかカナダ限定というエラーが出る)ため、適当にアメリカを選んでおきましょう。アメリカで登録しても、日本からのアクセスだからと言って遮断されることはなく、問題なく動作しました(もし問題が出たらクラウドサービスのアメリカリージョンを使おうかと思っていました)。
API Tokenのコードを取得する
ログインできるようになったら、次はAPI Tokenのコードを取得しましょう。取得といっても特別な作業が必要なわけではなく、ダッシュボードのページを少し下にスクロールすれば、API Tokenをコピーできる部分があるはずです。
組み合わせ最適化問題を定義すると共に、2次形式に式変形しておく
本記事では、以下の例を使いました。3つの変数のうち1つだけが1で残りは0という制約を表すための評価関数式が示されています。
https://docs.dwavesys.com/docs/latest/c_gs_6.html
3の内容をLeapに認識させるためのPythonコードを作成する
Leapに本問題を認識させるためには、以下に示すようなディクショナリ形式の変数を作成する必要があります。各係数は上の式と対応しています。
これを実現するためのコードとして以下が与えられています。
linear = {('x0', 'x0'): -1, ('x1', 'x1'): -1, ('x2', 'x2'): -1} quadratic = {('x0', 'x1'): 2, ('x0', 'x2'): 2, ('x1', 'x2'): 2} Q = dict(linear) Q.update(quadratic)
https://docs.dwavesys.com/docs/latest/c_gs_8.html
4の内容をAPIに渡すためのPythonコードを作成する
まず、PythonからDwaveを使うためのライブラリをインストールしておきます。
pip install dwave-system
次に、ライブラリをインポートし、先ほど定義したQを渡してレスポンスを受け取る処理をコーディングします。
from dwave.system.samplers import DWaveSampler from dwave.system.composites import EmbeddingComposite response = EmbeddingComposite(DWaveSampler(token="hogehoge")).sample_qubo(Q, num_reads=1000)
num_readsは同じ検討を何回実施するかを示します。大きいほどアニーリングの結果(確率的)が収束しますが、1分/月の計算時間を消費してしまうので、あまり大きな値にしすぎないほうがいいかと思います。また、公式マニュアルには記載がなかったのですが、DWaveSamplerの引数にtokenとして2で取得したコード(hogehogeと書いている部分)を渡さないと、
ValueError: API token not defined
というエラーが出ますので気を付けてください。
APIを叩き結果を取得する
上記のコードを実行すればレスポンスに実行結果が返ってきているはずです。以下のコードで確認できます。これも、公式マニュアルの記載の通りにするとエラーが出るので微修正が必要でした。
#マニュアルとは異なり、listで括る処理と、戻り値が4つになっていることに留意する。 for sample, energy, num_occurrences, chain_break_fraction in list(response.data()): print(sample, "Energy: ", energy, "Occurrences: ", num_occurrences)
ソースコードと実行結果
以下にソースコード全文とその時の実行結果を載せておきます。
まずはソースコード。数行の処理ですので、コードとしては簡単ですね。
from dwave.system.samplers import DWaveSampler from dwave.system.composites import EmbeddingComposite linear = {('x0', 'x0'): -1, ('x1', 'x1'): -1, ('x2', 'x2'): -1} quadratic = {('x0', 'x1'): 2, ('x0', 'x2'): 2, ('x1', 'x2'): 2} Q = dict(linear) Q.update(quadratic) response = EmbeddingComposite(DWaveSampler(token="hogehoge")).sample_qubo(Q, num_reads=1000) for sample, energy, num_occurrences, chain_break_fraction in list(response.data()): print(sample, "Energy: ", energy, "Occurrences: ", num_occurrences)
実行結果は以下です。3種類の結果がありますが、1つだけが1で他が0という答えがEnergy(評価関数)が-1と最も小さくなり、その発生回数は459, 311, 230(合計すると1000)であるという結果になっています。この偏りに関しては検討できていません(回数を増やせばなくなってくるのかもしれませんが、時間をあまり消費したくなかった)が、1つだけが1で他が0という欲しい答えが選ばれているので正しく動作していることが読み取れます。計算時間の消費は0.1秒とかそのくらいだったと思います。
{'x0': 0, 'x1': 0, 'x2': 1} Energy: -1.0 Occurrences: 459 {'x0': 0, 'x1': 1, 'x2': 0} Energy: -1.0 Occurrences: 311 {'x0': 1, 'x1': 0, 'x2': 0} Energy: -1.0 Occurrences: 230
まとめ
少し苦戦しましたが、D-WaveのLeapのサンプルプログラムをPythonで動作させることができました。今後ナップサック問題等を解かせてみて、量子アニーリングを使わない場合との計算速度等を検討してみたいと考えています。