Skip to main content

View on GitHub

Open this notebook in GitHub to run it yourself
The quantum phase estimation (QPE) function estimates the phase of an eigenvector of a unitary function. More precisely, given a unitary function FF and an input containing a quantum variable with a state ψ|\psi\rangle such that F(ψ)=e2πiνψ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 eigenvalues
  • phase: QNum
  • The output of the qpe, holding the phase as a number in the range [0,1)[0, 1)
Function: qpe_flexible The function is suitable when one wants to specialize the way the power of a unitary is defined, other than using the naive power. For example it can be used to obtain the time evolution of hamiltonians or for Shor’s algorithm. Arguments:
  • unitary_with_power: QCallable[CInt]
  • 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:
  1. Initialize the state 3|3\rangle over two qubits.
  2. Apply a phase estimation on the the controlled-RZ gate, represeneted by the unitary matrix:
(10000eiλ2000010000eiλ2)\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 λ4π\frac{\lambda}{4\pi}, the phase of the eigenvalue of the 3|3\rangle state. Choosing λ=π\lambda = \pi, the expected result is 14\frac{1}{4}, represented in binary by 01.
from classiq import *
from classiq.qmod.symbolic import pi

QPE_RESOLUTION = 2


@qfunc
def main(
    state: Output[QArray[QBit]],
    phase: Output[QNum[QPE_RESOLUTION, UNSIGNED, QPE_RESOLUTION]],
):
    allocate(phase)
    allocate(2, state)

    X(state[0])
    X(state[1])

    qpe(unitary=lambda: CRZ(pi, state[0], state[1]), phase=phase)


qmod = create_model(main)

qprog = synthesize(qmod)
Show the actual results:
result = execute(qprog).result_value()
print("Results:", result.parsed_counts)
Output:

Results: [{'state': [1, 1], 'phase': 0.25}: 2048]
  

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: (0000014000012000034)\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=18Z0I114I0Z1+38I0I1H = -\frac{1}{8}Z_0I_1 - \frac{1}{4}I_0Z_1 + \frac{3}{8}I_0I_1
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[QPE_RESOLUTION, UNSIGNED, QPE_RESOLUTION]],
):
    allocate(2, state)
    allocate(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)

qprog = synthesize(qmod)
Show the actual results:
result = execute(qprog).result_value()
print("Results:", result.parsed_counts)
Output:

Results: [{'state': [0, 0], 'phase': 0.0}: 554, {'state': [1, 1], 'phase': 0.75}: 517, {'state': [1, 0], 'phase': 0.25}: 516, {'state': [0, 1], 'phase': 0.5}: 461]
  

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