進捗のようなもの

やったこと書きます

PennyLaneで量子状態の最適化をやってみた

はじめに

今回は、1量子ビットの量子状態を最適化します。
カナダ/トロントにあるXanadu社が開発した量子機械学習のプラットフォーム"PennyLane"のチュートリアルを兼ねています。

pennylane.ai


\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}}

PennyLaneについて

PannyLaneのコンセプトとして、

  • Hybrid computation (古典・量子ハイブリッド)
  • Quantum nodes (量子ノード)
  • Quantum embeddings (量子畳み込み)
  • Variational circuits (変分回路)
  • Quantum gradients (量子勾配)

が挙げられています。

入力に古典的な情報を取り、出力として古典的な情報を生成する量子回路をもつ量子ノードを導入し、従来からある古典ノードを組み合わせることでハイブリッド計算を実現しているようです。
また、最適化や機械学習で必要となる勾配計算を量子ノードでも計算することが可能です。

コンセプトについて詳細はこちらを確認してみてください。

インストール

pipでインストールできます。

# install the latest released version of PennyLane
pip install pennylane --upgrade

やってみよう

公式チュートリアルの量子状態の最適化をやってみます!

pennylane.ai

ここでは、シングル量子ビットの量子状態を \ket{0}から \ket{1}に反転させるためにRxゲートとRyゲートの2つの量子ゲートを最適化します。

f:id:SJSY:20191225005220p:plain:w300

RxゲートとRyゲートは

 R_x( \phi_1 )=\begin{bmatrix}\cos( \frac{\phi_1}{2}) & - i \sin( \frac{\phi_1}{2}) \\\ -i \sin( \frac{\phi_1}{2}) & \cos( \frac{\phi_1}{2}) \end{bmatrix}
 R_y(\phi_2)=\begin{bmatrix}\cos( \frac{\phi_2}{2}) & -  \sin( \frac{\phi_2}{2}) \\\  \sin( \frac{\phi_2}{2}) & \cos( \frac{\phi_2}{2}) \end{bmatrix}

と書け、 \ket{0}に作用させた後の状態は次のようになります。

 \ket{\psi}=R_y(\phi_2)R_x(\phi_1)\ket{0}

最後に、パウリZ演算子の期待値 \bra{\psi}\sigma_z\ket{\psi}を計算します。

 \bra{\psi}\sigma_z\ket{\psi} = \cos(\phi_1) \cos(\phi_2)

出力は\phi_1 \phi_2に依存しており、1( \ket{\psi} = \ket{0}のとき)から−1( \ket{\psi} = \ket{1}のとき)の間の値をとります。

では、コードです。

import pennylane as qml
from pennylane import numpy as np

(重要) NumPyは標準Numpyではなく、PennyLaneでラッパーされたバージョンのNumPyをインポートするようにします。

dev1 = qml.device("default.qubit", wires=1)

回路を作る前にdeviceを初期化します。deviceはIBMQのハードたシミュレータから選べることができますが、今回はシンプルな'default.qubit'を使います。
また、wires=1でシングル量子ビットを設定しています。

続いて、量子ノードの構築です。

@qml.qnode(dev1)
def circuit(params):
    qml.RX(params[0], wires=0)
    qml.RY(params[1], wires=0)
    return qml.expval(qml.PauliZ(0))

量子回路を定義した関数の上にqnode()デコレータを適用することで、ddeviceで実行されるQNodeに変化します。 関数の中は上で示した回路になっています。

続いて、量子勾配の計算を確かめてみます。

dcircuit = qml.grad(circuit, argnum=0)
print(dcircuit([0.54, 0.12]))

Out:

 [-0.5104386525165021, -0.10267819945693202]

QNodeでカプセル化した関数回路の勾配は、関数自体の評価に使用したデバイスを使用して評価できます。
PennyLaneでは、解析的微分と数値的微分が両方とも自動的に行われいます。

def cost(var):
    return circuit(var)

最適化に使用するコスト関数を定義します。

init_params = np.array([0.011, 0.012])
print(cost(init_params))

Out:

 0.9998675058299389

1に近い値となるようなパラメータ初期値を設定します。

# 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))

Out:

Cost after step     5:  0.9961778
Cost after step    10:  0.8974944
Cost after step    15:  0.1440490
Cost after step    20: -0.1536720
Cost after step    25: -0.9152496
Cost after step    30: -0.9994046
Cost after step    35: -0.9999964
Cost after step    40: -1.0000000
Cost after step    45: -1.0000000
Cost after step    50: -1.0000000
....
Optimized rotation angles: [9.35979013e-17 3.14159265e+00]
print(circuit(params))

Out:

-1.0

40ステップくらいでパラメータが最適化されて、 \ket{1}になっていることが確認できました!!!

まとめ

PennyLaneのチュートリアルをやってみました。 他にもいろいろデモがあるみたいなので、勉強してみようかと思います。
量子機械学習、最適化がんばります。