# CrossProductSweeper

John Hunter jdhunter at nitace.bsd.uchicago.edu
Mon Sep 10 18:42:46 CEST 2001

```Here is a simple class to systematically investigate a cross product
space, which you might normally do with a series nested for loops.  I
suspect that there is an existing way to do this, but sometimes its
easier to roll your own that find the right package.  Please point me
to the light if there is an existing way to do this I should be aware
of.

CrossProductSweeper sweeps all points in the cross product space of the
lists in the initialization list

Example:

p = CrossProductSweeper( ( (1,2,3,4), (5,6), (7,8,9,10) ) )
while(p.more()):
pars = p.next()

is equivalent to the nested for loops

for x in (1,2,3,4):
for y in (5,6):
for z in (7,8,9,10):
pars = (x,y,z)

CrossProductSweeper also contains the method is_end_of_loop(i) which,
when invoked after a call to 'next' will return true if the point in
cross product space corresponds to the end of i-th loop had the space
been investigated using nested loops.

Eg,
for x in (1,2,3,4):
for y in (5,6):
for z in (7,8,9,10):
pars = (x,y,z)
print 'Just finished y'

is equivalent to:

p = CrossProductSweeper( ( (1,2,3,4), (5,6), (7,8,9,10) ) )
while(p.more()):
pars = p.next()
if p.is_end_of_loop(1):
print 'Just finished y'

CrossProductSweeper provides the following methods:

__init__( list_of_lists )
get_count - the number of points investigated so far
get_ith_length(i) - the number of points on the i-th dimension
get_num_dimensions - the dimension of the cross product space
get_total - the number of points in the cross product space
is_end_of_loop(i) - true if the last point occurs at
the end of iterator 'i'
more - True if there are uninvestigated points in cross-product space
next - Return the next uninvestigated point and increment
the iterators

--begin CrossProductSweeper.py--
"""CrossProductSweeper sweeps all points in the cross product space of the
lists in the initialization list

Example:

p = CrossProductSweeper( ( (1,2,3,4), (5,6), (7,8,9,10) ) )
while(p.more()):
pars = p.next()

is equivalent to the nested for loops

for x in (1,2,3,4):
for y in (5,6):
for z in (7,8,9,10):
pars = (x,y,z)

CrossProductSweeper also contains the method is_end_of_loop(i) which,
when invoked after a call to 'next' will return true if the point in
cross product space corresponds to the end of i-th loop had the space
been investigated using nested loops.

Eg,
for x in (1,2,3,4):
for y in (5,6):
for z in (7,8,9,10):
pars = (x,y,z)
print 'Just finished y'

is equivalent to:

p = CrossProductSweeper( ( (1,2,3,4), (5,6), (7,8,9,10) ) )
while(p.more()):
pars = p.next()
if p.is_end_of_loop(1):
print 'Just finished y'

CrossProductSweeper provides the following methods:

__init__( list_of_lists )
get_count - the number of points investigated so far
get_ith_length(i) - the number of points on the i-th dimension
get_num_dimensions - the dimension of the cross product space
get_total - the number of points in the cross product space
is_end_of_loop(i) - true if the last point occurs at
the end of iterator 'i'
more - True if there are uninvestigated points in cross-product space
next - Return the next uninvestigated point and increment
the iterators

"""

class CrossProductSweeper:
def __init__(self, p):

self.__allPars = p
self.__numPars = []
self.__dimensions = len(p)
self.__iter = []
self.__is_end_of_loop = []
self.__total = 1
self.__cnt = 0
for pars in p:
self.__numPars.append( len(pars) )
self.__iter.append( 0 )
self.__total = self.__total * len(pars)
self.__is_end_of_loop.append(0)

def more(self):
"""True if there remain uninvestigated points in the cross-product
space"""
return self.__cnt < self.__total

def is_end_of_loop(self,i):
"""This returns true if the last point of cross-product space
investigated would have occurred at the end if the i-th 'for
loop' had the same space been investigated with nested for
loops in order of the initialization list"""
return self.__is_end_of_loop[i]

def get_count(self):
"""Return the number of points of the cross product space
investigated so far"""
return self.__cnt

def get_total(self):
"""Return the total number of points in the cross product space"""
return self.__total

def get_num_dimensions(self):
"""Return the number of dimensions of the cross product space"""
return self.__dimensions

def get_ith_length(self, i):
"""Return the number of points in the ith dimension of the
cross-product space"""
return self.__numPars[i]

def next(self):
"""Return the current point in cross product space and
increment the iterators"""
pars = []
for (thisPars, i) in map(None, self.__allPars, self.__iter):
pars.append( thisPars[i] )

if self.more():
self.__increment_iter( self.__dimensions-1 )
self.__cnt = self.__cnt + 1
return pars

def __increment_iter(self, dim):
for i in range( self.__dimensions ):
self.__is_end_of_loop[i]=0
if (self.__iter[dim] < self.__numPars[dim]-1):
self.__iter[dim] = self.__iter[dim] + 1
else:
self.__iter[dim] = 0
self.__increment_iter(dim-1)
self.__is_end_of_loop[dim] = 1

--end CrossProductSweeper.py--

```