Source code for toqito.helper.update_odometer
"""Updates the odometer."""
import numpy as np
[docs]
def update_odometer(old_ind: list[int] | np.ndarray, upper_lim: list[int] | np.ndarray) -> list[int] | np.ndarray:
r"""Increase a vector as odometer.
Increases the last entry of the vector `old_ind` by 1, unless that would
make it larger than the last entry of the vector `upper_lim`. In this case,
it sets the last entry to 0 and instead increases the second-last entry of
`old_ind`, unless that would make it larger than the second-last entry of
`upper_lim`. In this case, it sets the second-last entry to 0 and instead
increases the third-last entry of `old_ind` (and so on; it works like an
odometer).
This function is useful when you want to have k nested loops, but k isn't
specified beforehand. For example, instead of looping over i and j going
from 1 to 3, you could loop over a single variable going from 1 to 3^2 and
set [i, j] = update_odometer([i, j], [3, 3]) at each step within the loop.
This function is adapted from QETLAB [@QETLAB_link].
Examples:
```python exec="1" source="above"
from toqito.helper import update_odometer
import numpy as np
vec = np.array([0, 0])
upper_lim = np.array([3, 2])
for j in range(0, np.prod(upper_lim)-1):
vec = update_odometer(vec, upper_lim)
print(vec)
```
Args:
old_ind: The initial vector.
upper_lim: The upper limit on which to increase the odometer to.
Returns:
The updated vector.
"""
ind_len = len(old_ind)
new_ind = old_ind[:]
# Start by increasing the last index by 1.
if len(new_ind) > 0:
new_ind[-1] = new_ind[-1] + 1
# Increment the "odometer": Repeatedly set each digit to 0 if it is too high
# and carry the addition to the left until we hit a digit that is not too
# high.
for j in range(ind_len, 0, -1):
# If we have hit the upper limit in this entry, move onto the next
# entry.
if new_ind[j - 1] >= upper_lim[j - 1]:
new_ind[j - 1] = 0
if j >= 2:
new_ind[j - 2] = new_ind[j - 2] + 1
else:
# We are at the left end of the vector, so just stop.
return new_ind
else:
# Always return if the odometer doesn't turn over.
return new_ind
return new_ind