PennyLane v0.16.0
PennyLaneの最新versionがリリースされました。
色々機能が入っていますが、今回は量子回路の実行回数が見積もれるspec機能を使ってみます。
コード
dev = qml.device('default.qubit', wires=4)
@qml.qnode(dev, diff_method='parameter-shift')
def circuit(x, y):
qml.RX(x[0], wires=0)
qml.Toffoli(wires=(0, 1, 2))
qml.CRY(x[1], wires=(0, 1))
qml.Rot(x[2], x[3], y, wires=0)
return qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliX(1))
x = np.array([0.05, 0.1, 0.2, 0.3], requires_grad=True)
y = np.array(0.4, requires_grad=False)
specs_func = qml.specs(circuit)
info = specs_func(x, y)
qml.specs
は、qnodeを受け取って、その情報を返す関数のようです。
ここではqnodeがパラメータxとyを持っています。
ただしyについては requires_grad=False
となっているので、定数として扱います。
結局、変分パラメータとして動的に動くのはx(4要素ベクトル)だけです。
回路全体のパラメータは4個あることになります。
これをパラメータシフトルールで勾配計算しながら最適化することを考えます。
まず今のパラメータにおけるコストを知るために、回路を1度実行します。
次にパラメータを動かすための勾配情報をパラメータシフトルールで得ますので、
パラメータx2 回の回路実行が必要となります。
合計で 1 + 4 x 2 = 9 回の回路実行・・・と思われるのですが?
specの結果を見てみます。
info
{'gate_sizes': defaultdict(int, {1: 2, 3: 1, 2: 1}),
'gate_types': defaultdict(int, {'RX': 1, 'Toffoli': 1, 'CRY': 1, 'Rot': 1}),
'num_operations': 4,
'num_observables': 2,
'num_diagonalizing_gates': 1,
'num_used_wires': 3,
'depth': 4,
'num_trainable_params': 4,
'num_parameter_shift_executions': 11,
'num_device_wires': 4,
'device_name': 'default.qubit',
'diff_method': 'parameter-shift'}
注目するのは
num_parameter_shift_executions': 11
です。9回ではないようです。
なぜ?と思い、質問したところ、回答がありました。
https://discuss.pennylane.ai/t/the-number-of-circuit-execution-in-parameter-shift/1144/3
実は制御ゲート(今回だとCRYがあります)の場合は、パラメータシフトルールは2回ではなく4回の回路実行が必要となるそうです。
今回、
RXは1パラメータなので、2回
CRYは1パラメータだが、制御ゲートなので4回
ROTは2パラメータなので4回
となり、これにコスト計算のための1回を加えると 2+4+4+1 = 11 となるわけです。
計算が合いました。
制御ゲート+変分パラメータ を多用すると、計算が重くなってしまいますね。注意しましょう!
spec機能での見積もりはなかなか重要そうです。
例えば有料のQPUやシミュレータを使う場合、この実行回数におよそ比例して料金がかかります。(計算時間も)
まとめ
PennyLane v0.16.0を使ってみた。
spec機能はなかなか便利そう。