回路の途中の状態ベクトルをメモる
qiskitでは、回路実行時にstatevctor simulatorを使うと、状態ベクトルを簡単に取り出すことができます。
しかし実機動作(サンプリング)を考えると、qasm simulatorを使いたいことも多いです。
この場合、サンプリングは出来ますが、状態ベクトルがわからないです。デバッグがめんどくさい。
使い分ければいいじゃないか、という話なのですが、
- qasm simulatorは回路の最後にmeasureが必須
- statevctor simulatorは回路の最後にmeasureがあると射影測定後の状態ベクトルしか得られない
ということで、いまいちやりづらいです。
そこで、qasm simulatorで回路の途中の状態ベクトルを取り出す方法を記載します。
この方法はシミュレーター限定ですが、statevector simulatorに限らず、qasm simulatorでも使えます。
snapshot
回路の任意の位置で snapshot という操作を入れます。(ゲートのような感覚です)
circuit.snapshot('my_sv',snapshot_type='statevector') # get a snapshot of present statevector
snapshotはいくつでも入れられます。
ここで、回路の最後に measure を入れても構いません。
(途中で入れると、当然そこで射影測定により状態ベクトルが変わりますので気をつけてください)
次に、回路を実行します。
results = execute(circuit, backend, shots=1).result()
結果の変数resultsの中身に、以下の呪文でアクセスします。
statevec = results.data()['snapshots']['statevector']['my_sv'][k] # 2^nqubits complex vector |ψ>
ここで、kはsnapshotを複数とった場合に何番目を取り出すかを意味します。
出力結果は複素ベクトル(状態ベクトル)になっていますので、期待値計算は簡単です。
expectation = np.real(np.vdot(statevec,np.dot(obs_mat,statevec))) # Real[<ψ|O|ψ>]
obs_matはオブザーバブルの行列表現です。
当然、measureを入れておいてqasm simuator で実行すれば、サンプリングと状態ベクトルが同時に取れます。
出力イメージ。ヒストグラムと、状態ベクトルのオブザーバブル期待値
なお、逆にstate vector simulatorでサンプリングをすることは簡単です。
Statevecotr のクラスに sample_counts というメソッドがあるようです。