Source code for qrisp.alg_primitives.qpe

"""
\********************************************************************************
* Copyright (c) 2023 the Qrisp authors
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License, v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is
* available at https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
"""

from qrisp.core.gate_application_functions import h
from qrisp.alg_primitives.qft import QFT


[docs] def QPE( args, U, precision=None, target=None, iter_spec=False, ctrl_method=None, kwargs={} ): r""" Evaluates the `quantum phase estimation algorithm <https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm>`_. The unitary to estimate is expected to be given as Python function, which is called on ``args``. Parameters ---------- args : list A list of arguments (could be QuantumVariables) which represent the state, the quantum phase estimation is performed on. U : function A Python function, which will receive the list ``args`` as arguments in the course of this algorithm. precision : int, optional The precision of the estimation. The default is None. target : QuantumFloat, optional A target QuantumFloat to perform the estimation into. The default is None. If given neither a precision nor a target, an Exception will be raised. iter_spec : bool, 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_method : string, optional Allows to specify which method should be used to generate the controlled U circuit. For more information check :meth:`.control <qrisp.Operation.control>`. The default is None. kwargs : dict, optional A dictionary of keyword arguments to pass to ``U``. The default is {}. Raises ------ Exception Tried to perform quantum phase estimation without precision specification. Returns ------- res : QuantumFloat The QuantumFloat containing the estimated phase as a fraction of $2 \pi$. Examples -------- We define a function that applies two phase gates onto its input and estimate the applied phase. :: from qrisp import p, QuantumVariable, QPE, multi_measurement def U(qv): x = 0.5 y = 0.125 p(x*2*np.pi, qv[0]) p(y*2*np.pi, qv[1]) qv = QuantumVariable(2) h(qv) res = QPE(qv, U, precision = 3) >>> multi_measurement([qv, res]) {('00', 0.0): 0.25, ('10', 0.5): 0.25, ('01', 0.125): 0.25, ('11', 0.625): 0.25} >>> res.qs.depth() 66 During the phase estimation, ``U`` is called $2^{\text{precision}}$ times. We can reduce that number by abusing that we can bundle repeated calls into a single call with a modified phase. :: def U(qv, iter = None): x = 0.5 y = 0.125 p(x*2*np.pi*iter, qv[0]) p(y*2*np.pi*iter, qv[1]) qv = QuantumVariable(2) h(qv) res = QPE(qv, U, precision = 3, iter_spec = True) >>> multi_measurement([qv, res]) {('00', 0.0): 0.25, ('10', 0.5): 0.25, ('01', 0.125): 0.25, ('11', 0.625): 0.25} >>> res.qs.depth() 34 """ from qrisp import QuantumFloat, control if target is None: if precision is None: raise Exception( "Tried to perform quantum phase estimation without" "precision specification" ) qpe_res = QuantumFloat(precision, -precision, signed=False) else: qpe_res = target h(qpe_res) for i in range(qpe_res.size): if iter_spec: with control(qpe_res[i], ctrl_method=ctrl_method): U(args, iter=2**i, **kwargs) else: with control(qpe_res[i], ctrl_method=ctrl_method): for j in range(2**i): U(args, **kwargs) QFT(qpe_res, inv=True) return qpe_res