def generate_of_length(self, n, input): rule = list(self.rule.items()) h = max( k[0] for k,v in rule ) + 1 if rule else 1 w = max( k[1] for k,v in rule ) + 1 if rule else 1 def permute(arr, perm): res = [None] * len(arr) for i in range(len(arr)): res[i] = arr[perm[i] - 1] return res def count_assignments(at, left): if at == len(rule): if left == 0: yield [] elif type(rule[at][1]) is PointPermutationSet: # this doesn't need to be handled separately, # it's just an optimization if left > 0: for ass in count_assignments(at + 1, left - 1): yield [1] + ass else: for cur in range(left+1): for ass in count_assignments(at + 1, left - cur): yield [cur] + ass for count_ass in count_assignments(0, n): cntz = [ [ 0 for j in range(w) ] for i in range(h) ] for i, k in enumerate(count_ass): cntz[rule[i][0][0]][rule[i][0][1]] = k rowcnt = [ sum( cntz[row][col] for col in range(w) ) for row in range(h) ] colcnt = [ sum( cntz[row][col] for row in range(h) ) for col in range(w) ] for colpart in product(*[ ordered_set_partitions(range(colcnt[col]), [ cntz[row][col] for row in range(h) ]) for col in range(w) ]): scolpart = [ [ sorted(colpart[i][j]) for j in range(h) ] for i in range(w) ] for rowpart in product(*[ ordered_set_partitions(range(rowcnt[row]), [ cntz[row][col] for col in range(w) ]) for row in range(h) ]): srowpart = [ [ sorted(rowpart[i][j]) for j in range(w) ] for i in range(h) ] for perm_ass in product(*[ s[1].generate_of_length(cnt, input) for cnt, s in zip(count_ass, rule) ]): arr = [ [ [] for j in range(w) ] for i in range(h) ] for i, perm in enumerate(perm_ass): arr[rule[i][0][0]][rule[i][0][1]] = perm res = [ [None]*colcnt[col] for col in range(w) ] cumul = 1 for row in range(h-1,-1,-1): for col in range(w): for idx, val in zip(scolpart[col][row], permute(srowpart[row][col], arr[row][col])): res[col][idx] = cumul + val cumul += rowcnt[row] yield Permutation(flatten(res))
def get_elmnts(self, of_size): # Return permutations of length 'of_size' on a MeshTiling like this: # # ------------------------ # | | o | | # |----------+---+---------| # | Av(31#2) | | Av(1#2) | # ------------------------ # # The following code was shamelessly ported and adapted from # PermutaTriangle/grids repo, grids/Tilings.py file w = self.columns h = self.rows tiling = self.tiling def permute(arr, perm): res = [None] * len(arr) for i in range(len(arr)): res[i] = arr[perm[i]] return res def count_assignments(at, left): if at == len(self): # base case in recursion if left == 0: yield [] else: if tiling[at].is_point(): # one point in cell if left > 0: for ass in count_assignments(at + 1, left - 1): yield [1] + ass elif tiling[at].is_empty(): # no point in cell for ass in count_assignments(at + 1, left): yield [0] + ass else: for cur in range(left + 1): for ass in count_assignments(at + 1, left - cur): yield [cur] + ass elmnts_list = [] for count_ass in count_assignments(0, of_size): cntz = [[0 for j in range(w)] for i in range(h)] for i, k in enumerate(count_ass): (col, row) = self.convert_linear_number_to_coordinates(i) cntz[row][col] = k rowcnt = [sum(cntz[ro][co] for co in range(w)) for ro in range(h)] colcnt = [sum(cntz[ro][co] for ro in range(h)) for co in range(w)] for colpart in product(*[ ordered_set_partitions(range( colcnt[col]), [cntz[row][col] for row in range(h)]) for col in range(w) ]): scolpart = [[sorted(colpart[i][j]) for j in range(h)] for i in range(w)] for rowpart in product(*[ ordered_set_partitions(range( rowcnt[row]), [cntz[row][col] for col in range(w)]) for row in range(h) ]): srowpart = [[sorted(rowpart[i][j]) for j in range(w)] for i in range(h)] for perm_ass in product(*[ s.get_permclass().of_length(cnt) for cnt, s in zip(count_ass, tiling) ]): arr = [[[] for j in range(w)] for i in range(h)] for i, perm in enumerate(perm_ass): (col, row ) = self.convert_linear_number_to_coordinates(i) arr[row][col] = perm res = [[None] * colcnt[col] for col in range(w)] cumul = 0 for row in range(h): for col in range(w): for idx, val in zip( scolpart[col][row], permute(srowpart[row][col], arr[row][col])): res[col][idx] = cumul + val cumul += rowcnt[row] elmnts_list.append(Perm(flatten(res))) return elmnts_list
def generate_of_length(self, n, input): rule = list(self.rule.items()) h = max(k[0] for k, v in rule) + 1 if rule else 1 w = max(k[1] for k, v in rule) + 1 if rule else 1 def permute(arr, perm): res = [None] * len(arr) for i in range(len(arr)): res[i] = arr[perm[i] - 1] return res def count_assignments(at, left): if at == len(rule): if left == 0: yield [] elif type(rule[at][1]) is PointPermutationSet: # this doesn't need to be handled separately, # it's just an optimization if left > 0: for ass in count_assignments(at + 1, left - 1): yield [1] + ass else: for cur in range(left + 1): for ass in count_assignments(at + 1, left - cur): yield [cur] + ass for count_ass in count_assignments(0, n): for perm_ass in product(*[ s[1].generate_of_length(cnt, input) for cnt, s in zip(count_ass, rule) ]): arr = [[[] for j in range(w)] for i in range(h)] for i, perm in enumerate(perm_ass): arr[rule[i][0][0]][rule[i][0][1]] = perm rowcnt = [ sum(len(arr[row][col]) for col in range(w)) for row in range(h) ] colcnt = [ sum(len(arr[row][col]) for row in range(h)) for col in range(w) ] for colpart in product(*[ ordered_set_partitions( range(colcnt[col]), [len(arr[row][col]) for row in range(h)]) for col in range(w) ]): for rowpart in product(*[ ordered_set_partitions( range(rowcnt[row]), [len(arr[row][col]) for col in range(w)]) for row in range(h) ]): ok = True for idxs, perm_set in self.overlay: res = [[None] * colcnt[col] for col in range(w)] cumul = 1 for row in range(h - 1, -1, -1): for col in range(w): if (row, col) in idxs: for idx, val in zip( sorted(colpart[col][row]), permute( sorted(rowpart[row][col]), arr[row][col])): res[col][idx] = cumul + val cumul += rowcnt[row] perm = Permutation.to_standard(flatten(res)) if not perm_set.contains(perm): ok = False break if not ok: continue res = [[None] * colcnt[col] for col in range(w)] cumul = 1 for row in range(h - 1, -1, -1): for col in range(w): for idx, val in zip( sorted(colpart[col][row]), permute(sorted(rowpart[row][col]), arr[row][col])): res[col][idx] = cumul + val cumul += rowcnt[row] yield Permutation(flatten(res))
def test_ordered_set_partitions(self): it = ordered_set_partitions([1,2,3], [2,1]) self.assertEqual([[1,2],[3]], next(it)) self.assertEqual([[1,3],[2]], next(it)) self.assertEqual([[2,3],[1]], next(it)) with self.assertRaises(StopIteration): next(it) it = ordered_set_partitions([1,2,3], [2,1]) self.assertEqual([[1,2],[3]], next(it)) self.assertEqual([[1,3],[2]], next(it)) self.assertEqual([[2,3],[1]], next(it)) with self.assertRaises(StopIteration): next(it) lst = list(ordered_set_partitions([2,3,4,5,6], [2,1,2])) self.assertEqual([[[2, 3], [4], [5, 6]], [[2, 3], [5], [4, 6]], [[2, 3], [6], [4, 5]], [[2, 4], [3], [5, 6]], [[2, 4], [5], [3, 6]], [[2, 4], [6], [3, 5]], [[2, 5], [3], [4, 6]], [[2, 5], [4], [3, 6]], [[2, 5], [6], [3, 4]], [[2, 6], [3], [4, 5]], [[2, 6], [4], [3, 5]], [[2, 6], [5], [3, 4]], [[3, 4], [2], [5, 6]], [[3, 4], [5], [2, 6]], [[3, 4], [6], [2, 5]], [[3, 5], [2], [4, 6]], [[3, 5], [4], [2, 6]], [[3, 5], [6], [2, 4]], [[3, 6], [2], [4, 5]], [[3, 6], [4], [2, 5]], [[3, 6], [5], [2, 4]], [[4, 5], [2], [3, 6]], [[4, 5], [3], [2, 6]], [[4, 5], [6], [2, 3]], [[4, 6], [2], [3, 5]], [[4, 6], [3], [2, 5]], [[4, 6], [5], [2, 3]], [[5, 6], [2], [3, 4]], [[5, 6], [3], [2, 4]], [[5, 6], [4], [2, 3]]], sorted(lst)) lst = list(ordered_set_partitions([2,3,4,5,6], [3,1,1])) self.assertEqual([[[2, 3, 4], [5], [6]], [[2, 3, 4], [6], [5]], [[2, 3, 5], [4], [6]], [[2, 3, 5], [6], [4]], [[2, 3, 6], [4], [5]], [[2, 3, 6], [5], [4]], [[2, 4, 5], [3], [6]], [[2, 4, 5], [6], [3]], [[2, 4, 6], [3], [5]], [[2, 4, 6], [5], [3]], [[2, 5, 6], [3], [4]], [[2, 5, 6], [4], [3]], [[3, 4, 5], [2], [6]], [[3, 4, 5], [6], [2]], [[3, 4, 6], [2], [5]], [[3, 4, 6], [5], [2]], [[3, 5, 6], [2], [4]], [[3, 5, 6], [4], [2]], [[4, 5, 6], [2], [3]], [[4, 5, 6], [3], [2]]], sorted(lst))