Iterative Quantum Phase Estimation#

IQPE(args: Any, U: Callable, precision: int | Tracer, iter_spec: bool = False, ctrl_method: str | None = None, kwargs: dict | None = None) → Array[source]#

Estimate the phase of a unitary with the iterative quantum phase estimation algorithm.

The algorithm is described in this paper. The unitary to estimate is expected to be given as Python function, which is called on args.

Instead of a variable of precision qubits, the algorithm uses a single control qubit at a time. Step \(j\) applies \(U^{2^{t - 1 - j}}\) controlled on a fresh qubit, where \(t\) is the precision, corrects the phase of the bits measured before, and measures bit \(j\) of the estimate, from the least significant one.

Parameters:
argsAny

The state on which the phase estimation is performed, for example a QuantumVariable or a list of QuantumVariables. It is passed to U as its first argument.

UCallable

The unitary, as a Python function that is called as U(args, **kwargs), with the keyword iter as well if iter_spec is True.

precisionint or Tracer

The precision of the estimation.

iter_specbool, optional

If set to True, U will be called with the additional keyword iter = i where i is the amount of iterations to perform (instead of simply calling U for i times). The default is False.

ctrl_methodstr, optional

Allows to specify which method should be used to generate the controlled U circuit. For more information check .control. The default is None.

kwargsdict, optional

A dictionary of keyword arguments to pass to U. The default is None, which passes no keyword arguments.

Returns:
float

The estimated phase as a fraction of \(2 \pi\).

Raises:
TypeError

If precision is not an integer.

ValueError

If precision is larger than 63. A traced precision, for example an argument of a jaspified function, is not checked, since its value is only known when the program runs.

Notes

Without iter_spec, the first step calls U \(2^{t-1}\) times and the last one once, \(2^t - 1\) calls in total. The number of iterations \(2^{t-1}\) is a 64-bit integer, also with iter_spec, so the precision is at most 63. The estimate is a float, exact for a precision of up to 53 bits. For the order finding of Shor’s algorithm with thousands of bits, see semiclassical_order_finding().

Examples

We define a function that applies two rotations onto its input and estimate the applied phase:

>>> import numpy as np
>>> from qrisp import IQPE, QuantumFloat, h, rx, x
>>> from qrisp.jasp import make_jaspr
>>> def f():
...     def U(qv):
...         rx(2 * np.pi / 2**3, qv[0])
...         rx(2 * np.pi / 2**2, qv[1])
...     qv = QuantumFloat(2)
...     x(qv)
...     h(qv)
...     return IQPE(qv, U, precision=4)
>>> jaspr = make_jaspr(f)()

Each qubit is in the state \(\lvert - \rangle\), on which \(R_X(2 \pi x)\) has the eigenvalue \(e^{i \pi x}\), so the phase is \((1/8 + 1/4) / 2 = 0.1875\):

>>> jaspr()
Array(0.1875, dtype=float64)