Quantum Phase Estimation¶
The quantum phase estimation (QPE) function estimates the phase of an eigenvector of a unitary function. More precisely, given a unitary function $F$ and an input containing a quantum variable with a state $|\psi\rangle$ such that $F(|\psi\rangle)=e^{2\pi i\nu}|\psi\rangle$, the phase estimation function outputs an estimation of $\nu$ as a fixed-point binary number.
Phase estimation is frequently used as a subroutine in other quantum algorithms such as Shor's algorithm and quantum algorithms for solving linear systems of equations (HHL algorithm). Theoretical details are in Ref. [1].
Function: qpe
Arguments:
unitary: QCallable
- The unitary operation for which the qpe estimation the eigenvaluesphase: QNum
- The output of the qpe, holding the phase as a number in the range $[0, 1)$
Function: qpe_flexible
The function is suitalbe when wants to specialize the way the power of a unitary is defined, other than using the naive power. For example it can used with exponentiaing hamiltonians or for shor's algorithm.
Arguments:
unitary_with_power: QCallable[QParam[int]]
- Power of a unitary. Accepts as argument the power of the unitary to apply.phase: QNum
Examples¶
Example 1: QPE of a function¶
This example shows how to perform a simple phase estimation:
- Initialize the state $|3\rangle$ over two qubits.
- Apply a phase estimation on the the controlled-RZ gate, represeneted by the unitary matrix:
$$ \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & e^{-i\frac{\lambda}{2}} & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & e^{i\frac{\lambda}{2}} \end{pmatrix} $$
The expected phase variable should encode $\frac{\lambda}{4\pi}$, the phase of the eigenvalue of the $|3\rangle$ state.
Choosing $\lambda = \pi$, the expected result is $\frac{1}{4}$, represented in binary by 01
.
from classiq import (
CRZ,
Output,
QArray,
QBit,
QNum,
allocate,
allocate_num,
create_model,
inplace_prepare_int,
qfunc,
qpe,
)
from classiq.qmod.symbolic import pi
QPE_RESOLUTION = 2
@qfunc
def main(state: Output[QArray[QBit]], phase: Output[QNum]):
allocate(2, state)
allocate_num(QPE_RESOLUTION, 0, QPE_RESOLUTION, phase)
inplace_prepare_int(3, state)
qpe(unitary=lambda: CRZ(pi, state[0], state[1]), phase=phase)
qmod = create_model(main)
from classiq import synthesize, write_qmod
write_qmod(qmod, "qpe_example")
qprog = synthesize(qmod)
Show the actual results:
from classiq import execute
res = execute(qprog).result()[0].value
print("Results:", res.parsed_counts)
Results: [{'state': 3.0, 'phase': 0.25}: 1000]
Example 2: Flexible QPE¶
The following examples will specifiy directly how to take powers in the QPE. The unitary function is suzuki_trotter
, where the number of repetitions will be 1. In the case of diagonal hamiltonian it be exact exponentiation of the hamiltoian.
Take the following matrix: $$ \begin{pmatrix} 0 & 0 & 0 & 0 \\ 0 & \tfrac{1}{4} & 0 & 0 \\ 0 & 0 & \tfrac{1}{2} & 0 \\ 0 & 0 & 0 & \tfrac{3}{4} \\ \end{pmatrix} $$
Represented by the hamiltonian:
$H = -\frac{1}{8}Z_0I_1 - \frac{1}{4}I_0Z_1 + \frac{3}{8}I_0I_1$
from classiq import (
Output,
Pauli,
PauliTerm,
QArray,
QBit,
QNum,
allocate,
allocate_num,
create_model,
hadamard_transform,
qfunc,
qpe_flexible,
suzuki_trotter,
)
from classiq.qmod.symbolic import pi
QPE_RESOLUTION = 2
HAMILTONIAN = [
PauliTerm(pauli=[Pauli.I, Pauli.Z], coefficient=-0.125),
PauliTerm(pauli=[Pauli.Z, Pauli.I], coefficient=-0.25),
PauliTerm(pauli=[Pauli.I, Pauli.I], coefficient=0.375),
]
@qfunc
def main(state: Output[QArray[QBit]], phase: Output[QNum]):
allocate(2, state)
allocate_num(QPE_RESOLUTION, 0, QPE_RESOLUTION, phase)
hadamard_transform(state)
qpe_flexible(
lambda power: suzuki_trotter(
HAMILTONIAN,
evolution_coefficient=-2 * pi * (power),
order=1,
repetitions=1,
qbv=state,
),
phase,
)
qmod = create_model(main)
from classiq import synthesize, write_qmod
write_qmod(qmod, "qpe_flexible_example")
qprog = synthesize(qmod)
Show the actual results:
from classiq import execute
res = execute(qprog).result()[0].value
print("Results:", res.parsed_counts)
Results: [{'state': 3.0, 'phase': 0.75}: 257, {'state': 2.0, 'phase': 0.5}: 256, {'state': 1.0, 'phase': 0.25}: 250, {'state': 0.0, 'phase': 0.0}: 237]
References¶
[1] A. Yu. Kitaev Barenco et al, Quantum Measurements and the Abelian Stabilizer Problem, (1995). https://doi.org/10.48550/arXiv.quant-ph/9511026