量子位相推定は、量子計算における最も重要なサブルーチンの1つです。 多くの量子アルゴリズムの中心的な構成要素として機能します。このアルゴリズムの目的は次のとおりです。
ユニタリ演算子$U$が、 $U\vert\psi \rangle =e^{\boldsymbol{2\pi i} \theta }|\psi \rangle$のように与えられた場合に、$\theta$を推定します。 ここで、$|\psi\rangle$ は固有ベクトルであり、$e^{\boldsymbol{2\pi i}\theta}$は対応する固有値です。$U$ はユニタリーなので、すべての固有値のノルムは1です。
位相推定の一般的な量子回路を以下に示します。 上側のレジスターには$t$個の「カウント」量子ビットがあり、下のレジスターには$|\psi\rangle$の状態の量子ビットがあります:
1.1 直感的解釈
量子位相推定アルゴリズムは、位相キックバックを使用して、$U$の(フーリエ基底における)位相をカウントレジスターの$t$ 量子ビットに書き込みます。次に、逆QFTを使用して、フーリエ基底から計算基底に変換し、測定します。
(QFTの章から)フーリエ基底では、 $0$から数えて$2^t$回で最上位の量子ビットが1回転したことを覚えているでしょう。 $0$から$2^t$の間の数である$x$を数えるには、この量子ビットをz軸を中心に$\tfrac{x}{2^t}$ 回転させます。 次の量子ビットでは$\tfrac{2x}{2^t}$回転し、3番目の量子ビットでは$\tfrac{4x}{2^t}$回転します。
制御$U$ゲートを使うと、量子ビットは(キックバックにより)位相 $e^{2i\pi\theta}$に比例して回転します。 連続して$CU$ゲートを使用して、フーリエ基底で$0$ 〜 $2^t$の数値として位相$\theta$をエンコードできるところまで、この回転を適切な回数繰り返します。
次に、$QFT^\dagger$を使用してこれを計算基底に変換します。
1.2 基礎となる数学
上記のように、この回路はユニタリー演算子$U$の位相を推定します。$U\vert\psi \rangle =e^{\boldsymbol{2\pi i} \theta }|\psi \rangle$において、$|\psi\rangle$は固有ベクトル、$e^{\boldsymbol{2\pi i}\theta}$は対応する固有値で、$\theta$を推定します。回路は次の手順です。
i. 準備:$\vert\psi\rangle$を1量子ビットレジスターにセットします。 別の$n$個の量子ビットのセットは、値$2^n\theta$を格納するカウントレジスターです。
$$ \psi_0 = \lvert 0 \rangle^{\otimes n} \lvert \psi \rangle$$ii. 重ね合わせ:$n$ビットのアダマールゲート操作$H^{\otimes n}$をカウントレジスターに適用します。
$$ \psi_1 = {\frac {1}{2^{\frac {n}{2}}}}\left(|0\rangle +|1\rangle \right)^{\otimes n} \lvert \psi \rangle$$iii. 制御ユニタリー演算:制御ビットが$|1\rangle$の場合にのみ、ターゲットレジスターにユニタリー演算子 $U$ を適用する、制御ユニタリー演算$C-U$を導入する必要があります。$U$は、$U|\psi \rangle =e^{\boldsymbol{2\pi i} \theta }|\psi \rangle$となる固有ベクトル$|\psi\rangle$ のユニタリー演算子であるため、次のようになります。
$$U^{2^{j}}|\psi \rangle =U^{2^{j}-1}U|\psi \rangle =U^{2^{j}-1}e^{2\pi i\theta }|\psi \rangle =\cdots =e^{2\pi i2^{j}\theta }|\psi \rangle$$すべての𝑛制御演算子 $C − U^{2^j}$を$0\leq j\leq n-1$において適用し、$|0\rangle \otimes |\psi \rangle +|1\rangle \otimes e^{2\pi i\theta }|\psi \rangle =\left(|0\rangle +e^{2\pi i\theta }|1\rangle \right)\otimes |\psi \rangle$を使用すると以下のようになります。
\begin{aligned} \psi_{2} & =\frac {1}{2^{\frac {n}{2}}} \left(|0\rangle+{e^{\boldsymbol{2\pi i} \theta 2^{n-1}}}|1\rangle \right) \otimes \cdots \otimes \left(|0\rangle+{e^{\boldsymbol{2\pi i} \theta 2^{1}}}\vert1\rangle \right) \otimes \left(|0\rangle+{e^{\boldsymbol{2\pi i} \theta 2^{0}}}\vert1\rangle \right) \otimes |\psi\rangle\\\\ & = \frac{1}{2^{\frac {n}{2}}}\sum _{k=0}^{2^{n}-1}e^{\boldsymbol{2\pi i} \theta k}|k\rangle \otimes \vert\psi\rangle \end{aligned}ここで、$k$ はnビットの2進数の整数表現です。
iv. 逆フーリエ変換:上の式は、量子フーリエ変換とそのQiskit実装のnotebookで導出したように、量子フーリエ変換を適用した結果であることに注意してください。 QFTがn量子ビットの入力状態$\vert x\rangle$を出力として以下のようにマップすることを思い出してください。
$$ QFT\vert x \rangle = \frac{1}{2^\frac{n}{2}} \left(\vert0\rangle + e^{\frac{2\pi i}{2}x} \vert1\rangle\right) \otimes \left(\vert0\rangle + e^{\frac{2\pi i}{2^2}x} \vert1\rangle\right) \otimes \ldots \otimes \left(\vert0\rangle + e^{\frac{2\pi i}{2^{n-1}}x} \vert1\rangle\right) \otimes \left(\vert0\rangle + e^{\frac{2\pi i}{2^n}x} \vert1\rangle\right) $$上の式で$x$を$2^n\theta$ に置き換えると、上記のステップ2で導出された式が正確に得られます。したがって、状態$\vert2^n\theta\rangle$を復元するには、補助レジスターに逆フーリエ変換を適用します。そうすることで、以下を得られます。 $$ \vert\psi_3\rangle = \frac {1}{2^{\frac {n}{2}}}\sum _{k=0}^{2^{n}-1}e^{\boldsymbol{2\pi i} \theta k}|k\rangle \otimes | \psi \rangle \xrightarrow{\mathcal{QFT}_n^{-1}} \frac {1}{2^n}\sum _{x=0}^{2^{n}-1}\sum _{k=0}^{2^{n}-1} e^{-\frac{2\pi i k}{2^n}(x - 2^n \theta)} |x\rangle \otimes |\psi\rangle $$
v. 測定:上記の式は$x = 2^n\theta$付近でピークになります。$2^n\theta$が整数の場合、計算基底で測定すると、高い確率で補助レジスターに位相が得られます。
$$ |\psi_4\rangle = | 2^n \theta \rangle \otimes | \psi \rangle$$$2^n\theta$が整数でない場合、上記の式は $x = 2^n\theta$ の近くでピークに達し、その確率は$4/\pi^2 \approx 40\%$よりも高いものになります[1]。
みなさんがよく知っている$T$ゲートを例として取り上げ、量子位相推定を使用してその位相を推定します。$T$ゲートは状態$|1\rangle$に位相$e^\frac{i\pi}{4}$ を追加することを思い出してください。
$$ T|1\rangle = \begin{bmatrix} 1 & 0\\ 0 & e^\frac{i\pi}{4}\\ \end{bmatrix} \begin{bmatrix} 0\\ 1\\ \end{bmatrix} = e^\frac{i\pi}{4}|1\rangle $$以下の式で与えられる $\theta$ についてQPEを使って、
$$ T|1\rangle = e^{2i\pi\theta}|1\rangle $$$\theta$を見つけることができます:
$$\theta = \frac{1}{8}$$この例では、3量子ビットを使用して、 正確な 結果(推定ではありません!)を得ます。
#initialization
import matplotlib.pyplot as plt
import numpy as np
import math
# importing Qiskit
from qiskit import IBMQ, Aer, transpile, assemble
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister
# import basic plot tools
from qiskit.visualization import plot_histogram
次に、量子回路を設定します。 4量子ビットを使用します。qubit 0〜2はカウント量子ビットとして、qubit 3はユニタリー演算子($T$)の固有状態として使用します。
$X$ ゲートを適用して、$\vert\psi\rangle = \vert1\rangle$と初期化します。
qpe = QuantumCircuit(4, 3)
qpe.x(3)
qpe.draw()
カウント量子ビットにアダマールゲートをかけます:
for qubit in range(3):
qpe.h(qubit)
qpe.draw()
次に、制御ユニタリー演算を実行します。注意:Qiskitでは量子ビットが上の画像とは逆のむきに並びます。
repetitions = 1
for counting_qubit in range(3):
for i in range(repetitions):
qpe.cp(math.pi/4, counting_qubit, 3); # This is C-U
repetitions *= 2
qpe.draw()
逆量子フーリエ変換を適用して、カウントレジスターの状態を変換します。 ここでは、$QFT^\dagger$のコードを以下のように与えます。
def qft_dagger(qc, n):
"""n-qubit QFTdagger the first n qubits in circ"""
# Don't forget the Swaps!
for qubit in range(n//2):
qc.swap(qubit, n-qubit-1)
for j in range(n):
for m in range(j):
qc.cp(-math.pi/float(2**(j-m)), m, j)
qc.h(j)
次に、カウントレジスターを測定します。
qpe.barrier()
# Apply inverse QFT
qft_dagger(qpe, 3)
# Measure
qpe.barrier()
for n in range(3):
qpe.measure(n,n)
qpe.draw()
aer_sim = Aer.get_backend('aer_simulator')
shots = 2048
t_qpe = transpile(qpe, aer_sim)
qobj = assemble(t_qpe, shots=shots)
results = aer_sim.run(qobj).result()
answer = results.get_counts()
plot_histogram(answer)
結果(001
)のみが得られ、これは10進数に変換されると 1
となります。$\theta$の結果を得るには、結果(1
)を$2^n$で割る必要があります。
これはまさに私たちが期待した結果です!
# Create and set up circuit
qpe2 = QuantumCircuit(4, 3)
# Apply H-Gates to counting qubits:
for qubit in range(3):
qpe2.h(qubit)
# Prepare our eigenstate |psi>:
qpe2.x(3)
# Do the controlled-U operations:
angle = 2*math.pi/3
repetitions = 1
for counting_qubit in range(3):
for i in range(repetitions):
qpe2.cp(angle, counting_qubit, 3);
repetitions *= 2
# Do the inverse QFT:
qft_dagger(qpe2, 3)
# Measure of course!
for n in range(3):
qpe2.measure(n,n)
qpe2.draw()
# Let's see the results!
aer_sim = Aer.get_backend('aer_simulator')
shots = 4096
t_qpe2 = transpile(qpe2, aer_sim)
qobj = assemble(t_qpe2, shots=shots)
results = aer_sim.run(qobj).result()
answer = results.get_counts()
plot_histogram(answer)
予測される結果は$\theta = 0.3333\dots$です。実行の結果、最も可能性の高い結果は010(bin) = 2(dec)
と011(bin) = 3(dec)
であることが見てわかります。 これらの2つの結果から、それぞれ$\theta = 0.25$ (off by 25%) と$\theta = 0.375$ (off by 13%)が得られます。$\theta$ の真の値は、カウントビットから取得できる値の間にあり、この回路は、不確実であり不正確であることがわかります。
3.2 解決策
より精度を上げるには、カウント量子ビットを追加するだけです。 さらに2つのカウント量子ビットを追加しましょう。
# Create and set up circuit
qpe3 = QuantumCircuit(6, 5)
# Apply H-Gates to counting qubits:
for qubit in range(5):
qpe3.h(qubit)
# Prepare our eigenstate |psi>:
qpe3.x(5)
# Do the controlled-U operations:
angle = 2*math.pi/3
repetitions = 1
for counting_qubit in range(5):
for i in range(repetitions):
qpe3.cp(angle, counting_qubit, 5);
repetitions *= 2
# Do the inverse QFT:
qft_dagger(qpe3, 5)
# Measure of course!
qpe3.barrier()
for n in range(5):
qpe3.measure(n,n)
qpe3.draw()
### Let's see the results!
aer_sim = Aer.get_backend('aer_simulator')
shots = 4096
t_qpe3 = transpile(qpe3, aer_sim)
qobj = assemble(t_qpe3, shots=shots)
results = aer_sim.run(qobj).result()
answer = results.get_counts()
plot_histogram(answer)
最も可能性の高い2つの測定結果は、01011
(10進数の11)と01010
(10進数の10)です。 これらから、次のように$\theta$が求められます。
この2つの結果の$\frac{1}{3}$ との誤差は、それぞれ3%と6%です。さきほどよりずっと優れた精度の結果が得られました!
qpe.draw()
IBMQ.load_account()
from qiskit.tools.monitor import job_monitor
provider = IBMQ.get_provider(hub='ibm-q')
santiago = provider.get_backend('ibmq_santiago')
# Run with 2048 shots
shots = 2048
t_qpe = transpile(qpe, santiago, optimization_level=3)
job = santiago.run(t_qpe, shots=shots)
job_monitor(job)
# get the results from the computation
results = job.result()
answer = results.get_counts(qpe)
plot_histogram(answer)
うまくいけば、最も可能性の高い結果は、シミュレーターから期待される結果である 001
になることがわかります。 シミュレーターとは異なり、 001
以外も測定される可能性があります。これは、量子コンピューターにおけるノイズとゲートエラーによるものです。
import qiskit.tools.jupyter
%qiskit_version_table