> ## Documentation Index
> Fetch the complete documentation index at: https://docs.classiq.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Quantum Phase Estimation

> **[View on GitHub](https://github.com/Classiq/classiq-library/blob/main/functions/qmod_library_reference/classiq_open_library/qpe/qpe.ipynb)**
>
> 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 $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\]](#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)$

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\rangle$ over two qubits.
2. 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`.

```python theme={null}
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_)
```

```python theme={null}

qprog = synthesize(main)
```

Show the actual results:

```python theme={null}
result = sample(qprog)
print("Results:", result)
```

> [!NOTE]
>
> **Output:**
>
> ```
>
> Submitting job to simulator
>   Job: https://platform.classiq.io/jobs/9aaf55f5-0215-47ea-b507-e2264f344f1d
>
>
> ```

> [!NOTE]
>
> **Output:**
>
> ```
>
> Results:     state  phase_  counts  probability bitstring
>   0  [1, 1]    0.25    2048          1.0      0111
>
>
> ```

#

## 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$

```python theme={null}
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_,
    )
```

```python theme={null}

qprog = synthesize(main)
```

Show the actual results:

```python theme={null}
result = sample(qprog)
print("Results:", result)
```

> [!NOTE]
>
> **Output:**
>
> ```
>
> Submitting job to simulator
>   Job: https://platform.classiq.io/jobs/d8c4b2c5-6cd3-41e8-ac09-8b6bf82914da
>
>
> ```

> [!NOTE]
>
> **Output:**
>
> ```
>
> Results:     state  phase_  counts  probability bitstring
>   0  [1, 0]    0.25     530     0.258789      0101
>   1  [1, 1]    0.75     521     0.254395      1111
>   2  [0, 0]    0.00     501     0.244629      0000
>   3  [0, 1]    0.50     496     0.242188      1010
>
>
> ```

## 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](https://doi.org/10.48550/arXiv.quant-ph/9511026)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.