PennyLane : 初級 Tutorials : プラグインとハイブリッド計算

PennyLane 初級 Tutorials : プラグインとハイブリッド計算 (翻訳)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 10/27/2019

* 本ページは、PennyLane : Tutorials : Learn PennyLane の次のページを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

$$
\def\bra#1{\mathinner{\left\langle{#1}\right|}}
\def\ket#1{\mathinner{\left|{#1}\right\rangle}}
\def\braket#1#2{\mathinner{\left\langle{#1}\middle|#2\right\rangle}}
$$

 

初級 Tutorials : プラグインとハイブリッド計算

このチュートリアルは幾つかの PennyLane プラグインを組み合わせることによりハイブリッド計算の概念を導入します。最初に PennyLane の Strawberry Fields プラグイン を紹介して非-Gaussian 光量子回路を調べるためにそれを使用します。それから完全にハイブリッドな計算を作成して最適化するために、この光量子回路を — 幾つかの古典的処理と一緒に — 量子ビット回路と組み合わせます。

Note
貴方自身のコンピュータ上でこのチュートリアルに沿ってフォローするためには、PennyLane-SF プラグイン を必要とします、PennyLane を使用して Strawberry Fields Fock バックエンドにアクセスするために。それは pip を通してインストールできます :

pip install pennylane-sf

 

非-Gaussian 回路

最初に光量子回路を考えます、これは 量子ビット回転 回路に考え方で類似しています :

これをステップ毎に、分解します :

  1. 2 つの qumode サブシステムで計算を開始します。PennyLane では、量子サブシステムを参照するために簡潔な ‘wire’ を使用します、それらが qumode、量子ビット、あるいは任意の他の種類の量子レジスタであっても。
  2. 状態 $\left|1,0\right\rangle$ を準備します。つまり、最初のワイヤ (wire 0) はシングル光子状態で、一方 2 番目のワイヤ (wire 1) は真空状態として準備されます。前者の状態は非 Gaussian で、’strawberryfields.fock’ バックエンド・デバイスの使用を必要とします。
  3. それから 両者のワイヤは beamsplitter 上の incident で、自由パラメータ $\theta$ と $\phi$ を持ちます。ここで、beamsplitter transmission 振幅は $t=\cos\theta$、そして reflection 振幅は $r=e^{i\phi}\sin\theta$ という慣習を持ちます。演算慣習の完全なリストは 量子演算 を見てください。
  4. 最後に、2 番目のワイヤの 平均光子数 $\left\langle \hat{n}\right\rangle$ を測定します、ここで
    $$\hat{n} = \hat{a}^\dagger\hat{a}$$

    は number 演算子で、$\hat{n}\left|n\right\rangle = n\left|n\right\rangle$ のような Fock 基底 number 状態上で作用します。

このチュートリアルの目的は beamsplitter パラメータ $(\theta, \phi)$ を、2 番目のワイヤの期待される光子数が 最大化 されるように最適化することです。beamsplitter は合計光子数を保存する passive optical 要素ですので、これは出力状態 $\left|0,1\right\rangle$ に対応します — i.e., 最初のワイヤからの incident 光子が 2 番目のワイヤに「リダイレクト」されたときです。

 

正確な計算

後の数値的結果と比較するために、最初に解析的に何が起きるかを考えることができます。回路の初期状態は $\left|\psi_0\right\rangle=\left|1,0\right\rangle$ で、そして系の出力状態は形式 $\left|\psi\right\rangle = a\left|1, 0\right\rangle + b\left|0,1\right\rangle$ にあります、ここで $|a|^2+|b|^2=1$。こうして出力状態を計算基底のベクトルとして書いても良いです、 $\left|\psi\right\rangle = \begin{bmatrix}a & b\end{bmatrix}^T$。

beamsplitter は次のように 2-次元部分空間上で作用します :

\[
\begin{split}\left|\psi\right\rangle = B(\theta, \phi)\left|1, 0\right\rangle = \begin{bmatrix}
\cos\theta & -e^{-i\phi}\sin\theta\\
e^{i\phi}\sin\theta & \cos\theta
\end{bmatrix}\begin{bmatrix} 1\\ 0\end{bmatrix} = \begin{bmatrix}
\cos\theta\\
e^{i\phi} \sin\theta
\end{bmatrix}\end{split}
\]

更に、2 番目のワイヤの平均光子数は :

\[
\left\langle{\hat{n}_1}\right\rangle = \langle{\psi}\mid{\hat{n}_1}\mid{\psi}\rangle = |e^{i\phi} \sin\theta|^2
\langle{0,1}\mid{\hat{n}_1}\mid{0,1}\rangle = \sin^2 \theta.
\]

従って、以下を見ることができます :

  1. $0\leq \left\langle \hat{n}_1\right\rangle\leq 1$ : 量子回路の出力は 0 と 1 の間にバインドされます ;
  2. $\frac{\partial}{\partial \phi} \left\langle \hat{n}_1\right\rangle=0$ : 量子回路の出力は beamsplitter 位相 $\phi$ からは独立です ;
  3. 上の量子回路の出力は $\theta=(2m+1)\pi/2$ であるとき最大化されます。

 

プラグイン・デバイスをロードする

PennyLane が基本的な量子ビット・シミュレータ (‘default.qubit’) と基本的な CV Gaussian シミュレータ (‘default.gaussian’) を提供する一方で、PennyLane の真のパワーはその プラグイン・エコシステム に由来し、量子計算に様々な量子シミュレータとハードウェアデバイス上で実行することを可能にします。

この回路のために、QNode を構築するために ‘strawberryfields.fock’ デバイスを使用していきます。これは Strawberry Fields Fock バックエンドを使用して基礎となる量子計算が遂行されることを可能にします。

いつものように、PennyLane と PennyLane により提供される NumPy のラップされたバージョンをインポートすることから始めます :

import pennylane as qml
from pennylane import numpy as np

次に、量子ノードを実行するデバイスを作成します。これは PennyLane では容易です ; PennyLane-SF プラグインがインストールされればすぐに、’strawberryfields.fock’ デバイスがロードできます — 追加のコマンドや必要なライブラリ・インポートはありません。

dev_fock = qml.device("strawberryfields.fock", wires=2, cutoff_dim=2)

PennyLane で提供されるデフォルトデバイスと比べて、’strawberryfields.fock’ デバイスは追加のキーワード引数を必要とします :

  • cutoff_dim: 量子シミュレーションを遂行するために使用される Fock space truncation

Note
外部プラグインで提供されるデバイスは追加の引数とキーワード引数を要求するかもしれません — より詳細はプラグイン・ドキュメントを調べてください。

 

量子ノードを構築する

デバイスを初期化した今、量子ノードを構築できます。他のチュートリアルのように、(上の回路でエンコードされる) 量子関数を Strawberry Fields 上で動作する量子ノードに変換するために qnode デコレータを使用します。

@qml.qnode(dev_fock)
def photon_redirection(params):
    qml.FockState(1, wires=0)
    qml.Beamsplitter(params[0], params[1], wires=[0, 1])
    return qml.expval(qml.NumberOperator(1))

‘strawberryfields.fock’ デバイスは PennyLane で提供される総ての CV オブジェクトをサポートします ; CV 演算 を見てください。

 

最適化

今は光子 redirection を実行するために組込み PennyLane optimizer の一つを使用しましょう私達は 2 番目のワイヤの平均光子数を最大化することを望みますので、回路出力の負 (の値) を最小化するコスト関数を定義できます。

def cost(params):
    return -photon_redirection(params)

最適化を始めるために、次の小さい初期値を選択します :

init_params = np.array([0.01, 0.01])
print(cost(init_params))
-9.999666671111085e-05

ここで、ゼロに非常に近い $\theta$ と $\phi$ の値を選択します ; これは $B(\theta,\phi)\approx I$ という結果になり、そして量子回路の出力は $\left|1, 0\right\rangle$ に非常に近くなります — i.e., 回路は光子を first モードの状態にします。

何故 $\theta=0$ と $\phi=0$ を選択しないのでしょう?

パラメータ空間のこのポイントで、$\left\langle \hat{n}_1\right\rangle = 0$、そして $\frac{d}{d\theta}\left\langle{\hat{n}_1}\right\rangle|_{\theta=0}=2\sin\theta\cos\theta|_{\theta=0}=0$ です。それらの初期パラメータ値で勾配はゼロですので、最適化アルゴリズムは決して最大値から降下しません。

これは PennyLane を直接使用して検証することもできます :

dphoton_redirection = qml.grad(photon_redirection, argnum=0)
print(dphoton_redirection([0.0, 0.0]))
[0.0, 0.0]

さて、GradientDescentOptimizer を使用して、そして 100 最適化ステップに渡り回路パラメータを更新しましょう。

# initialise the optimizer
opt = qml.GradientDescentOptimizer(stepsize=0.4)

# set the number of steps
steps = 100
# set the initial parameter values
params = init_params

for i in range(steps):
    # update the circuit parameters
    params = opt.step(cost, params)

    if (i + 1) % 5 == 0:
        print("Cost after step {:5d}: {: .7f}".format(i + 1, cost(params)))

print("Optimized rotation angles: {}".format(params))
Cost after step     5: -0.0349558
Cost after step    10: -0.9969017
Cost after step    15: -1.0000000
Cost after step    20: -1.0000000
Cost after step    25: -1.0000000
Cost after step    30: -1.0000000
Cost after step    35: -1.0000000
Cost after step    40: -1.0000000
Cost after step    45: -1.0000000
Cost after step    50: -1.0000000
Cost after step    55: -1.0000000
Cost after step    60: -1.0000000
Cost after step    65: -1.0000000
Cost after step    70: -1.0000000
Cost after step    75: -1.0000000
Cost after step    80: -1.0000000
Cost after step    85: -1.0000000
Cost after step    90: -1.0000000
Cost after step    95: -1.0000000
Cost after step   100: -1.0000000
Optimized rotation angles: [1.57079633 0.01      ]

これを上の 正確な計算 と比較すると、これは $\theta=\pi/2$ の最適条件の値に近いです、一方で $\phi$ の値は変わりません — $\left\langle \hat{n}_1\right\rangle$ が $\phi$ から独立であるという事実と矛盾しません。

 

ハイブリッド計算

PennyLane の能力を実際にハイライトするために、今は 量子ビット回転チュートリアル からの 量子ビット回転 QNode を上の CV 光子-redirection、そしてある古典的処理を組み合わせましょう、真にハイブリッドな計算モデルを生成するために。

最初に、3 つのステップから成る計算を定義します ; 2 つの量子ノード (量子ビット回転と光子 redirection 回路、それぞれ ‘default.qubit’ と ‘strawberryfields.fock’ デバイス上で動作する)、そして NumPy を使用してそれら 2 つの入力の自乗差を単純に返す古典的関数を伴います :

# create the devices
dev_qubit = qml.device("default.qubit", wires=1)
dev_fock = qml.device("strawberryfields.fock", wires=2, cutoff_dim=10)


@qml.qnode(dev_qubit)
def qubit_rotation(phi1, phi2):
    """Qubit rotation QNode"""
    qml.RX(phi1, wires=0)
    qml.RY(phi2, wires=0)
    return qml.expval(qml.PauliZ(0))


@qml.qnode(dev_fock)
def photon_redirection(params):
    """The photon redirection QNode"""
    qml.FockState(1, wires=0)
    qml.Beamsplitter(params[0], params[1], wires=[0, 1])
    return qml.expval(qml.NumberOperator(1))


def squared_difference(x, y):
    """Classical node to compute the squared
    difference between two inputs"""
    return np.abs(x - y) ** 2

今、3 つのサブコンポーネントを一緒にリンクして、最適化に関連する目的関数を定義することができます。ここでは、次のハイブリッド量子古典的最適化を遂行することを望みます :

  • 量子ビット回路は固定回転角 $\phi_1$ と $\phi_2$ を含みます。
  • 光子-redirection 回路は 2 つの自由パラメータを含みます、beamsplitter 角度 $\theta$ と $\phi$ です、これらが最適化されます。
  • それから両者の QNode の出力は古典的ノードに供給され、2 つの量子関数の自乗差を返します。
  • 最後に、optimizer は自由パラメータ $\theta$ と $\phi$ に関する計算全体の勾配を計算し、そしてそれらの値を更新します。

本質的には、光子-redirection 回路を量子回転回路と 同じ期待値 を返すように最適化しています、それらは 2 つの完全に独立した量子系ですが。

この計算グラフを次の関数に変換できます、これは 3 つのノードを単一のハイブリッド計算に結合します。下で、デフォルト値 $\phi_1=0.5$, $\phi_2=0.1$ を選択します :

def cost(params, phi1=0.5, phi2=0.1):
    """Returns the squared difference between
    the photon-redirection and qubit-rotation QNodes, for
    fixed values of the qubit rotation angles phi1 and phi2"""
    qubit_result = qubit_rotation(phi1, phi2)
    photon_result = photon_redirection(params)
    return squared_difference(qubit_result, photon_result)

今、100 ステップの最適化を遂行するために 組込み GradientDescentOptimizer を使用します。前のように、$\theta=0.01$, $\phi=0.01$ の初期 beamsplitter パラメータを選択します。

# initialise the optimizer
opt = qml.GradientDescentOptimizer(stepsize=0.4)

# set the number of steps
steps = 100
# set the initial parameter values
params = np.array([0.01, 0.01])

for i in range(steps):
    # update the circuit parameters
    params = opt.step(cost, params)

    if (i + 1) % 5 == 0:
        print("Cost after step {:5d}: {: .7f}".format(i + 1, cost(params)))

print("Optimized rotation angles: {}".format(params))
Cost after step     5:  0.2154539
Cost after step    10:  0.0000982
Cost after step    15:  0.0000011
Cost after step    20:  0.0000000
Cost after step    25:  0.0000000
Cost after step    30:  0.0000000
Cost after step    35:  0.0000000
Cost after step    40:  0.0000000
Cost after step    45:  0.0000000
Cost after step    50:  0.0000000
Cost after step    55:  0.0000000
Cost after step    60:  0.0000000
Cost after step    65:  0.0000000
Cost after step    70:  0.0000000
Cost after step    75:  0.0000000
Cost after step    80:  0.0000000
Cost after step    85:  0.0000000
Cost after step    90:  0.0000000
Cost after step    95:  0.0000000
Cost after step   100:  0.0000000
Optimized rotation angles: [1.20671364 0.01      ]

これを光子 redirection QNode に代入するとそれは量子ビット回転 QNode と同じ出力を今では生成することを示します :

result = [1.20671364, 0.01]
print(photon_redirection(result))
print(qubit_rotation(0.5, 0.1))
0.8731983021146449
0.8731983044562817

This is just a simple example of the kind of hybrid computation that can be carried out in PennyLane. Quantum nodes (bound to different devices) and classical functions can be combined in many different and interesting ways.

 

以上