何も調整しないと
state tomography fidelity on ibmq_manila = 0.2373 ± 0.0014
という結果に。error mitigation などを工夫するようにとのことだが、あんまり実感がない。
を何とかしろってことなんだろうな・・・。シミュレータで行うと
state tomography fidelity on qasm_simulator = 0.0003 ± 0.0002
とかで、
ある意味では理想的な測定結果になる。
qiskit.quantum_info.state_fidelity — Qiskit 0.37.1 documentation の解釈が難しいが、密度行列 $\rho_1$, $\rho_2$ があるとして、$\rho_1$ が純粋状態による $\rho_1 = \ket{\psi_1}\bra{\psi_1}$ とすると、fidelity は $F(\rho_1, \rho_2) = \braket{\psi_1|\rho_2|\psi_1}$ になるとのこと。$\rho_2$ も純粋状態による $\rho_2 = \ket{\psi_2}\bra{\psi_2}$ とすると、$F(\rho_1, \rho_2) = |\braket{\psi_2|\psi_1}|^2$ になるので、$\ket{\psi_1} = \ket{\psi_2}$ なら fidelity は 1 になるし、直交していれば 0 になるという値である。
今回のコンテストは、時間発展の結果としては $\ket{110}$ が期待されているのでこれとの fidelity をとっている。但し、短い Trotter 展開では上記のように $\ket{011}$ になるので、ある程度は長くする必要がある。しかしそれだとエラーが増えるというジレンマがある。
state_tomography_circuits
を通すと、色んな基底で測定するための回路が作成される。リストの最後は Z 基底での測定に対応するようだ。1 量子ビットのケースでは、順に X 基底、Y 基底、Z 基底での測定用回路が生成された。
課題を numpy
と scipy
で記述して、実際にはどういったことを計算したいのか具体的につかんでみよう:
import numpy as np from scipy.linalg import expm I = np.array([ [1, 0], [0, 1] ]) X = np.array([ [0, 1], [1, 0] ]) Y = np.array([ [0, -1.j], [1.j, 0] ]) Z = np.array([ [1, 0], [0, -1] ]) Zero = np.array([1, 0]) One = np.array([0, 1]) # H = (I^X^X) + (X^X^I) + (I^Y^Y) + (Y^Y^I) + (I^Z^Z) + (Z^Z^I) IXX = np.kron(np.kron(I, X), X) XXI = np.kron(np.kron(X, X), I) IYY = np.kron(np.kron(I, Y), Y) YYI = np.kron(np.kron(Y, Y), I) IZZ = np.kron(np.kron(I, Z), Z) ZZI = np.kron(np.kron(Z, Z), I) H = IXX + XXI + IYY + YYI + IZZ + ZZI t = np.pi U = expm(-1.j * t * H) # |110> init_state = np.kron(np.kron(One, One), Zero) fin_state = np.round(U@init_state, 2) print('init_state:', init_state) print('ideal fin_state:', fin_state) reps = 4 partial_approx_U = expm(-1.j * t/reps * IXX) @ \ expm(-1.j * t/reps * XXI) @ \ expm(-1.j * t/reps * IYY) @ \ expm(-1.j * t/reps * YYI) @ \ expm(-1.j * t/reps * IZZ) @ \ expm(-1.j * t/reps * ZZI) approx_U = partial_approx_U for _ in range(reps-1): approx_U = approx_U@partial_approx_U approx_fin_state = np.round(approx_U@init_state, 2) print('approx fin_state:', approx_fin_state)
の出力が
init_state: [0 0 0 0 0 0 1 0]
ideal fin_state: [ 0.+0.j 0.+0.j 0.+0.j -0.-0.j 0.+0.j 0.+0.j 1.-0.j 0.+0.j]
approx fin_state: [ 0.+0.j 0.+0.j 0.+0.j -1.+0.j 0.+0.j -0.-0.j -0.-0.j 0.+0.j]
となるので、本来は $\ket{110}$ から $\ket{110}$ になるはずなのだが、Trotter 展開で近似することで $\ket{011}$ になるので、何かしら改善が必要であることが示唆されている。reps = 16
くらいから良い感じの近似にはなってくる。