qrisp.qcla#
- qcla(a, b, radix_base=2, radix_exponent=1, t_depth_reduction=True, ctrl=None)[source]#
Implementation of the higher radix quantum carry lookahead adder (QCLA) as described here. This adder stands out for having logarithmic T-depth like Drapers QCLA. 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:
\[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 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. Ift_depth_reduction
is set toTrue
the carry values will be uncomputed using the intermediate result of the sub-adder - if set toFalse
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:
- aQuantumFloat or List[Qubit] or int
The value that is added.
- bQuantumFloat or List[Qubit]
The value that is operated on.
- radix_baseinteger, optional
The radix of the Brent-Kung tree. The default is 2.
- radix_exponentinteger, optional
The cancellation treshold for the Brent-Kung recursion. The adder-Radix is then \(R = r^k\). The default is 1.
- t_depth_reductionbool, 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 thecompile
method. This keyword allows you to specify a function of Operation objects, which returns the speed of that Operation. For more information check out thecompile
documentation page.For T-depth, there is already a pre-coded function:
T-depth
.>>> 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:
>>> 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}