Quantum phase estimation#
Description#
If \(\lambda\) is an eigenvalue of a given unitary operator \(\Unitary\) corresponding to a given eigenvector \(\ket{\psi}\), then we have
Since unitary operators represent transformations around the unit circle, then their eigenvalues necessarily have unit modulus, i.e., \(\abs{\lambda} = 1\). This means that any such eigenvalue can be written in the form
and so is characterized completely by its phase \(\theta \in \Reals\). Note that, due to the peridocity of the complex exponential, this may be taken on the restricted domain \(0 \leq \theta < 1\). Quantum phase estimation is then simply a procedure for estimating this phase \(\theta\) given both a unitary operator \(\Unitary\) and an eigenvector \(\ket{\psi}\).
Algorithm#
In the canonical quantum phase estimation algorithm, introduced by Kitaev [1] and depicted in Figure 28, we require two registers. The first (upper), called the estimation (or control) register, consists of \(n\) qubits (on the Hilbert space \(\SpaceHilbert_2^{\otimes n}\)), with each initialized to \(\ket{0}\). The second (lower), called the eigenvector (or target) register, is in the state of an eigenvector \(\ket{\psi}\) of the given \(\Unitary\) over \(m\) qubits (on the Hilbert space \(\SpaceHilbert_2^{\otimes m}\)). The total initial state may therefore be written as
The first step consists of transforming the estimation register to an equal superposition state. This is achieved via an \(n\)-qubit Hadamard gate operation \(\Hadamard^{\otimes n}\), which gives
Here, \(\ket{x}\) is an \(n\)-ary representation of states in the \(n\)-qubit register, e.g.,
where the binary decomposition of \(x\) is simply
A sequence of controlled-\(\Unitary\) operations, each of the form,
is then applied, where \(\ell\) is the index of the system in the estimation register. The total transformation incurred by this sequence may be written as
under which the circuit’s state becomes
Note that here we introduced the eigenvalue of \(\Unitary\) as \(\lambda = \e^{2\pi\eye\theta}\) (corresponding to the eigenvector \(\ket{\psi}\)), and subsequently used the fact that
Performing an \(n\)-qubit inverse Fourier transform \(\QFT_n^\dagger\),
on the estimation register then yields the output state
By inspection, the amplitude associated with each \(\ket{x}\) simply takes the form
and so performing a measurement in the computational basis on the estimation register yields the outcome \(\ket{y}\) with probability
With foresight, we can define the substitution
where \(z/2^{n}\) is the nearest integer to \(\theta\), and the discrepancy \(\delta\) satisfies \(0 \leq \abs{\delta} \leq 1/2\). In effect, this approximates \(\theta \in [0, 1]\) by rounding its value to the nearest integer. With this, the probabilities take the form
If \(\delta = 0\), the corresponding probability to find such a value \(z\) is
Evidently, in such a case, the outcome is always found to be \(y = z\), and so the phase can decoded as \(\theta = z / 2^n\). Alternatively, if \(\delta \neq 0\), then the probability to find \(z\) is
where we used the identity
With a little effort, it can be shown that
for any \(\delta \neq 0\), from which we can conclude that the algorithm provides an estimate of \(\theta\) (to within \(1/2^n\) of the actual value) with a probability of at least \(4/\pi^2\).
Implementation#
In this implementation, the target register consists of a single qubit \(\ket{\psi} = \ket{1}\), with which the unitary operator is the phase gate, specifically,
from qhronology.quantum.gates import GateStack, Hadamard, Pauli, Phase, Fourier
from qhronology.quantum.circuits import QuantumCircuit
from qhronology.mechanics.matrices import encode, decode
import sympy as sp
import numpy as np
phase = 0.64 # The phase to be estimated
precision = 4 # The number of qubits used by the estimation
num_controls = precision
num_targets = 1
num_total = num_targets + num_controls
systems_controls = list(range(0, num_controls))
systems_targets = [m + num_controls for m in range(0, num_targets)]
# Gates
HX = GateStack(
*[Hadamard()] * num_controls,
Pauli(index=1),
)
unitaries = [
Phase(
phase=sp.exp(2 * sp.I * sp.pi * phase * 2**n),
targets=systems_targets,
controls=[systems_controls[n]],
num_systems=num_total,
label=f"U^{2**n}",
)
for n in range(0, num_controls)
]
IQFT = Fourier(
targets=systems_controls,
num_systems=num_total,
composite=True,
conjugation=True,
label="QFT^†",
)
# Circuit
phase_estimator = QuantumCircuit(
gates=[HX] + unitaries + [IQFT],
numerical=True,
array=True,
)
phase_estimator.diagram(pad=(1, 0), force_separation=True)
# Measurement
basis = [encode(k, num_controls) for k in range(0, 2**num_controls)]
probabilities = phase_estimator.measure(
operators=basis,
targets=systems_controls,
observable=False,
statistics=True,
)
probabilities = [np.real(probability) for probability in probabilities]
# Results
print(f"Input phase: {phase}")
expectation = 0
threshold = 0.001
for k, probability in enumerate(probabilities):
value = decode(basis[k]) / 2**num_controls
value = sp.N(value).round(precision)
bitstring = encode(decode(basis[k]), num_controls, return_type=str)
expectation += probability * value
suffix = ""
if probability == max(probabilities):
suffix = " (most probable)"
if probability >= threshold or probability == max(probabilities):
probability = sp.N(probability).round(3)
print(
f"Bitstring={bitstring}, "
+ f"Probability={probability}, "
+ f"Phase={value}"
+ f"{suffix}"
)
expectation = sp.N(expectation).round(precision)
print(f"Expectation (weighted average): {expectation}")
Output#
Diagram#
>>> phase_estimator.diagram(pad=(1, 0), force_separation=True)
Results#
Cumulative output from the various print statements:
Input phase: 0.64
Bitstring=0000, Probability=0.002, Phase=0
Bitstring=0001, Probability=0.002, Phase=0.0625
Bitstring=0010, Probability=0.002, Phase=0.1250
Bitstring=0011, Probability=0.002, Phase=0.1875
Bitstring=0100, Probability=0.002, Phase=0.2500
Bitstring=0101, Probability=0.002, Phase=0.3125
Bitstring=0110, Probability=0.003, Phase=0.3750
Bitstring=0111, Probability=0.005, Phase=0.4375
Bitstring=1000, Probability=0.010, Phase=0.5000
Bitstring=1001, Probability=0.031, Phase=0.5625
Bitstring=1010, Probability=0.825, Phase=0.6250 (most probable)
Bitstring=1011, Probability=0.083, Phase=0.6875
Bitstring=1100, Probability=0.016, Phase=0.7500
Bitstring=1101, Probability=0.007, Phase=0.8125
Bitstring=1110, Probability=0.004, Phase=0.8750
Bitstring=1111, Probability=0.003, Phase=0.9375
Expectation (weighted average): 0.6245
References
A. Y. Kitaev, “Quantum measurements and the Abelian Stabilizer Problem”, arXiv, November 1995. DOI: 10.48550/arXiv.quant-ph/9511026