こんにちは。
今日は量子コンピュータのうちでも、イオントラップ と呼ばれる、原子核をイオン化したものにレーザーを当てて計算をするタイプの量子コンピュータについて、実行結果を交えて書いてみます。
イオントラップ
今回利用したのは、メリーランド州のIonQ(アイオンキュー)と言う会社のイオントラップ型の量子コンピュータです。量子コンピュータといえば、IBMやGoogleの超電導と呼ばれるチップの上に量子ビットが乗ったものが有名ですが、今回はチップの上の空中に浮いた原子核をレーザーで打ち込むタイプのマシンを使います。
現在こちらはamazon braketと呼ばれるawsのサービスで利用でき、量子ビット数は11、結合は全結合になっています。
方式は汎用ゲートモデルと呼ばれるもので量子回路を作っていきます。
グローバーのアルゴリズム
今回実行したのはグローバーのアルゴリズムと呼ばれるものです。グローバーのアルゴリズムは所望の振幅を操作できる量子振幅増幅という仕組みを使って、欲しい振幅を最大にするというアルゴリズムです。
グローバーのアルゴリズムは、
1、マーキング
2、振幅増幅
の2段階から成り立ちます。初期状態は初期の振幅がわかるようにHゲートで重ね合わせにしておきます。詳しくは別の機会で。
111を見つける
今回は3量子ビットを利用して、111という答えの振幅を大きくすることを目指しました。
量子コンピュータを利用した計算では、量子回路を組みます。グローバーでは、欲しい答えの振幅を最大にしますが、
この確率振幅は状態ベクトルを考えることで、最大にできます。
000から111まで3量子ビットある場合の状態ベクトルの要素数は8あります。そのうち、111に該当するのは、状態ベクトルの一番最後の要素になります。その要素をまずはマーキングと呼ばれる操作で振幅を負にします。
マーキング
今回はマーキングと呼ばれる操作で、111の状態ベクトルの振幅を正から負にします。これをするには、CCZゲートを使います。CCZは行列の対角成分のうち、一番最後だけが-1になっているため、重ね合わせ状態の状態ベクトルにかけると、111に相当する状態ベクトルのみにマイナスをつけることができます。
次に振幅増幅
振幅増幅は同様に、対角成分がマイナスとなった行列を上記のマーキングしたものにかけることで、マイナスのかかった状態ベクトルの振幅だけを伸ばすことができます。今回はこの一連の操作をイオントラップ型量子コンピュータで行いました。
CCZゲート
ここで1つ事前準備が必要です。CCZゲートはデフォルトでは用意されていないため、自分たちで作る必要があります。CCZゲートはCCXゲートのターゲットビットをHゲートで囲んで、XをZにすることで実現できます。CCXゲートはトフォリゲートと呼ばれていて、複数の1量子ビットゲートと2量子ビットゲートを組み合わせることでできます。
今回最終的にできた回路
こちらは、最終的にできた回路です。実際はほとんどの部分がCCZとなっていますが、初期にHゲートで重ね合わせを作り、CCZでマーキング、その後振幅増幅を行っています。
引用:amazon braket
深さ方向は最大28になっています。
イオントラップ型マシンには営業時間がある
今回利用した時は営業時間に制限がありました。世界標準時の13時から21時の間に処理されます。今回はたまたま13時30分くらいにジョブをなげたところ、18時18分ごろに処理されました。日本時間だと夜中の3時くらいなので、寝る前にジョブを投げて、起きたら終わってるくらいの感じでやるのがいいと思います。
計算結果
計算結果はjsonファイルとしてawsのs3という静的ファイル置き場に置かれます。参考に今回のファイルをおいておきます。
計算結果は、measurementProbabilitiesに格納されています。今回は1000shotsしたので、そのうちの回数が1/1000の確率として表現されています。実際には例えば、0.563は563回その答えが出たことになります。
下記では、111の答えが0.563という振幅になっていますので、答えがきちんと出ています。2回目の計算結果も続いて貼っていますので、ご覧ください。
{
"braketSchemaHeader": {
"name": "braket.task_result.gate_model_task_result",
"version": "1"
},
"measurementProbabilities": {
"000": 0.06,
"100": 0.092,
"010": 0.047,
"110": 0.039,
"001": 0.05,
"101": 0.045,
"011": 0.104,
"111": 0.563
},
"measuredQubits": [
0,
1,
2
],
"taskMetadata": {
"braketSchemaHeader": {
"name": "braket.task_result.task_metadata",
"version": "1"
},
"id": "hogehoge",
"shots": 1000,
"deviceId": "arn:aws:braket:::device/qpu/ionq/ionQdevice",
"deviceParameters": {
"braketSchemaHeader": {
"name": "braket.device_schema.ionq.ionq_device_parameters",
"version": "1"
},
"paradigmParameters": {
"braketSchemaHeader": {
"name": "braket.device_schema.gate_model_parameters",
"version": "1"
},
"qubitCount": 3
}
},
"createdAt": "2020-10-13T13:34:58.756Z",
"endedAt": "2020-10-13T18:18:10.944Z",
"status": "COMPLETED"
},
"additionalMetadata": {
"action": {
"braketSchemaHeader": {
"name": "braket.ir.jaqcd.program",
"version": "1"
},
"instructions": [
{
"target": 0,
"type": "h"
},
{
"target": 1,
"type": "h"
},
{
"target": 2,
"type": "h"
},
{
"target": 2,
"type": "h"
},
{
"target": 2,
"type": "h"
},
{
"control": 1,
"target": 2,
"type": "cnot"
},
{
"target": 2,
"type": "ti"
},
{
"control": 0,
"target": 2,
"type": "cnot"
},
{
"target": 2,
"type": "t"
},
{
"control": 1,
"target": 2,
"type": "cnot"
},
{
"target": 2,
"type": "ti"
},
{
"control": 0,
"target": 2,
"type": "cnot"
},
{
"target": 2,
"type": "t"
},
{
"target": 2,
"type": "h"
},
{
"target": 1,
"type": "t"
},
{
"control": 0,
"target": 1,
"type": "cnot"
},
{
"target": 0,
"type": "t"
},
{
"target": 1,
"type": "ti"
},
{
"control": 0,
"target": 1,
"type": "cnot"
},
{
"target": 2,
"type": "h"
},
{
"target": 0,
"type": "h"
},
{
"target": 1,
"type": "h"
},
{
"target": 2,
"type": "h"
},
{
"target": 0,
"type": "x"
},
{
"target": 1,
"type": "x"
},
{
"target": 2,
"type": "x"
},
{
"target": 2,
"type": "h"
},
{
"target": 2,
"type": "h"
},
{
"control": 1,
"target": 2,
"type": "cnot"
},
{
"target": 2,
"type": "ti"
},
{
"control": 0,
"target": 2,
"type": "cnot"
},
{
"target": 2,
"type": "t"
},
{
"control": 1,
"target": 2,
"type": "cnot"
},
{
"target": 2,
"type": "ti"
},
{
"control": 0,
"target": 2,
"type": "cnot"
},
{
"target": 2,
"type": "t"
},
{
"target": 2,
"type": "h"
},
{
"target": 1,
"type": "t"
},
{
"control": 0,
"target": 1,
"type": "cnot"
},
{
"target": 0,
"type": "t"
},
{
"target": 1,
"type": "ti"
},
{
"control": 0,
"target": 1,
"type": "cnot"
},
{
"target": 2,
"type": "h"
},
{
"target": 0,
"type": "x"
},
{
"target": 1,
"type": "x"
},
{
"target": 2,
"type": "x"
},
{
"target": 0,
"type": "h"
},
{
"target": 1,
"type": "h"
},
{
"target": 2,
"type": "h"
}
],
"results": [],
"basis_rotation_instructions": []
}
}
}
二回同じ問題を実行しました。計算結果は、
"measurementProbabilities": {
"000": 0.062,
"100": 0.144,
"010": 0.056,
"110": 0.044,
"001": 0.062,
"101": 0.05,
"011": 0.117,
"111": 0.465
},
のように、確率振幅を求めることができました。111が0.465となっています。
おすすめshot数
クラウドでイオントラップを利用する際の注意点は、値段が高いと言うことです。2020年10月現在で、動かすための費用は、1タスクに約30円+shotと呼ばれる計算回数*1円です。量子コンピュータの計算の場合、計算が一回で終わると言うことはあまりなく、確率分布を求めるために、複数回同じ回路を実行するのが普通です。そのため、shotは1000が多いのですが、それだと1タスクを実行するのに、1000円かかります。流石にそれだと用意した予算がなくなってしまうので、shotを50とか100とかにしておけば、大体1回の計算に50円とか100円で済みます。もちろん、計算の種類によりますが、よほどでない限りで、大学の教科書に出るような汎用計算だと十分かと思います。
まとめ
大学の教科書に出るような、汎用計算がどんどんできます。ぜひ超電導マシンと並行してイオントラップも使ってみましょう。