Source code for qrisp.alg_primitives.arithmetic.adders.qcla.wrapper_function

"""
\********************************************************************************
* 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.alg_primitives.arithmetic.adders.qcla.quantum_quantum.qq_carry_path import *
from qrisp.alg_primitives.arithmetic.adders.qcla.quantum_quantum.qq_sum_path import *
from qrisp.alg_primitives.arithmetic.adders.qcla.quantum_quantum.qq_qcla_adder import *

from qrisp.alg_primitives.arithmetic.adders.qcla.classical_quantum.cq_carry_path import *
from qrisp.alg_primitives.arithmetic.adders.qcla.classical_quantum.cq_sum_path import *
from qrisp.alg_primitives.arithmetic.adders.qcla.classical_quantum.cq_qcla_adder import *


[docs] def qcla(a, b, radix_base = 2, radix_exponent = 1, t_depth_reduction = True, ctrl = None): r""" Implementation of the higher radix quantum carry lookahead adder (QCLA) as described `here <https://arxiv.org/abs/2304.02921>`__. This adder stands out for having logarithmic T-depth like `Drapers QCLA <https://arxiv.org/abs/quant-ph/0406142>`_. Compared to Drapers QCLA, the higher radix QCLA allows a more dynamic structure and the use of customizable "sub-adders" which enables this adder to beat Drapers QCLA in terms of speed (ie. T-depth). In Python syntax, this function performs the inplace addition: :: b += a Apart from the two quantum arguments, this function supports the specification of the adder-radix R. The adder-radix can be specified in the form of an exponential of integers: .. math:: R = r^k Where $r$ is the radix base and $k$ is the radix exponent. Calling ``qcla`` with radix base $r$ and radix exponent $k$, will precalculate the carry values using the `Brent-Kung tree <https://en.wikipedia.org/wiki/Brent%E2%80%93Kung_adder>`_ with carry-radix $r$ and cancel the recursion $k$ layers before conclusion. An additional compilation option is given with the ``t_depth_reduction`` keyword. This compilation option modifies the way the carry values are uncomputed. If ``t_depth_reduction`` is set to ``True`` the carry values will be uncomputed using the intermediate result of the sub-adder - if set to ``False`` they will be uncomputed using the automatic uncomputation algorithm. The advantage of the automated version is that, both T-depth and CNOT-depth are scaling with the the logarithm of the input size. For ``t_depth_reduction = True`` the T-depth is significantly reduced (and still logarithmic) however the CNOT depth becomes linear. Parameters ---------- a : QuantumFloat or List[Qubit] or int The value that is added. b : QuantumFloat or List[Qubit] The value that is operated on. radix_base : integer, optional The radix of the Brent-Kung tree. The default is 2. radix_exponent : integer, optional The cancellation treshold for the Brent-Kung recursion. The adder-Radix is then $R = r^k$. The default is 1. t_depth_reduction : bool, optional A compilation option that reduces T-depth but in turn weakens CNOT depth to linear scaling. The default is True. Raises ------ Exception Tried to add QuantumFloat of higher precision onto QuantumFloat of lower precision. Examples -------- We try out several constellations of parameters: >>> from qrisp import QuantumFloat, qcla >>> a = QuantumFloat(8) >>> b = QuantumFloat(8) >>> a[:] = 4 >>> b[:] = 15 >>> qcla(a, b) >>> print(b) {19: 1.0} We now measure the T-depth. To get the optimal result, we need to tell the compiler that we only care about T-gates. This can be achieved with the ``gate_speed`` keyword of the :meth:`compile <qrisp.QuantumSession.compile>` method. This keyword allows you to specify a function of :ref:`Operation` objects, which returns the speed of that Operation. For more information check out the :meth:`compile <qrisp.QuantumSession.compile>` documentation page. For T-depth, there is already a pre-coded function: :meth:`T-depth <qrisp.t_depth_indicator>`. >>> from qrisp import t_depth_indicator >>> gate_speed = lambda x : t_depth_indicator(x, epsilon = 2**-10) >>> qc = b.qs.compile(gate_speed = gate_speed, compile_mcm = True) >>> qc.t_depth() 17 This function contains many allocations/deallocations that can be leveraged into parallelism, implying it can profit a lot from additional workspace: >>> qc = b.qs.compile(workspace = 10, gate_speed = gate_speed, compile_mcm = True) >>> qc.t_depth() 7 We can verify the logarithmic behavior by comparing to the `Gidney-adder <https://arxiv.org/abs/1709.06648>`_: >>> from qrisp import gidney_adder >>> a = QuantumFloat(40) >>> b = QuantumFloat(40) >>> gidney_adder(a, b) >>> qc = b.qs.compile(gate_speed = gate_speed, compile_mcm = True) >>> qc.t_depth() 40 >>> a = QuantumFloat(40) >>> b = QuantumFloat(40) >>> qcla(a, b) >>> qc = b.qs.compile(workspace = 50, gate_speed = gate_speed, compile_mcm = True) >>> qc.t_depth() 19 The function can also be used to perform semi-classical in-place addition >>> b = QuantumFloat(10) >>> b[:] = 20 >>> qcla(22, b) >>> print(b) {42: 1.0} """ if isinstance(a, (int, str)): return cq_qcla(a, b, radix_base = radix_base, radix_exponent = radix_exponent, t_depth_reduction = t_depth_reduction, ctrl = ctrl) elif isinstance(a, (list, QuantumVariable)): return qq_qcla(a, b, radix_base = radix_base, radix_exponent = radix_exponent, t_depth_reduction = t_depth_reduction) else: raise Exception(f"Don't know how to handle type {type(a)} for QCLA addition")