各Labの記録
- 参加結果の記事:Qiskit Global Summer School 2023 参加記録
- Lab1:記事なし。かなり基礎的な内容だった気がするので
- Lab2:Qiskit Global Summer School 2023 Lab2 参加記録
- Lab3:Qiskit Global Summer School 2023 Lab3 参加記録
- Lab4:Qiskit Global Summer School 2023 Lab4 参加記録
- Lab5:Qiskit Global Summer School 2023 Lab5 参加記録
まえがき
Qiskit Global Summer School 2023 Lab4の記録です。
Lab 4 : Iterative phase estimation
- 反復位相推定アルゴリズムの簡単なバージョンを実装するラボ。
- 動的回路機能を使う。
- IBM Spring Challenge 2023のLab3の転用なので、わからなかったらIBM Quantum Challenge: Spring 2023 参加記録を見ればいいかも。
背景(翻訳)
量子位相推定(QPE)アルゴリズムは、最も重要で有名な量子アルゴリズムの1つである。Shorの因数分解アルゴリズムの重要なサブルーチンであり、量子シミュレーションのアルゴリズムでもある。このアルゴリズムの教科書的なバージョンは、必要な精度に応じてスケーリングされる補助的な量子ビットの数を使用するため、量子ビットの数や接続性が制限された今日のノイズの多いデバイスで実行するのは困難な回路になる。
反復位相推定(IPE)は、補助量子ビットを1つだけ必要とするQPEの変種である。IPEでは、補助量子ビットが繰り返し測定され、その測定結果が将来の量子演算の指針となる。このような古典的なフィードフォワードは、以前はIBMの量子プロセッサーで実行することは不可能だったが、最近導入された動的回路機能を使えば可能になる。
他の位相推定アルゴリズムと同様に、IPEは以下の問題を解決するように設計されている:
問題文: ユニタリー行列Uと、未知の固有値を持つUの固有状態|Ψ⟩が与えられたとき、φの値を推定せよ。
この問題では、いくつかの重要な点を明確にする必要がある。つまりUと|Ψ⟩がどのように指定されるかである。
UはUを実装する量子回路として与えられ、実際、我々は正の整数tに対してcontrolled- の演算を効率的に実装する能力を持っていると仮定する。固有状態も量子回路として与えられる。
簡単のために、まずφが厳密な二項展開ができると仮定してみよう。
ここで、最後の等式では基数2の「小数点」表記を用いている。簡単のために、Uが1量子ビットに作用するユニタリー演算子であるとする(ここで述べることは、Uが複数の量子ビットに作用する場合にも当てはまる)。IPEは補助量子ビットを必要とするので、q0とq1の2つの量子ビットの系が必要になる。q0は補助量子ビットで、q1はUが作用する物理系を表す。
ここで、q0を状態|+⟩に、q1を状態|Ψ⟩に初期化したとする。q0をコントロール、q1をターゲットとしてcontrolled-ゲートを適用するとどうなるか?|Ψ⟩は固有値を持つUの固有状態なので、次のようになる。
つまり、システム量子ビットの状態は変化せず、の位相が補助量子ビットの状態に「キックバック」されたことになる。
さて、次のことに注意してほしい。
最後の等式では、任意の整数nに対してであるため、位相の「10進数」表現の整数部分は消えている。たとえば、
t=0の場合、位相は
t=1の場合、位相は
t=2の場合、位相は
t=m-1の場合、位相は
最後のt=m-1の場合、位相はとなり、の場合は1、の場合は-1となる。最初のケースでは、補助量子ビットq0は|+⟩状態にあり、2番目のケースでは|-⟩状態にある。したがって、Pauli X基底で量子ビットを測定すれば、最初のケースでは0を測定し、2番目のケースでは1を測定するようになり、100%の成功率でこれらのケースを区別できる。測定されたビットはに等しくなる。
Pauli X基底での測定は、量子ビットを測定する前にアダマールゲートを実行することで行われる。
実装
固有値を持つ固有状態|Ψ⟩=|1⟩を使う。つまり𝜑=1/4=0.01=0.𝜑1𝜑2となる。
𝜑は2ビットで正確に表現できるので、量子回路の実装では2ビットの古典レジスタを使う。
q0が補助量子ビット、q1が|Ψ⟩。
ex1
UゲートとしてSゲートを使って反復位相推定を行う。
controlled-SゲートはCPhaseGate
を使えば良い。
from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister import numpy as np def step_1_circuit(qr: QuantumRegister, cr: ClassicalRegister) -> QuantumCircuit: # qr is a quantum register with 2 qubits # cr is a classical register with 2 bits qc = QuantumCircuit(qr, cr) ####### your code goes here ####### qc.h(0) qc.x(1) qc.cp(np.pi, 0, 1) qc.h(0) qc.measure(0,0) return qc qr = QuantumRegister(2, "q") cr = ClassicalRegister(2, "c") qc = QuantumCircuit(qr, cr) qc = step_1_circuit(qr, cr) qc.draw("mpl")
ex2
def step_2_circuit(qr: QuantumRegister, cr: ClassicalRegister) -> QuantumCircuit: # qr is a quantum register with 2 qubits # cr is a classical register with 2 bits # begin with the circuit from Step 1 qc = step_1_circuit(qr, cr) ####### your code goes here ####### qc.reset(qr[0]) qc.h(qr[0]) with qc.if_test((cr[0], 0)) as else_: # 0を測定したら、正しいので何もしない pass with else_: # 1を測定したら、-pi/2で位相補正する qc.rz(-np.pi/2, qr[0]) return qc qr = QuantumRegister(2, "q") cr = ClassicalRegister(2, "c") qc = QuantumCircuit(qr, cr) qc = step_2_circuit(qr, cr) qc.draw("mpl")
さて、この回路をAerSimulatorで実行してみる。
from qiskit_aer import AerSimulator sim = AerSimulator() job = sim.run(qc, shots=1000) result = job.result() counts = result.get_counts() counts # {'01': 1000}
結果は 01
となり、𝜑=1/4=0.01=0.𝜑1𝜑2 を正しく推定できる回路を作ることができた。
ex3
Tゲートの位相を推定するIPEを作れという問題。
これ以降は以前の問題と同じと気づいたので詳細は省略。この回路は何ビット必要か?固有状態は?など、詳しくはIBM Quantum Challenge: Spring 2023 参加記録のLab3のExercise 3を参照。
TゲートのIPE回路は以下になる。
from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister import numpy as np def t_gate_ipe_circuit(qr: QuantumRegister, cr: ClassicalRegister) -> QuantumCircuit: # qr is a quantum register with 2 qubits # cr is a classical register with 3 bits qc = QuantumCircuit(qr, cr) ####### your code goes here ####### """𝜑1のステップ""" # 初期化 qc.h(qr[0]) qc.x(qr[1]) # 𝜑1の推定 qc.cp(np.pi, qr[0], qr[1]) qc.h(qr[0]) qc.measure(qr[0], cr[0]) """𝜑2のステップ""" # 初期化 qc.reset(qr[0]) qc.h(qr[0]) # Z軸周りの角度wの回転で位相補正 with qc.if_test((cr[0], 1)): qc.p(-2*np.pi/(2**2), qr[0]) # 𝜑2の推定 qc.cp(np.pi/(2**1), qr[0], qr[1]) qc.h(qr[0]) qc.measure(qr[0], cr[1]) """𝜑3のステップ""" # 初期化 qc.reset(qr[0]) qc.h(qr[0]) # Z軸周りの角度wの回転で位相補正 with qc.if_test((cr[0], 1)): qc.p(-2*np.pi/(2**3), qr[0]) with qc.if_test((cr[1], 1)): qc.p(-2*np.pi/(2**2), qr[0]) # 𝜑3の推定 qc.cp(np.pi/(2**2), qr[0], qr[1]) qc.h(qr[0]) qc.measure(qr[0], cr[2]) return qc qr = QuantumRegister(2, "q") cr = ClassicalRegister(3, "c") qc = QuantumCircuit(qr, cr) qc = t_gate_ipe_circuit(qr, cr) qc.draw("mpl")
from qiskit_aer import AerSimulator sim = AerSimulator() job = sim.run(qc, shots=1000) result = job.result() counts = result.get_counts() counts # {'001': 1000}
ex4
詳しくはIBM Quantum Challenge: Spring 2023 参加記録のLab3のExercise 4を参照。
ex5
詳しくはIBM Quantum Challenge: Spring 2023 参加記録のLab3のExercise 5を参照。
ex6(ungraded)
ここまでに構築したIPE回路は、特定のゲートと特定の精度ビット数用に設計されたものであった。ここで一般化して、異なるゲートと精度レベルを扱える一般的なIPEルーチンを実装してみよう。
次の関数を完成させて、一般化された IPE ルーチンを実装しよう。以下の入力を受け取る:
qr
: 量子レジスタ。最初の量子ビットは補助量子ビット、残りはシステム量子ビットとする。cr
: 古典レジスタ。長さは希望する精度のビット数を示す。controlled_unitaries
:t=0,...,m-1に対してcontrolled-を実装したゲートのリスト。state_prep
:システム量子ビットの状態を初期化するためのゲート。
from qiskit.circuit import Gate def iterative_phase_estimation( qr: QuantumRegister, cr: ClassicalRegister, controlled_unitaries: list[Gate], state_prep: Gate, ) -> QuantumCircuit: qc = QuantumCircuit(qr, cr) ####### your code goes here ####### for i, u_gate in enumerate(controlled_unitaries[::-1]): # リセット処理 if i != 0: qc.reset(qr[0]) qc.h(qr[0]) if i == 0: qc.x(qr[1]) else: # Z軸周りの角度wの回転で位相補正 for j in range(0, i): with qc.if_test((cr[j], 1)): qc.p(-np.pi /(2**(i-j)), qr[0]) qc.append(u_gate, [qr[0], qr[1]]) # X基底でq0を測定 qc.h(qr[0]) qc.measure(qr[0], cr[i]) return qc
この関数を使用してS ゲートのIPE回路を生成する。
from qiskit.circuit.library import CPhaseGate, XGate qr = QuantumRegister(2, "q") cr = ClassicalRegister(2, "c") s_angle = np.pi / 2 controlled_unitaries = [CPhaseGate(s_angle * 2**k) for k in range(2)] qc = iterative_phase_estimation(qr, cr, controlled_unitaries, XGate()) qc.draw()
回路を実行する。結果は01
になるはずである。
sim = AerSimulator() job = sim.run(qc, shots=1000) result = job.result() counts = result.get_counts() counts # {'01': 1000}
合ってる。
Tゲートでも検証してみる。
qr = QuantumRegister(2, "q") cr = ClassicalRegister(3, "c") t_angle = np.pi / 4 controlled_unitaries = [CPhaseGate(t_angle * 2**k) for k in range(3)] qc = iterative_phase_estimation(qr, cr, controlled_unitaries, XGate()) qc.draw()
回路を実行する。結果は001
になるはずである。
sim = AerSimulator() job = sim.run(qc, shots=1000) result = job.result() counts = result.get_counts() counts # {'001': 1000}
合ってる。