import HillClimb
import HillClimb3

# genCPRow()
#
# Parameters:
# domains: A list containing n domains over which to form Cartesian product.
#	   Must specify at least one domain.
#
# Yields: Each row in Cartesian product of the n domains.
#
def genCPRow(domains):
	# If there is more than one domain specified,
	if len(domains) > 1:
		# Get a row of the Cartesian product of the first n-1 domains.
		for sublist in genCPRow(domains[:-1]):
			# For every element in this domain, append it to row.
			for item in iter(domains[ len(domains)-1 ]):
				yield  sublist + [item]
				
	# If only one domain given, yield its elements.
	else:
		for item in iter(domains[ len(domains)-1 ]):
			yield [item]

# gen2Cover()
#
# Generates a 2-cover of index vectors of a set of domains.
#
# Parameters:
# domainSizes: List of sizes of each domain. Domain sizes must be nonzero.

# Yields: Rows in the 2-cover of the index vectors of the domains.
def gen2Cover(domainSizes):
	indexVectors = []
	for i in range(len(domainSizes)):
		indexVectors.append( range(domainSizes[i]) )
	
	# Yield each row in the 2-cover of index vectors.
	hc = HillClimb.HillClimb(indexVectors)
	for row in iter(hc):
		yield row

# gen3Cover()
#
# Generates a 3-cover of index vectors of a set of domains.
#
# Parameters:
# domainSizes: List of sizes of each domain. Domain sizes must be nonzero.

# Yields: Rows in the 2-cover of the index vectors of the domains.
def gen3Cover(domainSizes):
	indexVectors = []
	for i in range(len(domainSizes)):
		indexVectors.append( range(domainSizes[i]) )
	
	# Yield each row in the 2-cover of index vectors.
	hc = HillClimb3.HillClimb(indexVectors)
	for row in iter(hc):
		yield row

# gen1Cover()
#
# Generates a 1-cover of index vectors of a set of domains.
#
# Parameters:
# domainSizes: List of sizes of each domain. Domain sizes must be nonzero.
#
# Yields: Rows in the 1-cover of the index vectors of the domains.
def gen1Cover(domainSizes):
	index=0
	
	# Generate rows in the 1-cover.
	for reps in range(max(domainSizes)):
		
		# Create a list of size |domainSizes| with every element set to index.
		row = [index] * len(domainSizes)
		
		# Check for and correct any domain indices out of bounds.
		for i in range(len(domainSizes)):
			if row[i] >= domainSizes[i]:
				row[i] = domainSizes[i]-1
		index += 1
		yield row

# genNCover()
#
# Generates the Cartesian product of index vectors of a set of domains.
#
# Parameters:
# domainSizes: List of sizes of each domain. Domain sizes must be nonzero.
#
# Yields: Rows in the Cartesian Product of the index vectors of the domains.
def genNCover(domainSizes):
	# Generate Index Vectors.
	indexVectors = []
	for i in range(len(domainSizes)):
		indexVectors.append( range(domainSizes[i]) )
		
	# Yield each row in the Cartesian product of the index vectors.
	for row in genCPRow(indexVectors):
		yield row

