Ejemplo n.º 1
0
 def con(i, now):
     if len(now) == len(patt):
         yield now
     elif i < len(perm):
         nxt = now + [perm[i]]
         if Permutation.to_standard(nxt) == Permutation.to_standard(patt[:len(nxt)]):
             for res in con(i+1, nxt):
                 yield res
         for res in con(i+1, now):
             yield res
Ejemplo n.º 2
0
 def _assure_length(self, l):
     if l in self.permutations:
         return
     if l == 0:
         self.permutations[0] = [Permutation()]
     else:
         self._assure_length(l - 1)
         here = set()
         for p in self.permutations[l - 1]:
             for i in range(l):
                 q = p[:i] + (l, ) + p[i:]
                 if Permutation(q).avoids(*self.avoid):
                     here.add(q)
         self.permutations[l] = list(here)
Ejemplo n.º 3
0
    def sub_mesh_pattern(self, indices):
        """Return the mesh pattern induced by indices.

        Args:
            self:
                A mesh pattern.
            indices: <collections.Iterable> of <numbers.Integral>
                A list of unique indices of elements in self.

        Returns: permuta.MeshPattern
            A mesh pattern where the pattern is the permutation induced by the
            indices and a region is shaded if and only if the corresponding
            region of self is fully shaded.
        """
        indices = sorted(indices)
        if not indices:
            return MeshPattern()
        pattern = Permutation.to_standard(self.pattern[index] for index in indices)
        vertical = [0]
        vertical.extend(index + 1 for index in indices)
        vertical.append(len(self) + 1)
        horizontal = [0]
        horizontal.extend(sorted(self.pattern[index] for index in indices))
        horizontal.append(len(self) + 1)
        shading = frozenset((x, y)
                            for x in range(len(pattern) + 1)
                            for y in range(len(pattern) + 1)
                            if self.is_shaded((vertical[x],
                                               horizontal[y]),
                                              (vertical[x+1] - 1,
                                               horizontal[y+1] - 1)))
        return MeshPattern(pattern, shading)
Ejemplo n.º 4
0
 def test_direct_sum(self):
     p1 = Permutation(1243)
     p2 = Permutation(15324)
     p3 = Permutation(312)
     p4 = Permutation(1)
     p5 = Permutation()
     # All together
     result = p1.direct_sum(p2, p3, p4, p5)
     expected = Permutation((1,2,4,3,5,9,7,6,8,12,10,11,13))
     self.assertEqual(result, expected)
     # Two
     result = p1.direct_sum(p3)
     expected = Permutation((1,2,4,3,7,5,6))
     self.assertEqual(result, expected)
     # None
     self.assertEqual(p1.direct_sum(), p1)
Ejemplo n.º 5
0
 def test_skew_sum(self):
     p1 = Permutation(1243)
     p2 = Permutation(15324)
     p3 = Permutation(312)
     p4 = Permutation(1)
     p5 = Permutation()
     # All together
     result = p1.skew_sum(p2, p3, p4, p5)
     expected = Permutation((10,11,13,12,5,9,7,6,8,4,2,3,1))
     self.assertEqual(result, expected)
     # Two
     result = p1.skew_sum(p3)
     expected = Permutation((4,5,7,6,3,1,2))
     self.assertEqual(result, expected)
     # None
     self.assertEqual(p1.skew_sum(), p1)
Ejemplo n.º 6
0
    def occurrences_in(self, perm):
        """Find all indices of occurrences of self in perm.

        Args:
            self:
                The mesh pattern whose occurrences are to be found.
            perm: permuta.Permutation
                The permutation to search for occurrences in.

        Yields: [int]
            The indices of the occurrences of self in perm. Each yielded element
            l is a list of integer indices of the permutation perm such that
            self.pattern == permuta.Permutation.to_standard([perm[i] for i in l])
            and that no element not in the occurrence falls within self.shading.
        """
        # TODO: Implement all nice
        indices = list(range(len(perm)))
        for candidate_indices in itertools.combinations(indices, len(self)):
            candidate = [perm[index] for index in candidate_indices]
            if Permutation.to_standard(candidate) != self.pattern:
                continue
            x = 0
            for element in perm:
                if element in candidate:
                    x += 1
                    continue
                y = sum(1 for candidate_element in candidate
                        if candidate_element < element)
                if (x, y) in self.shading:
                    break
            else:
                # No unused point fell within shading
                yield list(candidate_indices)
Ejemplo n.º 7
0
    def add_rule(self, rule):
        self.total_rules += 1
        bs = 0
        curcnt = 0
        empty = True
        for l in range(self.settings.perm_bound+1):
            curlevel = []
            for perm in rule.generate_of_length(l, self.settings.sinput.permutations):
                if not self.settings.sinput.contains(perm):
                    # the rule generated something that doesn't satisfy perm_prop
                    self.death_by_perm_prop += 1
                    return RuleDeath.PERM_PROP

                curlevel.append(perm)

            cur = sorted(curlevel)
            for a,b in zip(cur, cur[1:]):
                if a == b:
                    # the rule generated something more than once (i.e. there is overlap)
                    self.death_by_overlap += 1
                    return RuleDeath.OVERLAP

            i = 0
            j = 0
            while i < len(cur) and j < len(self.permset[l]):
                if self.permset[l][j] < Permutation(cur[i]):
                    j += 1
                    curcnt += 1
                elif Permutation(cur[i]) == self.permset[l][j]:
                    bs |= 1 << curcnt
                    i += 1
                    j += 1
                    curcnt += 1
                    empty = False
                else:
                    assert False

            assert i == len(cur)
            curcnt += len(self.permset[l]) - j

        if empty:
            assert False

        self.rules.setdefault(bs, [])
        self.rules[bs].append(rule)
        return RuleDeath.ALIVE
Ejemplo n.º 8
0
 def _assure_length(self, l):
     if l in self.permutations:
         return
     if l == 0:
         self.permutations[0] = []
         maybe = Permutation([])
         if maybe.avoids(*self.avoidance):
             self.permutations[0].append(maybe)
     else:
         self._assure_length(l-1)
         here = set()
         for p in self.permutations[l-1]:
             for i in range(l):
                 q = Permutation(p[:i] + (l,) + p[i:])
                 if q.avoids(*self.avoidance):
                     here.add(q)
         self.permutations[l] = list(here)
Ejemplo n.º 9
0
    def test_to_standard(self):
        def gen(perm):
            res = list(perm)
            add = 0
            for i in perm.inverse():
                add += random.randint(0,10)
                res[i-1] += add
            return Permutation(res)

        for i in range(100):
            perm = Permutations(random.randint(0,20)).random_element()
            self.assertEqual(perm, Permutation.to_standard(perm))
            self.assertEqual(perm, Permutation.to_standard(gen(perm)))

        self.assertEqual(Permutation.to_standard(range(10)),
                         Permutation((1,2,3,4,5,6,7,8,9,10)))
        self.assertEqual(Permutation.to_standard(10 - x for x in range(5)),
                         Permutation((5,4,3,2,1)))
Ejemplo n.º 10
0
 def _assure_length(self, l):
     if l in self.permutations:
         return
     if l == 0:
         self.permutations[0] = []
         maybe = Permutation([])
         if maybe.avoids(*self.avoidance):
             self.permutations[0].append(maybe)
     else:
         self._assure_length(l - 1)
         here = set()
         for p in self.permutations[l - 1]:
             for i in range(l):
                 q = Permutation(p[:i] + (l, ) + p[i:])
                 if q.avoids(*self.avoidance):
                     here.add(q)
         self.permutations[l] = here
Ejemplo n.º 11
0
def taylor_dag(settings, max_len_patt=None, upper_bound=None, remove=False, remove_finite=True,
               subpattern_type=SubPatternType.EVERY):
    assert settings.sinput.avoidance is not None, "Tayloring is only supported for avoidance"
    patterns = settings.sinput.avoidance

    started = datetime.datetime.now()
    settings.logger.log('Tayloring DAG')

    elems = []
    if len(patterns) > 0:

        if max_len_patt is None:
            max_len_patt = max( len(p) for p in patterns )

        n = max( len(p) for p in patterns )
        sub = [ set([]) for _ in range(len(patterns)) ]

        for i,p in enumerate(patterns):
            last = set([ p ])
            if len(p) <= max_len_patt:
                sub[i] |= last
            for l in range(len(p)-1, 1, -1):
                nxt = set([])
                for q in last:
                    for j in range(len(q)):
                        qp = Permutation([ x-1 if x>q[j] else x for x in q[:j] + q[j+1:] ])

                        nxt.add(qp)
                if l <= max_len_patt:
                    sub[i] |= nxt
                last = nxt

        valid = set()
        for i,p in enumerate(patterns):
            if subpattern_type == SubPatternType.RECTANGULAR:
                for l in range(len(p)):
                    for r in range(l,len(p)):
                        here = sorted(p.perm[l:r+1])
                        for x in range(len(here)):
                            want = set()
                            for y in range(x,len(here)):
                                want.add(here[y])
                                cur = []
                                for j in range(l,r+1):
                                    if p.perm[j] in want:
                                        cur.append(p.perm[j])
                                if len(cur) <= max_len_patt:
                                    valid.add(Permutation.to_standard(cur))
            elif subpattern_type == SubPatternType.CONSECUTIVE:
                for l in range(len(p)):
                    for r in range(l,len(p)):
                        if r - l + 1 > max_len_patt:
                            break
                        here = p.perm[l:r+1]
                        if max(here) - min(here) + 1 == len(here):
                            valid.add(Permutation.to_standard(here))

        if subpattern_type != SubPatternType.EVERY:
            for i,p in enumerate(patterns):
                sub[i] &= valid

        def can_add(add, picked):
            for p in picked:
                if len(p) > len(add) and p.contains(add):
                    return False
                if len(add) > len(p) and add.contains(p):
                    return False
            return True

        def bt(at,picked,seen):
            if upper_bound is not None and len(picked) > upper_bound:
                pass
            elif picked == set(patterns):
                pass
            elif at == len(patterns):
                yield picked
            else:
                for s in subsets(list(sub[at] - picked - seen)):
                    npicked = set(picked)
                    ok = True
                    for add in set(s):
                        if not can_add(add, npicked):
                            ok = False
                            break
                        npicked.add(add)
                    if not ok:
                        continue

                    found = False
                    for q in npicked:
                        if patterns[at].contains(q):
                            found = True
                            break
                    if not found:
                        continue

                    for res in bt(at+1,npicked,seen | sub[at]):
                        yield res

        for ps in bt(0,set(),set()):
            # if remove_av_incr_decr:
            #     if any( p.is_increasing() for p in ps ) and any( p.is_decreasing() for p in ps ):
            #         continue
            s = AvoiderPermutationSet(ps)
            s._assure_length(settings.perm_bound)
            here = set()
            finite = False
            for l in range(settings.perm_bound+1):
                found = False
                for p in s.generate_of_length(l, {}):
                    here.add(Permutation(list(p)))
                    found = True
                if not found:
                    finite = True
                if finite and remove_finite and settings.sinput.is_classical:
                    break
            if finite and remove_finite and settings.sinput.is_classical:
                continue
            here = { Permutation(list(p)) for l in range(settings.perm_bound+1) for p in s.generate_of_length(l, {}) }
            elems.append((s, here, None))

    input = settings.sinput.get_permutation_set()
    elems.append((InputPermutationSet(settings), input, None))
    elems.append((N, set([ Permutation([]) ]), None))
    elems.append((P, set([ Permutation([1]) ]), None))

    res = DAG()
    if remove:
        for ps,here,descr in elems:
            rem = set()
            rems = []
            for qs,other,odescr in elems:
                if other and other < here:
                    rems.append(qs)
                    rem |= other

            if not here-rem:
                continue

            if rems:
                res.add_element(SubtractPermutationSet(ps, rems, alone_ok=type(ps) is not InputPermutationSet))
            else:
                res.add_element(ps)
    else:
        for ps,here,descr in elems:
            res.add_element(ps)

        for ps,here,descr in elems:
            for qs,other,odescr in elems:
                if other and other < here:
                    res.put_below(qs,ps)

    ended = datetime.datetime.now()
    settings.logger.log('Finished in %.3fs' % (ended - started).total_seconds())
    return res
Ejemplo n.º 12
0
def decr(n):
    return SimpleGeneratingRule(Permutation([2, 1]), [X, P],
                                description='decreasing').to_static(n, empty)
Ejemplo n.º 13
0
from permuta.misc import ordered_set_partitions, flatten
from permstruct.permutation_sets import PermutationSet, StaticPermutationSet, PointPermutationSet, InputPermutationSet

from permstruct import X, N, P, empty, generate_all_of_length
from permuta import Permutation, Permutations
from permstruct.permutation_sets import SimpleGeneratingRule, OverlayGeneratingRule

from itertools import product
from copy import deepcopy

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)


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))
Ejemplo n.º 14
0
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,
    )
Ejemplo n.º 15
0
from permuta import Permutation
from permstruct import *
from permstruct.dag import *

patts = [ Permutation([1,3,2]) ]
# patts = [ Permutation([1,3,2]), Permutation([4,3,1,2]) ]
# patts = [ Permutation([]), Permutation([]) ]
# patts = [Permutation([1,4,3,2]), Permutation([4,2,3,1])]
# patts = [Permutation([1,3,2,4])]
# patts = [Permutation([1, 4, 2, 3]), Permutation([2, 1, 4, 3]), Permutation([2, 4, 3, 1]), Permutation([3, 1, 4, 2]), Permutation([3, 2, 1, 4]), Permutation([3, 2, 4, 1]), Permutation([3, 4, 1, 2]), Permutation([4, 1, 2, 3]), Permutation([4, 2, 1, 3]), Permutation([4, 2, 3, 1]), Permutation([4, 3, 2, 1])]

# patts = [Permutation([3,2,1]), Permutation([2,1,4,3])]
# patts = [ Permutation([1,2,3]) ]
# patts = [ Permutation([1,3,2,4]) ]

perm_bound = 7
settings = StructSettings(
        perm_bound=perm_bound,
        verify_bound=7,
        max_rule_size=(3,3),
        max_non_empty=3,
        verbosity=StructLogger.INFO)
# settings.set_input(StructInput.from_avoidance(settings, patts))
settings.set_input(AvoiderInput(settings, patts))
# settings.set_dag(taylor_dag(settings, max_len_patt=3, remove=True, upper_bound=3))
# settings.set_dag(taylor_dag(settings, remove=False))
# el = taylor_dag(settings, remove=True, max_len_patt=2, upper_bound=1).elements
# print(el)
# print(len(el))

dag = taylor_dag(settings, remove=False, subpattern_type=SubPatternType.EVERY)
Ejemplo n.º 16
0
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,
        )
    return not is_polynomial(C)


def wrong_is_polynomial(C):
    overallinterset = set([])
    for perm in C:
        overallinterset = overallinterset.union(wrong_types(perm))
        if len(overallinterset) == 10:
            return True
    return False


def wrong_is_non_polynomial(C):
    return not wrong_is_polynomial(C)


while True:
    line = sys.stdin.readline()
    if not line:
        break
    line = line.strip()
    perms = [Permutation(list(map(int, p))) for p in line.split('_')]
    if is_non_polynomial(perms):
        print line

    # Use the stuff below to see what we first missed
    # winp = wrong_is_non_polynomial(perms)
    # inp = is_non_polynomial(perms)
    # if winp != inp:
    #     print line
    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))
Ejemplo n.º 19
0
def decr_nonempty(n):
    return SimpleGeneratingRule(Permutation([2, 1]), [X, P],
                                description='decreasing nonempty').to_static(
                                    n, {1: [Permutation([1])]})
Ejemplo n.º 20
0
def taylor_dag(settings,
               max_len_patt=None,
               upper_bound=None,
               remove=False,
               remove_finite=True,
               subpattern_type=SubPatternType.EVERY):
    assert settings.sinput.avoidance is not None, "Tayloring is only supported for avoidance"
    patterns = settings.sinput.avoidance

    started = datetime.datetime.now()
    settings.logger.log('Tayloring DAG')

    elems = []
    if len(patterns) > 0:

        if max_len_patt is None:
            max_len_patt = max(len(p) for p in patterns)

        n = max(len(p) for p in patterns)
        sub = [set([]) for _ in range(len(patterns))]

        for i, p in enumerate(patterns):
            last = set([p])
            if len(p) <= max_len_patt:
                sub[i] |= last
            for l in range(len(p) - 1, 1, -1):
                nxt = set([])
                for q in last:
                    for j in range(len(q)):
                        qp = Permutation([
                            x - 1 if x > q[j] else x for x in q[:j] + q[j + 1:]
                        ])

                        nxt.add(qp)
                if l <= max_len_patt:
                    sub[i] |= nxt
                last = nxt

        valid = set()
        for i, p in enumerate(patterns):
            if subpattern_type == SubPatternType.RECTANGULAR:
                for l in range(len(p)):
                    for r in range(l, len(p)):
                        here = sorted(p.perm[l:r + 1])
                        for x in range(len(here)):
                            want = set()
                            for y in range(x, len(here)):
                                want.add(here[y])
                                cur = []
                                for j in range(l, r + 1):
                                    if p.perm[j] in want:
                                        cur.append(p.perm[j])
                                if len(cur) <= max_len_patt:
                                    valid.add(Permutation.to_standard(cur))
            elif subpattern_type == SubPatternType.CONSECUTIVE:
                for l in range(len(p)):
                    for r in range(l, len(p)):
                        if r - l + 1 > max_len_patt:
                            break
                        here = p.perm[l:r + 1]
                        if max(here) - min(here) + 1 == len(here):
                            valid.add(Permutation.to_standard(here))

        if subpattern_type != SubPatternType.EVERY:
            for i, p in enumerate(patterns):
                sub[i] &= valid

        def can_add(add, picked):
            for p in picked:
                if len(p) > len(add) and p.contains(add):
                    return False
                if len(add) > len(p) and add.contains(p):
                    return False
            return True

        def bt(at, picked, seen):
            if upper_bound is not None and len(picked) > upper_bound:
                pass
            elif picked == set(patterns):
                pass
            elif at == len(patterns):
                yield picked
            else:
                for s in subsets(list(sub[at] - picked - seen)):
                    npicked = set(picked)
                    ok = True
                    for add in set(s):
                        if not can_add(add, npicked):
                            ok = False
                            break
                        npicked.add(add)
                    if not ok:
                        continue

                    found = False
                    for q in npicked:
                        if patterns[at].contains(q):
                            found = True
                            break
                    if not found:
                        continue

                    for res in bt(at + 1, npicked, seen | sub[at]):
                        yield res

        for ps in bt(0, set(), set()):
            # if remove_av_incr_decr:
            #     if any( p.is_increasing() for p in ps ) and any( p.is_decreasing() for p in ps ):
            #         continue
            s = AvoiderPermutationSet(ps)
            s._assure_length(settings.perm_bound)
            here = set()
            finite = False
            for l in range(settings.perm_bound + 1):
                found = False
                for p in s.generate_of_length(l, {}):
                    here.add(Permutation(list(p)))
                    found = True
                if not found:
                    finite = True
                if finite and remove_finite and settings.sinput.is_classical:
                    break
            if finite and remove_finite and settings.sinput.is_classical:
                continue
            here = {
                Permutation(list(p))
                for l in range(settings.perm_bound + 1)
                for p in s.generate_of_length(l, {})
            }
            elems.append((s, here, None))

    input = settings.sinput.get_permutation_set()
    elems.append((InputPermutationSet(settings), input, None))
    elems.append((N, set([Permutation([])]), None))
    elems.append((P, set([Permutation([1])]), None))

    res = DAG()
    if remove:
        for ps, here, descr in elems:
            rem = set()
            rems = []
            for qs, other, odescr in elems:
                if other and other < here:
                    rems.append(qs)
                    rem |= other

            if not here - rem:
                continue

            if rems:
                res.add_element(
                    SubtractPermutationSet(ps,
                                           rems,
                                           alone_ok=type(ps)
                                           is not InputPermutationSet))
            else:
                res.add_element(ps)
    else:
        for ps, here, descr in elems:
            res.add_element(ps)

        for ps, here, descr in elems:
            for qs, other, odescr in elems:
                if other and other < here:
                    res.put_below(qs, ps)

    ended = datetime.datetime.now()
    settings.logger.log('Finished in %.3fs' %
                        (ended - started).total_seconds())
    return res
Ejemplo n.º 21
0
#         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

# permProp = lambda perm: perm.avoids([1,2])
permProp = lambda perm: perm.avoids([2,3,1])
# permProp = lambda perm: perm.avoids([1,4,2,3])
Ejemplo n.º 22
0
def incr(n):
    return SimpleGeneratingRule(Permutation([1, 2]), [X, P],
                                description='increasing').to_static(n, empty)
Ejemplo n.º 23
0
 def contains(self, perm):
     if type(perm) is not Permutation:
         perm = Permutation(list(perm))
     return perm in self.permutations[len(perm)]
    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 rotate(perm):
    n = len(perm)
    return Permutation([ perm.index(n-i) + 1 for i in range(n)])
Ejemplo n.º 26
0
    def generate_of_length(self, n, input):

        if n == 1:
            yield Permutation([1])
Ejemplo n.º 27
0
    def test_taylor(self):

        settings = StructSettings(perm_bound=7,
                                  max_rule_size=(3, 3),
                                  max_non_empty=3)

        patts = [Permutation([1, 2, 3]), Permutation([3, 2, 1])]
        settings.set_input(StructInput.from_avoidance(settings, patts))
        res = taylor_dag(settings, remove=False)
        self.check([], res)

        patts = [Permutation([1, 2, 3]), Permutation([3, 2, 1])]
        settings.set_input(StructInput.from_avoidance(settings, patts))
        res = taylor_dag(settings, remove=False, remove_finite=False)
        self.check([
            [Permutation([1, 2]), Permutation([2, 1])],
            [Permutation([1, 2, 3]),
             Permutation([2, 1])],
            [Permutation([1, 2]), Permutation([3, 2, 1])],
        ], res)

        patts = [
            Permutation([1, 2, 3]),
            Permutation([3, 2, 1]),
        ]
        settings.set_input(StructInput.from_avoidance(settings, patts))
        res = taylor_dag(settings,
                         upper_bound=1,
                         remove=False,
                         remove_finite=False)
        self.check([], res)

        patts = [
            Permutation([1, 2, 3]),
            Permutation([3, 2, 1]),
        ]
        settings.set_input(StructInput.from_avoidance(settings, patts))
        res = taylor_dag(settings,
                         max_len_patt=2,
                         remove=False,
                         remove_finite=False)
        self.check([
            [Permutation([1, 2]), Permutation([2, 1])],
        ], res)