Loops#
- jrange(*args)[source]#
Performs a loop with a dynamic bound. Similar to the Python native
range
, this iterator can receive multiple arguments. If it receives just one, this value is interpreted as the stop value and the start value is assumed to be 0. Two arguments represent start and stop value, whereas three represent start, stop and step.Warning
Similar to the ClControlEnvironment, this feature must not have external carry values, implying values computed within the loop can’t be used outside of the loop. It is however possible to carry on values from the previous iteration.
Warning
Each loop iteration must perform exactly the same instructions - the only thing that changes is the loop index
- Parameters:
- startint
The loop index to start at.
- stopint
The loop index to stop at.
- stepint
The value to increase the loop index by after each iteration.
Examples
We construct a function that encodes an integer into an arbitrarily sized QuantumVariable:
from qrisp import QuantumFloat, control, x from qrisp.jasp import jrange, make_jaspr @qache def int_encoder(qv, encoding_int): for i in jrange(qv.size): with control(encoding_int & (1<<i)): x(qv[i]) def test_f(a, b): qv = QuantumFloat(a) int_encoder(qv, b+1) return measure(qv) jaspr = make_jaspr(test_f)(1,1)
Test the result:
>>> jaspr(5, 8) 9 >>> jaspr(5, 9) 10
We now give examples that violate the above rules (ie. no carries and changing iteration behavior).
To create a loop with carry behavior we simply return the final loop index
@qache def int_encoder(qv, encoding_int): for i in jrange(qv.size): with control(encoding_int & (1<<i)): x(qv[i]) return i def test_f(a, b): qv = QuantumFloat(a) int_encoder(qv, b+1) return measure(qv) jaspr = make_jaspr(test_f)(1,1)
>>> jaspr(5, 8) Exception: Found jrange with external carry value
To demonstrate the second kind of illegal behavior, we construct a loop that behaves differently on the first iteration:
@qache def int_encoder(qv, encoding_int): flag = True for i in jrange(qv.size): if flag: with control(encoding_int & (1<<i)): x(qv[i]) else: x(qv[0]) flag = False def test_f(a, b): qv = QuantumFloat(a) int_encoder(qv, b+1) return measure(qv) jaspr = make_jaspr(test_f)(1,1)
In this script,
int_encoder
defines a boolean flag that changes the semantics of the iteration behavior. After the first iteration the flag is set toFalse
such that the alternate behavior is activated.>>> jaspr(5, 8) Exception: Jax semantics changed during jrange iteration