Quantum Cloud Serviceとローカル実行

この記事は量子コンピュータ Advent Calendar 2018の8日目の記事です.

概要

Rigettiの提供しているQuantum Cloud Service全体についての概要と,そこで利用されるライブラリpyquilをローカルで実行する方法と実行した結果について説明していきます.

Quantum Cloud Serviceとは

Quantum Cloud Service(QCS)とはRigettiが提供している量子コンピュータ関連のクラウドサービス全体を指します. このクラウドサービスにおいてRigettiはクラウド上にインスタンスを提供しており,そのインスタンスsshなどを経由してアクセスすることでRigettiが提供している量子コンピュータへ接続して使用することができるようになっています.イメージとしてはRigettiがHP上で公開している以下のイメージが全体像をイメージしやすいと思います.

f:id:kadora:20181125141558p:plain 出典: Rigetti Computing https://www.rigetti.com/qcs

このQCSは,以下のページのSign up for Quantum Cloud Servicesのところからメールアドレスを登録することで誰でも登録することができます.

https://www.rigetti.com/qcs

ただし現在のところ実際に使用できるようになるまでは順番待ちになっていて,使用できるようになるまで結構待ち時間があります(11月の頭に登録しましたがまだ順番が回ってきてません).

実際に動いている量子コンピュータ

現在のところRigettiが提供している実機の量子コンピュータには8Qubitの量子コンピュータと,19Qubitの量子コンピュータがあります. 各々の実機がどのように量子ビットが配置されているかや,パフォーマンスなどについては以下のページに詳細があります.

https://www.rigetti.com/qpu

Forest™ SDK

Forest™ SDKはRigettiが提供しているSDKで,中身としてはローカルで動かすことができる量子コンピュータのシミュレータなどQCSと同様の環境をローカルで利用するために必要なものが入ったものです.QCSと違い,こちらの方はメールアドレスを登録することで順番を待つことなく即座にダウンロード可能なリンクが送られてきます.

pyquil

pyquilはRigettiが提供している量子コンピュータを使用するためにPythonから利用できるライブラリです.QCS内で実機の量子コンピュータに接続するためにも使いますが,pyquil2.0からローカルで使用することも出来るようになりました.Forest™ SDKと一緒にローカルに導入することで,ローカルで量子コンピュータのシミュレートを実行することが出来ます.

pyquilをローカルで使用してみる

では実際にpyquilをローカルで実行してみて,Rigettiの量子コンピュータがどのような感じで使えるのかを見ていこうと思います.

事前準備

pyquilの実行にはPython 3.6系以降が必要です(Python2系での動作は保証されていません). また,現在Forest™ SDKmacOS用とLinux用のパッケージ(.pkg, .dev, .rpm)での提供となっているため,いずれかの環境を用意する必要があります(Windowsはcoming soonとなっていますがいつになるかはわかりません).

pyquilのインストール

pyquilはpipを利用してインストールすることが出来ます.以下のコマンドを実行することでインストールを行います.

pip install pyquil

Forest™ SDKのインストール

以下のページのDownload the new Forest™ SDKβの部分にメールアドレスを登録すると,SDKのダウンロード用のURLがメールで送られてくるので,使用する環境に応じたリンク先からSDKをダウンロードしてきてインストールします.

https://www.rigetti.com/forest

QVMとCompilerの立ち上げ

pyquilをローカルで使用するためには,Forest™ SDKに含まれているQVMとCompilerをローカルホストで立ち上げて,実行時にそれらとやり取りを行う必要があります. QVMとCompilerはForest™ SDK内でそれぞれqvmとquilcというバイナリとして提供されており,正しくパスが通っていればコマンドラインから使用することが出来るようになっています. Forest™ SDKのインストール時にqvmとquilcのインストールされた場所にパスがちゃんと通っていることを確認しておきましょう.

qvmとquilcをそれぞれ,別ターミナルで以下のコマンドを実行することでサーバモードでローカルで立ち上げることができます.

% qvm -S

******************************
* Welcome to the Rigetti QVM *
******************************
Copyright (c) 2018 Rigetti Computing.

This is a part of the Forest SDK. By using this program
you agree to the End User License Agreement (EULA) supplied
with this program. If you did not receive the EULA, please
contact <support@rigetti.com>.

(Configured with 10240 MiB of workspace and 8 workers.)

[2018-12-07 18:44:55] Starting server on port 5000.
% quilc -S

+-----------------+
|  W E L C O M E  |
|   T O   T H E   |
|  R I G E T T I  |
|     Q U I L     |
| C O M P I L E R |
+-----------------+
Copyright (c) 2018 Rigetti Computing.

This is a part of the Forest SDK. By using this program
you agree to the End User License Agreement (EULA) supplied
with this program. If you did not receive the EULA, please
contact <support@rigetti.com>.

[2018-12-07 18:44:59] Starting server: 0.0.0.0 : 6000.

それぞれについて,詳しいドキュメントは以下になります.

qvm: https://pyquil.readthedocs.io/en/stable/qvm-man.html

quilc: https://pyquil.readthedocs.io/en/stable/quilc-man.html

pyquilのコードを書く

実際にpyquilをPythonで実行するコードを書いていきましょう. ここで解説しているコード全体は以下のGitHubリポジトリにあります.

github.com

以下では量子テレポーテーションをシミュレートしていくコードをpyquilで書いて行きます. 量子テレポーテーションについては,以前にIBM Qを用いてシミュレーションした記事を公開していますので詳しくは以下の記事を参照してください.

kadora.hatenablog.com

まずはpyquilをimportします.

from pyquil import Program, get_qc
from pyquil.gates import *
from pyquil.api import WavefunctionSimulator
from math import pi

1行目のimportで量子コンピュータで実行するプログラムを記述するためのオブジェクトであるProgramと,量子コンピュータへの接続に使用するget_qcをimportします. 2行目では量子コンピュータで扱う量子ゲートをimportしています.3行目は結果をわかりやすく表示するために波動関数で出力する際に使用するライブラリをimportしてます. また, \piを使用するために4行目でpiをimportしています.

最初に量子コンピュータで実行するプログラムを記述するためのオブジェクトであるProgramと,結果をわかりやすく表示するために波動関数で出力するためのオブジェクトを用意します.

p = Program()
wf = WavefunctionSimulator()

次に量子テレポーテーションで送る量子ビットを用意します. どんな状態でも良いのですが,今回は回転ゲートRYで \frac{\pi}{4}回転させたビットをテレポートさせてみます.

p += RY(math.pi / 4.0, 0)
print('Sending quantum state.')
print(wf.wavefunction(p))

f:id:kadora:20181202153354p:plain:w200

この様にProgramのオブジェクトに+=でゲートなどを追加していくことで逐次的に実行されていくプログラムを記述していきます. RY()は,1つ目の引数に回転の角度を受け取り,2つ目の引数にゲートを適用させる量子ビットを受け取ります. wf.wavefunction(p)によってその時点でのpをシミュレートした後の波動関数を出力することが出来るので,どのような量子状態を送ろうとしているのかを表示させます.

次に,量子テレポーテーションに使用するベル状態の2qubitを用意します.

p += H(1)
p += CNOT(1,2)

f:id:kadora:20181202155420p:plain:w150

H()はHゲートを適用させる量子ビットを引数にとります.CNOT()は1つ目の引数に取る量子ビットを制御ビット,2つ目の引数に取る量子ビットをターゲットビットとしてCNOTゲートを適用させます.

量子テレポーテーションをするにはAliceの量子ビットを測定した結果を利用する必要があるので,測定結果を入れるための古典レジスタを用意します.

ro = p.declare('ro', 'BIT', 2)

declare()によって,実行中に測定結果を保持するためのレジスタを確保します.

量子テレポーテーションでBobへ必要な情報を送るためにAliceのビットをベル基底で測定する必要がありますが,ベル基底での測定は用意されていないので,測定の前にAliceのビットに対してHゲートとCNOTゲートを適用させてから測定を行います.

p += CNOT(0,1)
p += H(0)
p += MEASURE(0, ro[0])
p += MEASURE(1, ro[1])

f:id:kadora:20181202155500p:plain:w300

MEASURE()は1つ目の引数にある量子ビットをパウリZ基底で測定した時の結果を2つ目の引数にとったレジスタに入れます.

最後にAliceのビットの測定結果を用いてBobのビットに対してゲートを適用させて量子テレポーテーションを行います.

p.if_then(ro[1], X(2))
p.if_then(ro[0], Z(2))

f:id:kadora:20181202155547p:plain:w300

if_thenは,1つ目の引数に取った値がtrueなら,2つ目の引数に取ったProgramを実行します.3つ目の引数は1つ目の引数に取った値がfalseだった時に実行されるProgramを渡すことが出来て省略することも出来ます. if_thenで2つ目の引数に取れるのは,単体のゲートだけではなく,Program全体を渡すことも出来るので,より複雑な処理を行う際にはその処理を別のProgramオブジェクトとして記述してからそれを渡すようにします.

コード全体では次のようになります.

from pyquil import Program, get_qc
from pyquil.gates import *
from pyquil.api import WavefunctionSimulator
from math import pi

# prepare Objects
p = Program()
wf = WavefunctionSimulator()

# prepare sending qubit
p += RY(pi / 4.0, 0)
print('Sending quantum state.')
print(wf.wavefunction(p))

# prepare Bell state
p += H(1)
p += CNOT(1,2)

# prepare classical register
ro = p.declare('ro', 'BIT', 2)

# measure Alice bits
p += CNOT(0,1)
p += H(0)
p += MEASURE(0, ro[0])
p += MEASURE(1, ro[1])

# apply gates to Bob's bit
p.if_then(ro[1], X(2))
p.if_then(ro[0], Z(2))
print('Received quantum state.')
print(wf.wavefunction(p))

f:id:kadora:20181202155242p:plain:w600

上2つがAliceの持つ量子ビット,下の1つがBobの持つ量子ビットです.

実行結果

これを実行すると,以下のように結果が出力されます.

$ python qteleportation.py

Sending quantum state.
(0.9238795325+0j)|0> + (0.3826834324+0j)|1>
Received quantum state.
(0.9238795325+0j)|000> + (0.3826834324+0j)|100>

波動関数のケットの中身は右から順に0番目,1番目,2番目のビットを表しています. 最後のテレポーテーション後の状態を見てみると,0番目,1番目はAliceのビットなので既に測定されて状態が \left|0\right\rangleで確定していて,3番目のBobのビットのみが重ね合わせの状態にあり,((0.9238795325+0j)\left|0\right\rangle +  (0.3826834324+0j)\left|1\right\rangle) \otimes \left|0\right\rangle \otimes \left|0\right\rangleの状態になっており,最初にAliceが用意したビットの状態がそのままBobの持つ状態となっており,量子テレポーテーションに成功している様子がわかります.

まとめ

今回はQCSの利用順番待ちが間に合わなかったので,pyquilのローカル実行について紹介しました. pyquilには,本体以外にもgroveといういくつかのアルゴリズムなどがまとめられたものがあります.

github.com

これを使用することで,VQEなどのアルゴリズムも簡単に試してみることが出来るので興味を持った人はこの辺りも使用してみて色々とやってみると良いでしょう. 実機へのアクセスはまだクローズドベータという感じでなかなか使えませんが,ローカルとほぼ同じように(恐らく)実行出来るので実機を使う前に慣れておけるのもpyquilの良いところでしょう.