def test_contained_in(self): def generate_contained(n,perm): for i in range(len(perm),n): r = random.randint(1,len(perm)+1) for i in range(len(perm)): if perm[i] >= r: perm[i] += 1 x = random.randint(0,len(perm)) perm = perm[:x] + [r] + perm[x:] return Permutation(perm) self.assertTrue(Permutation([4,8,1,9,2,7,6,3,5]).contained_in(Permutation([4,8,1,9,2,7,6,3,5]))) self.assertTrue(Permutation([]).contained_in(Permutation([]))) self.assertTrue(Permutation([]).contained_in(Permutation([4,8,1,9,2,7,6,3,5]))) self.assertTrue(Permutation([1]).contained_in(Permutation([1]))) self.assertFalse(Permutation([8,4,1,9,2,7,6,3,5]).contained_in(Permutation([4,8,1,9,2,7,6,3,5]))) for i in range(100): n = random.randint(0, 4) patt = Permutations(n).random_element() perm = generate_contained(random.randint(n, 8), list(patt)) self.assertTrue(patt.contained_in(perm)) self.assertFalse(Permutation([1]).contained_in(Permutation([]))) self.assertFalse(Permutation([1,2]).contained_in(Permutation([]))) self.assertFalse(Permutation([1,2]).contained_in(Permutation([1]))) self.assertFalse(Permutation([2, 1]).contained_in(Permutation([1, 2]))) self.assertFalse(Permutation([1,2,3]).contained_in(Permutation([1,2]))) self.assertFalse(Permutation([2, 1, 3]).contained_in(Permutation([1, 2, 4, 5, 3]))) self.assertFalse(Permutation([1, 2, 3]).contained_in(Permutation([3, 2, 4, 1]))) self.assertFalse(Permutation([3, 2, 4, 1]).contained_in(Permutation([3, 1, 4, 2]))) self.assertFalse(Permutation([1, 3, 2]).contained_in(Permutation([3, 1, 2, 4]))) self.assertFalse(Permutation([3, 1, 2, 4]).contained_in(Permutation([6, 4, 3, 8, 2, 1, 7, 5]))) self.assertFalse(Permutation([1, 2, 3, 4]).contained_in(Permutation([5, 8, 6, 2, 7, 3, 4, 1])))
def test_apply(self): for i in range(100): n = random.randint(0,20) lst = [ random.randint(0,10000) for i in range(n) ] perm = Permutations(n).random_element() res = list(perm.apply(lst)) for j,k in enumerate(perm.inverse()): self.assertEqual(lst[j], res[k-1])
def classic_avoiders_length_3(perm_prop, n): dag = N_P_X2_mon2(perm_prop, n) for p in Permutations(3): has_incr = Permutation([1, 2, 3]).avoids(p) has_decr = Permutation([3, 2, 1]).avoids(p) if has_incr and has_decr: pset = StaticPermutationSet.from_predicate( (lambda x: not x.avoids([1, 2]) and not x.avoids([2, 1]) and x. avoids(p)), n, description='Av(%s)-incr-decr' % (p)) elif has_incr: pset = StaticPermutationSet.from_predicate( (lambda x: not x.avoids([2, 1]) and x.avoids(p)), n, description='Av(%s)-incr' % (p)) elif has_decr: pset = StaticPermutationSet.from_predicate( (lambda x: not x.avoids([1, 2]) and x.avoids(p)), n, description='Av(%s)-decr' % (p)) else: pset = StaticPermutationSet.from_predicate( (lambda x: x.avoids(p)), n, description='Av(%s)' % (p)) # pset = StaticPermutationSet.from_predicate((lambda x: not x.avoids([1,2]) and not x.avoids([2,1]) and x.avoids(p) and x.avoids(q)), n, description='Av(%s,%s)-incr-decr' % (p, q)) # pset = StaticPermutationSet.from_predicate((lambda x: not x.avoids([2,1]) and x.avoids(p) and x.avoids(q)), n, description='Av(%s,%s)-incr-decr' % (p, q)) if any(len(pset.perms[l]) > 0 for l in pset.perms): dag.add_element(pset) # av123 = classical_avoiders(Permutation([1,2,3]), n) # av132 = classical_avoiders(Permutation([1,3,2]), n) # av213 = classical_avoiders(Permutation([2,1,3]), n) # av231 = classical_avoiders(Permutation([2,3,1]), n) # av312 = classical_avoiders(Permutation([3,1,2]), n) # av321 = classical_avoiders(Permutation([3,2,1]), n) # dag.add_element(av123) # dag.add_element(av132) # dag.add_element(av213) # dag.add_element(av231) # dag.add_element(av312) # dag.add_element(av321) # dag.put_below(d, av123) # dag.put_below(d, av132) # dag.put_below(d, av213) # dag.put_below(d, av231) # dag.put_below(d, av312) # dag.put_below(i, av132) # dag.put_below(i, av213) # dag.put_below(i, av231) # dag.put_below(i, av312) # dag.put_below(i, av321) return dag
def from_predicate(predicate, max_n, gf=None, description=None): perms = [] for n in range(max_n + 1): for perm in Permutations(n): if predicate(perm): perms.append(perm) return StaticPermutationSet(perms, gf, description)
def len_3_pairs_X1(perm_prop, n): dag = N_P_X1_mon2(perm_prop, n) for p in Permutations(3): for q in Permutations(3): if p < q: has_incr = Permutation([1, 2, 3]).avoids(p) and Permutation( [1, 2, 3]).avoids(q) has_decr = Permutation([3, 2, 1]).avoids(p) and Permutation( [3, 2, 1]).avoids(q) if has_incr and has_decr: pset = StaticPermutationSet.from_predicate( (lambda x: not x.avoids([1, 2]) and not x.avoids( [2, 1]) and x.avoids(p) and x.avoids(q)), n, description='Av(%s,%s)-incr-decr' % (p, q)) elif has_incr: pset = StaticPermutationSet.from_predicate( (lambda x: not x.avoids([2, 1]) and x.avoids(p) and x. avoids(q)), n, description='Av(%s,%s)-incr' % (p, q)) elif has_decr: pset = StaticPermutationSet.from_predicate( (lambda x: not x.avoids([1, 2]) and x.avoids(p) and x. avoids(q)), n, description='Av(%s,%s)-decr' % (p, q)) else: pset = StaticPermutationSet.from_predicate( (lambda x: x.avoids(p) and x.avoids(q)), n, description='Av(%s,%s)' % (p, q)) # pset = StaticPermutationSet.from_predicate((lambda x: not x.avoids([1,2]) and not x.avoids([2,1]) and x.avoids(p) and x.avoids(q)), n, description='Av(%s,%s)-incr-decr' % (p, q)) # pset = StaticPermutationSet.from_predicate((lambda x: not x.avoids([2,1]) and x.avoids(p) and x.avoids(q)), n, description='Av(%s,%s)-incr-decr' % (p, q)) if any(len(pset.perms[l]) > 0 for l in pset.perms): dag.add_element(pset) return dag
def enume(perm_prop, N): for n in range(N + 1): print sum([1 for perm in Permutations(n) if perm_prop(perm)]) print 'Done counting!' time.sleep(5)
def construct_rule(perm_prop, perm_bound, dag, max_rule_size, max_nonempty, max_rules, ignore_first=1, allow_overlap_in_first=True): """Tries to construct a set of generating rules that together generate the given permutation set. INPUT: - ``perm_prop`` - the permutation set expressed as a boolean predicate: perm_prop(p) should return True iff the permutation p is a part of the permutation set. - ``perm_bound`` - consider only permutations of length up to perm_bound, inclusive. - ``max_rule_size`` - a tuple (n, m) specifying that we should consider generating rules with at most n rows and at most m columns. - ``max_nonempty`` - the maximum number of non-empty boxes in the resulting generating rule. - ``max_rules`` - the maximum number of generating rules to match together. - ``dag`` - a list of tuples (f, g), where g is a generating rule and f is a boolean predicate: f(p) should return True iff the permutation p can be produced by g. These generating rules are possible candidates for boxes in the resulting generating rules. - ``ignore_first`` - ignore the smallest ``ignore_first`` permutations when doing the generating rule matching. So even if a set of generating rules don't produce a certain small permutation, they will still be considered. - ``allow_overlap_in_first`` - whether to allow overlap (that is, the same permutation being produced multiple times) in the ``ignore_first`` permutations. Note that if performance is an issue, the parameters ``perm_bound``, ``max_rule_size``, ``max_nonempty``, ``max_rules`` and ``dag`` can be tweaked for better performance, at the cost of lower number of results. This function currently doesn't return anything meaningful, but it does display its results to stdout. """ main_perms = [] for perm in Permutations(perm_bound): if perm_prop(perm): main_perms.append(tuple(perm)) # pick the main permutation to work with, currently just chooses one of the # largest ones randomly # TODO: be more smart about picking the permutations to learn from (or use all of them) random.shuffle(main_perms) main_perms = main_perms[:50] # main_perm = [ Permutation([1,2,3,4,5,6]) ] rules = RuleSet(perm_prop, perm_bound) tried_rules = set() for n in range(1, max_rule_size[0] + 1): for m in range(1, max_rule_size[1] + 1): for xsep in choose(perm_bound - 1, n - 1): for ysep in choose(perm_bound - 1, m - 1): for main_perm in main_perms: arr = [[[] for j in range(m)] for i in range(n)] nonempty_cnt = 0 ok = True for i in range(n): for j in range(m): for k in range( 0 if j == 0 else ysep[j - 1] + 1, (perm_bound - 1 if j == m - 1 else ysep[j]) + 1): if (0 if i == 0 else xsep[i - 1] + 1 ) <= perm_bound - main_perm[k] <= ( perm_bound - 1 if i == n - 1 else xsep[i]): arr[i][j].append(main_perm[k]) if arr[i][j]: nonempty_cnt += 1 if nonempty_cnt > max_nonempty: ok = False break if not ok: break if not ok: continue nonempty = [] for i in range(n): for j in range(m): if arr[i][j]: arr[i][j] = Permutation.to_standard( arr[i][j]) cur = [] # for inp_prop, inp in dag.elements: for inp in dag.elements: if inp is None: continue if inp.contains(arr[i][j]): cur.append((i, j, inp)) nonempty.append(cur) for poss in product(*nonempty): rule = GeneratingRule({(i, j): inp for i, j, inp in poss}) if rule in tried_rules: continue # print(rule) tried_rules.add(rule) rules.add_rule(rule) print('Found %d rules, %d of which are valid, %d of which are distinct' % ( len(tried_rules), sum(len(v) for k, v in rules.rules.items()), len(rules.rules), )) return rules.exact_cover( max_rules, ignore_first, allow_overlap_in_first, )
decr = SimpleGeneratingRule(Permutation([2, 1]), [X, P], description='decreasing').to_static(8, empty) def at_most_one_descent(p): found = False for i in range(1, len(p)): if p[i - 1] > p[i]: if found: return False found = True return True av123 = set([ tuple(p) for l in range(8) for p in Permutations(l) if p.avoids([1, 2, 3]) ]) # print(sorted(av123)) # +-+-+-+ # | |o| | # +-+-+-+ # |X| |1| # +-+-+-+ # 1: decreasing # set([(0, 1), (1, 1)]), <function <lambda> at 0x7fd1f7d8f938> # 0b111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110 # G = OverlayGeneratingRule([ # [N, P, N], # [X, N, decr]
# for l in range(1, 8): # cnt = 0 # for p in Permutations(l): # if avoids_231_vinc(p) and p.avoids([1,2,3]): # cnt += 1 # # print(p) # print(l, cnt) # # import sys # sys.exit(0) avoiders_len_3 = [] for p in Permutations(3): avoiders_len_3.append((lambda perm: perm.avoids(p),StaticPermutationSet.from_predicate(lambda x: x.avoids(p), 6, description='Av(%s)' % str(p)))) # avoiders_len_3.append((lambda perm: len(perm) >= 3 and perm.avoids(p),StaticPermutationSet.from_predicate(lambda x: x.avoids(p), 6, description='Av(%s)' % str(p)))) incr = SimpleGeneratingRule(Permutation([1,2]), [X, P], description='increasing').to_static(8, empty) decr = SimpleGeneratingRule(Permutation([2,1]), [X, P], description='decreasing').to_static(8, empty) incr_nonempty = SimpleGeneratingRule(Permutation([1,2]), [X, P], description='increasing nonempty').to_static(8, {1:[Permutation([1])]}) decr_nonempty = SimpleGeneratingRule(Permutation([2,1]), [X, P], description='decreasing nonempty').to_static(8, {1:[Permutation([1])]}) max_len = 6 n_range = (2, 3) # number of rows (min, max) m_range = (2, 3) # numbor of columns (min, max) max_nonempty = 4 max_ec_cnt = 4
def test_flip_antidiagonal(self): for i in range(100): perm = Permutations(random.randint(0,20)).random_element() self.assertEqual(perm.reverse().complement().inverse(), perm.flip_antidiagonal())
def test_reverse_complement(self): for i in range(100): perm = Permutations(random.randint(0,20)).random_element() self.assertEqual(perm.reverse_complement(), perm.rotate().rotate())
def generate_of_length(self, n, input): return [ p for p in Permutations(n) ]