Update odometer

From QETLAB
Jump to: navigation, search
update_odometer
Increases a vector subject to limits on how large each entry can be

Other toolboxes required none
Function category Helper functions
This is a helper function that only exists to aid other functions in QETLAB. If you are an end-user of QETLAB, you likely will never have a reason to use this function.

update_odometer is a function that implements an "odometer": that is, it increases the right-most entry of a vector by 1. If that right-most entry is now larger than its maximum allowed value then it "rolls over" to 0 and the second-to-right-most entry increases by 1. Similarly, if this entry is now too larger, it rolls over, and so on.

This function is useful if you are in a situation where you want to nest multiple for loops, but you don't know beforehand exactly how many of them there will be (since it depends on user input, for example).

Syntax

  • NEW_IND = update_odometer(OLD_IND,UPPER_LIM)

Argument descriptions

  • OLD_IND: The vector to be updated.
  • UPPER_LIM: A vector of the same length as OLD_IND with the property that its j-th entry specifies the "roll over" value of the j-th entry of OLD_IND. That is, the j-th value of OLD_IND is constrained to being in the interval from 0 to UPPER_LIM(j)-1 (inclusive).

Examples

The following code loops over all vectors of length 2 with the property that their first entry is 0, 1, or 2, and their second entry is 0 or 1:

>> v = [0,0]; upper_lim = [3,2];
>> for j = 0:prod(upper_lim)-1
     v = update_odometer(v,upper_lim)
   end
 
v =
 
     0     1
 
 
v =
 
     1     0
 
 
v =
 
     1     1
 
 
v =
 
     2     0
 
 
v =
 
     2     1
 
 
v =
 
     0     0

Source code

Click on "expand" to the right to view the MATLAB source code for this function.

  1. %%  UPDATE_ODOMETER    Increases a vector subject to limits on how large each entry can be
  2. %
  3. %   NEW_IND = update_odometer(OLD_IND,UPPER_LIM) increases the last entry
  4. %   of the vector OLD_IND by 1, unless that would make it larger than the
  5. %   last entry of the vector UPPER_LIM. In this case, it sets the last
  6. %   entry to 0 and instead increases the *second*-last entry of OLD_IND,
  7. %   unless that would make it larger than the second-last entry of
  8. %   UPPER_LIM. In this case, it sets the second-last entry to 0 and instead
  9. %   increases the *third*-last entry of OLD_IND (and so on; it works like
  10. %   an odometer).
  11. %
  12. %   This function is useful when you want to have k nested for loops, but k
  13. %   isn't specified beforehand. For example, instead for looping over i and
  14. %   j going from 1 to 3, you could loop over a single variable going from
  15. %   1 to 3^2, and set [i,j] = update_odometer([i,j],[3,3]) at each step
  16. %   within the loop.
  17. %
  18. %   URL: http://www.qetlab.com/update_odometer
  19.  
  20. %   requires: nothing
  21. %   author: Nathaniel Johnston (nathaniel@njohnston.ca)
  22. %   package: QETLAB
  23. %   last updated: December 11, 2014
  24.  
  25. function new_ind = update_odometer(old_ind,upper_lim)
  26.     % Start by increasing the last index by 1.
  27.     ind_len = length(old_ind);
  28.     new_ind = old_ind;
  29.     new_ind(end) = new_ind(end)+1;
  30.  
  31.     % Now we work the "odometer": repeatedly set each digit to 0 if it
  32.     % is too high and carry the addition to the left until we hit a
  33.     % digit that *isn't* too high.
  34.     for j = ind_len:-1:1
  35.         % If we've hit the upper limit in this entry, move onto the next
  36.         % entry.
  37.         if(new_ind(j) >= upper_lim(j))
  38.             new_ind(j) = 0;
  39.             if(j >= 2)
  40.                 new_ind(j-1) = new_ind(j-1) + 1;
  41.             else % we're at the left end of the vector; just stop
  42.                 return;
  43.             end
  44.         else
  45.             return; % always return if the odometer doesn't turn over
  46.         end
  47.     end
  48. end