Rigettiで位相キックバック回路

量子コンピュータ業界はFTQCと呼ばれる誤り訂正ありの量子コンピュータへと向かい始めました。ここでは、FTQCのうち、暗号解読や量子化学計算などに利用される量子位相推定アルゴリズムを取り上げますが、その前段階として位相キックバックと呼ばれるテクニックを実機で確認します。

https://github.com/Blueqat/Blueqat-tutorials/blob/master/tutorial-ja/120_phase_kick_back_ja.ipynb

こちらのチュートリアルを参考とします。

量子コンピュータの文脈でたびたび出現する固有値問題ですが、ユニタリゲート$U$と対応する固有値は、位相$\theta$をもちいて、固有値$|\psi\rangle$として、

$$ U|\psi\rangle = e^{i\theta}|\psi\rangle $$

今回はチュートリアルの例題に合わせて、ユニタリーゲートが下記のゲートの場合の固有値の位相を求めてみます。 $$ U = \begin{bmatrix}1 & 0\ 0 & e^{i\theta}\end{bmatrix} $$

細かい内容は上記のチュートリアルを見てもらうと助かりますが、固有状態は$|1\rangle$で既知であるとして、解てみます。

位相キックバックでは制御Uゲートを準備します。

|0> --H--*--H--測定
         |
|1> -----U-----

出力の回路を重ね合わせで準備し、入力の回路に固有状態を入力します。そして、制御ユニタリを利用して位相キックバックを行います。位相キックバックされた後の量子状態は|1>の出現確率は位相でしか見れないので、位相情報を取り出す必要があります。今回は1量子ビットの量子フーリエ変換に対応するHゲートを適用します。

最終的に、Hゲートを適用した後の出力量子ビットの状態ベクトルは、

$$ |\psi_0\rangle = \frac{1}{2}\begin{bmatrix}1+e^{i\theta}\1-e^{i\theta}\end{bmatrix} $$

となりますので、位相は0もしくは1の出現確率をサンプルから求めることで三角関数の逆関数から位相を求めることができます。 早速実機を利用してみます。

まずはランダムな位相を決めて、シミュレータで解きます。

from blueqat import Circuit
import numpy as np

theta = np.random.rand()*np.pi
shots = 1000
res = Circuit(2).x[1].h[0].cphase(theta)[0,1].h[0].m[0].run(shots = shots)

p0 = res['00'] / shots
theta_est = np.arccos(2 * p0 - 1)

print("θ推定値  :", theta_est)
print("実際の値 :", theta)
res

シミュレータですとサンプリングでも結構いい精度で出せましたね。次に実機を準備します。今回はbraketをつかってblueqat cloud経由でAPIをたたいてみます。

from braket.circuits import Circuit
from braket.device_schema import GateModelParameters
from braket.device_schema.rigetti import RigettiDeviceParameters
from braket.device_schema.ionq import IonqDeviceParameters
import json
import urllib.request

f = open('../.pass', 'r', encoding='UTF-8')
API_KEY = f.read()[:-1]
f.close()

API_ENDPOINT = "https://cloudapi.blueqat.com/v2/"

def post_request(path, body):
    headers = {
        "Content-Type": "application/json",
        "X-Api-Key": API_KEY,
    }
    req = urllib.request.Request(
        API_ENDPOINT + path, json.dumps(body).encode(), headers
    )
    with urllib.request.urlopen(req) as res:
        body = res.read()
    return json.loads(body)

def get_quantum_tasks(body):
    path = "quantum-tasks/list"
    return post_request(path, params)


def get_quantum_task_status(id):
    path = "quantum-tasks/get/status"
    body = {
        "id": id,
    }
    return post_request(path, body)

def get_quantum_task(id):
    path = "quantum-tasks/get"
    body = {
        "id": id,
    }
    return post_request(path, body)

def create_quantum_task(body):
    path = "quantum-tasks/create"
    return post_request(path, body)

#circuit
circuit = Circuit().x(1).h(0).cphaseshift(0, 1, theta).h(0)

paradigm_parameters = GateModelParameters(
    qubitCount=circuit.qubit_count, disableQubitRewiring=False
)

# rigetti
dprig = RigettiDeviceParameters(paradigmParameters=paradigm_parameters)
dprig.json()

params = {
    "action": circuit.to_ir().json(),
    "device": "aws/rigetti/Aspen-9",
    "deviceParameters": dprig.json(),
    "shots": 1000,
    "taskGroup": "",
    "sendEmail": False,
}

result = create_quantum_task(params)
tid = get_quantum_tasks({"index":0})['tasks'][0]['id']
res = get_quantum_task(tid)
a = res['result']['measurements']

b = []
for i in a:
    b.append("".join(map(str, i)))
    
import collections
c = collections.Counter(b)
c
p0_2 = c['01'] / 1000
theta_est2 = np.arccos(2 * p0_2 - 1)

print("θ推定値  :", theta_est2)
print("実際の値 :", theta)

ある程度は計算できている気がしますが、全然違う答えが出ることも結構あります。。。実機での位相推定はIonQを今度はやってみたいと思います。以上です。

Yuichiro Minato
blueqat CEO/CTO 2015年総務省異能vation最終採択 2017年内閣府ImPACTプロジェクトPM補佐 2019年文科省さきがけ量子情報処理領域アドバイザー
Comments
Yuichiro Minato
blueqat CEO/CTO 2015年総務省異能vation最終採択 2017年内閣府ImPACTプロジェクトPM補佐 2019年文科省さきがけ量子情報処理領域アドバイザー
Related posts

blueqat Inc.

Shibuya Scramble Square 39F 2-24-12, Shibuya, Shibuya-ku, Tokyo
Contact: info@blueqat.com