コード例 #1
0
def test_1234_fusion():
    __location__ = os.path.realpath(
        os.path.join(os.getcwd(), os.path.dirname(__file__)))
    with open(os.path.join(__location__, "spec-1234.json")) as f:
        d = json.loads(f.read())
    spec = CombinatorialSpecification.from_dict(d)
    assert isinstance(spec, CombinatorialSpecification)
    assert not any("NOTIMPLEMENTED" in str(eq.rhs)
                   for eq in spec.get_equations())
    assert [spec.count_objects_of_size(i) for i in range(15)] == [
        1,
        1,
        2,
        6,
        23,
        103,
        513,
        2761,
        15767,
        94359,
        586590,
        3763290,
        24792705,
        167078577,
        1148208090,
    ]
    av = Av([Perm((0, 1, 2, 3))])
    for i in range(10):
        assert set(av.of_length(i)) == set(
            gp.patt for gp in spec.generate_objects_of_size(i))
        assert spec.random_sample_object_of_size(i).patt in av
コード例 #2
0
def test_132_genf():
    searcher = TileScope([Perm((0, 2, 1))], point_placements)
    spec = searcher.auto_search(smallest=True)
    spec = spec.expand_verified()
    av = Av([Perm((0, 2, 1))])
    for i in range(10):
        assert set(av.of_length(i)) == set(
            gp.patt for gp in spec.generate_objects_of_size(i))
        assert spec.random_sample_object_of_size(i).patt in av
    gf = spec.get_genf()
    gf = sympy.series(spec.get_genf(), n=15)
    x = sympy.Symbol("x")
    assert [gf.coeff(x, n) for n in range(13)] == [
        1,
        1,
        2,
        5,
        14,
        42,
        132,
        429,
        1430,
        4862,
        16796,
        58786,
        208012,
    ]
コード例 #3
0
def test_123_positive_fusions():
    pack = TileScopePack.insertion_row_and_col_placements(
        row_only=True).make_fusion(tracked=True, apply_first=True)
    css = TileScope("123", pack)
    spec = css.auto_search(status_update=30)
    spec = spec.expand_verified()
    print(spec)
    assert isinstance(spec, CombinatorialSpecification)
    assert [spec.count_objects_of_size(i) for i in range(20)] == [
        1,
        1,
        2,
        5,
        14,
        42,
        132,
        429,
        1430,
        4862,
        16796,
        58786,
        208012,
        742900,
        2674440,
        9694845,
        35357670,
        129644790,
        477638700,
        1767263190,
    ]
    av = Av([Perm((0, 1, 2))])
    for i in range(10):
        assert set(av.of_length(i)) == set(
            gp.patt for gp in spec.generate_objects_of_size(i))
        assert spec.random_sample_object_of_size(i).patt in av
コード例 #4
0
 def get_permclass(self):
     if self.is_empty():
         return Av(Perm((0, )))
     elif self.is_point():
         return PermSet(1)
     elif self.is_anything():
         return PermSet()
     elif self.is_avoiding() and not self.is_containing():
         return Av(self.obstructions)
     else:
         return MockAvCoPatts(self.obstructions, self.requirements)
コード例 #5
0
    def __init__(self, av_patts, co_patts):
        self.base_perm_set = Av(av_patts)

        if isinstance(co_patts, (Perm, MeshPatt)):
            self.filter = lambda perm: perm.contains(co_patts)
        elif all(isinstance(patt, (Perm, MeshPatt)) for patt in co_patts):
            self.filter = lambda perm: any(
                perm.contains(patt) for patt in co_patts)
        else:
            raise ValueError("Variable 'co_patts' not as expected: "
                             "'{}'".format(co_patts))
コード例 #6
0
 def verified(self, comb_class: Tiling) -> bool:
     if not comb_class.dimensions == (1, 1):
         return False
     if not self.basis:
         return True
     tiling_class = Av([ob.patt for ob in comb_class.obstructions])
     sym_classes = (Av(sym) for sym in self.symmetries)
     is_strict_subclass = any(
         tiling_class.is_subclass(cls) and cls != tiling_class for cls in sym_classes
     )
     return is_strict_subclass or any(
         isinstance(ass, ComponentAssumption) for ass in comb_class.assumptions
     )
コード例 #7
0
def test_reverse_equiv():
    """A specification that should use reverse equivalence."""
    pack = TileScopePack(
        initial_strats=[
            strat.FactorFactory(),
            strat.RequirementCorroborationFactory(),
            strat.RequirementPlacementFactory(partial=False),
        ],
        inferral_strats=[strat.RowColumnSeparationStrategy()],
        expansion_strats=[[strat.CellInsertionFactory()]],
        ver_strats=[strat.BasicVerificationStrategy()],
        iterative=False,
        name="test pack",
    )
    basis = (Perm((0, 1, 3, 2)), Perm((0, 2, 3, 1)), Perm((1, 0, 3, 2)))
    # From https://oeis.org/A033321
    expected_enum = [
        1, 1, 2, 6, 21, 79, 311, 1265, 5275, 22431, 96900, 424068, 1876143
    ]
    x, f = sympy.symbols("x f")
    expected_min_poly = sympy.sympify("-4*f^2*x^2 + 8*f^2*x - 4*f*x - 4*f + 4")
    searcher = TileScope(basis, pack)
    spec = searcher.auto_search(smallest=True)
    assert [spec.count_objects_of_size(i) for i in range(13)] == expected_enum
    genf = spec.get_genf()
    assert sympy.simplify(expected_min_poly.subs(f, genf)) == 0
    assert taylor_expand(genf, 12) == expected_enum
    # In order to avoid ReccursionError we go incrementally
    for i in range(0, 100):
        spec.count_objects_of_size(i)
    assert spec.count_objects_of_size(50) == 86055297645519796258217673160170
    assert (
        spec.count_objects_of_size(100) ==
        2733073112795720153237297124938915907723365837935699807314396095313)
    len4_perms = tuple(spec.generate_objects_of_size(4))
    assert len(len4_perms) == 21
    assert all(p not in len4_perms for p in basis)
    len8_perms = tuple(spec.generate_objects_of_size(8))
    assert len(len8_perms) == 5275
    assert len(set(len8_perms)) == 5275
    for _ in range(10):
        gp = spec.random_sample_object_of_size(10)
        print(gp)
        assert gp.patt.avoids(*basis)

    av = Av(basis)
    for i in range(10):
        assert set(av.of_length(i)) == set(
            gp.patt for gp in spec.generate_objects_of_size(i))
        assert spec.random_sample_object_of_size(i).patt in av
コード例 #8
0
 def __str__(self) -> str:
     if self.maxreqlen == 1:
         return "point insertion"
     if self.extra_basis:
         perm_class = Av(self.extra_basis)
         return f"cell insertion from {perm_class} up to length {self.maxreqlen}"
     return f"cell insertion up to length {self.maxreqlen}"
コード例 #9
0
 def __str__(self) -> str:
     if self.extra_basis:
         perm_class = Av(self.extra_basis)
         return "requirement extension from {} up to " "length {}".format(
             perm_class, self.maxreqlen)
     return "requirement extension insertion up to " "length {}".format(
         self.maxreqlen)
コード例 #10
0
 def req_lists_to_insert(self, tiling: Tiling) -> Iterator[ListRequirement]:
     active = tiling.active_cells
     bdict = tiling.cell_basis()
     for cell, length in product(active, range(1, self.maxreqlen + 1)):
         basis = bdict[cell][0] + self.extra_basis
         yield from ((GriddedPerm.single_cell(patt, cell), )
                     for patt in Av(basis).of_length(length)
                     if not any(patt in perm for perm in bdict[cell][1]))
コード例 #11
0
 def __str__(self) -> str:
     if self.maxreqlen == 1:
         return "point insertion"
     if self.extra_basis:
         perm_class = Av(self.extra_basis)
         return "cell insertion from {} up to " "length {}".format(
             perm_class, self.maxreqlen)
     return "cell insertion up to length {}".format(self.maxreqlen)
コード例 #12
0
 def __str__(self) -> str:
     if not self.extra_basis:
         s = f"root insertion up to length {self.maxreqlen}"
     else:
         perm_class = Av(self.extra_basis)
         s = f"root insertion from {perm_class} up to length {self.maxreqlen}"
     if self.max_num_req is not None:
         s += f" (up to {self.max_num_req} requirements)"
     return s
コード例 #13
0
 def __str__(self) -> str:
     if not self.extra_basis:
         s = "root insertion up to length {}".format(self.maxreqlen)
     else:
         perm_class = Av(self.extra_basis)
         s = "root insertion from {} up to length {}".format(
             perm_class, self.maxreqlen)
     if self.max_num_req is not None:
         s += " (up to {} requirements)".format(self.max_num_req)
     return s
コード例 #14
0
 def req_lists_to_insert(self, tiling: Tiling) -> Iterator[ListRequirement]:
     bdict = tiling.cell_basis()
     cell_with_req = ((cell, obs, reqlist[0])
                      for cell, (obs, reqlist) in bdict.items()
                      if len(reqlist) == 1)
     for cell, obs, curr_req in cell_with_req:
         for length in range(len(curr_req) + 1, self.maxreqlen + 1):
             for patt in Av(obs + self.extra_basis).of_length(length):
                 if curr_req in patt:
                     yield (GriddedPerm.single_cell(patt, cell), )
コード例 #15
0
def simples_avoiding(basis):
    """
    Yield all simple permutations that avoid basis.

    You may wish to use the 'Av' class from permuta for iterating over
    permutations that avoid a given basis.
    A naive approach to know when to terminate is to use the fact that every
    length n simple contains a simple of length n - 1 or length n - 2.
    """
    av = Av(basis)
    longest = 4
    length = 4
    while True:
        if length - 2 > longest:
            break
        for perm in av.of_length(length):
            if perm.is_simple():
                yield perm
                longest = length
        length += 1
コード例 #16
0
    def test_get_elmnts_of_size_Av21_cell(self):
        mt = MeshTiling({
            (0, 0): Cell(frozenset({Perm((1, 0))}), frozenset()),
            (1, 1): MeshTiling.point_cell
        })

        for size in range(1, 5):
            expected_perms = set(Av([Perm((1, 0))]).of_length(size))
            mt_perms = mt.get_elmnts(of_size=size)
            assert (len(set(mt_perms)) == len(list(mt_perms)))
            assert (set(mt_perms) == expected_perms)
コード例 #17
0
def all_cell_insertions(tiling, **kwargs):
    """
    The cell insertion strategy.

    The cell insertion strategy is a batch strategy that considers each active
    cells, excluding positive cells. For each of these cells, the strategy
    considers all patterns (up to some maximum length given by maxreqlen, and
    some maximum number given by maxreqnum) and returns two tilings; one which
    requires the pattern in the cell and one where the pattern is obstructed.

    TODO:
        - Have a flag to insert into positive cells that contain the maximal
        intersections
    """
    maxreqlen = kwargs.get('maxreqlen')
    if not maxreqlen:
        maxreqlen = 1
    ignore_parent = kwargs.get('ignore_parent', False)
    extra_basis = kwargs.get('extra_basis')
    if extra_basis is None:
        extra_basis = []
    if (not isinstance(extra_basis, list)
            or not all(isinstance(p, Perm) for p in extra_basis)):
        raise TypeError("'extra_basis' flag should be a list of Perm to avoid")
    maxreqnum = kwargs.get('maxreqnum')
    if not maxreqnum:
        maxreqnum = 1

    active = tiling.active_cells
    bdict = tiling.cell_basis()
    for cell in active:
        if len(bdict[cell][1]) >= maxreqnum:
            continue
        for length in range(1, maxreqlen + 1):
            for patt in Av(bdict[cell][0] + extra_basis).of_length(length):
                if not any(patt in perm for perm in bdict[cell][1]):
                    if (tiling.dimensions != (1, 1)
                            or all(patt > perm for perm in bdict[cell][1])):
                        yield Rule(
                            formal_step=("Insert {} into cell {}.|{}|{}|{}|"
                                         "".format(
                                             patt, cell, cell[0], cell[1],
                                             "".join(str(i) for i in patt))),
                            comb_classes=cell_insertion(tiling, patt, cell),
                            ignore_parent=ignore_parent,
                            inferable=[True for _ in range(2)],
                            possibly_empty=[True for _ in range(2)],
                            workable=[True for _ in range(2)],
                            constructor='disjoint')
コード例 #18
0
class MockAvCoPatts:
    def __init__(self, av_patts, co_patts):
        self.base_perm_set = Av(av_patts)

        if isinstance(co_patts, (Perm, MeshPatt)):
            self.filter = lambda perm: perm.contains(co_patts)
        elif all(isinstance(patt, (Perm, MeshPatt)) for patt in co_patts):
            self.filter = lambda perm: any(
                perm.contains(patt) for patt in co_patts)
        else:
            raise ValueError("Variable 'co_patts' not as expected: "
                             "'{}'".format(co_patts))

    def of_length(self, size):
        return filter(self.filter, self.base_perm_set.of_length(size))
コード例 #19
0
    def req_lists_to_insert(self, tiling: Tiling) -> Iterator[ListRequirement]:
        if self.one_cell_only:
            assert self.maxreqlen == 1 and self.ignore_parent
            cells = sorted(
                frozenset(tiling.active_cells) - frozenset(tiling.positive_cells)
            )
            if cells:
                yield (GriddedPerm.single_cell((0,), cells[0]),)
            return

        active = tiling.active_cells
        bdict = tiling.cell_basis()
        for cell, length in product(active, range(1, self.maxreqlen + 1)):
            basis = bdict[cell][0] + self.extra_basis
            patterns = Av(basis).of_length(length) if basis else Perm.of_length(length)
            yield from (
                (GriddedPerm.single_cell(patt, cell),)
                for patt in patterns
                if not any(patt in perm for perm in bdict[cell][1])
            )
コード例 #20
0
def all_requirement_extensions(tiling, **kwargs):
    """Insert longer requirements in to cells which contain a requirement"""
    maxreqlen = kwargs.get('maxreqlen')
    if not maxreqlen:
        maxreqlen = 2
    extra_basis = kwargs.get('extra_basis')
    if extra_basis is None:
        extra_basis = []
    if (not isinstance(extra_basis, list)
            or not all(isinstance(p, Perm) for p in extra_basis)):
        raise TypeError("'extra_basis' flag should be a list of Perm to avoid")

    active = tiling.active_cells
    bdict = tiling.cell_basis()
    for cell in active:
        basis = bdict[cell][0]
        reqs = bdict[cell][1]
        if len(reqs) != 1:
            continue
        curr_req = reqs[0]
        for length in range(len(curr_req) + 1, maxreqlen + 1):
            for patt in Av(bdict[cell][0] + extra_basis).of_length(length):
                if curr_req in patt:
                    yield Rule(
                        formal_step=("Insert {} into cell {}."
                                     "".format(patt, cell)),
                        comb_classes=[
                            tiling.add_single_cell_obstruction(patt, cell),
                            tiling.add_single_cell_requirement(patt, cell)
                        ],
                        ignore_parent=False,
                        possibly_empty=[
                            any(len(r) > 1 for r in tiling.requirements), True
                        ],
                        inferable=[True for _ in range(2)],
                        workable=[True for _ in range(2)],
                        constructor='disjoint')
コード例 #21
0
def subclass_verified(tiling, basis, **kwargs):
    """The subclass verified strategy.

    A tiling is subclass verified if it only generates permutations in a
    proper subclass of Av(basis).
    """
    if tiling.dimensions == (1, 1):
        return None
    else:
        maxlen = kwargs.get('maxpattlen', 4)
        patterns = set(perm for perm in chain(
            *[Av(basis).of_length(i) for i in range(maxlen + 1)]))
        maxlen += tiling.maximum_length_of_minimum_gridded_perm()
        for i in range(maxlen + 1):
            for g in tiling.objects_of_length(i):
                perm = g.patt
                patterns = set(pattern for pattern in patterns
                               if perm.avoids(pattern))
                if not patterns:
                    return None
        return VerificationRule(formal_step=("The tiling belongs to the "
                                             "subclass obtained by adding"
                                             " the patterns {}."
                                             "".format(Basis(patterns))))
コード例 #22
0
def test_321_1324():
    searcher = TileScope("321_1324", reginsenc)
    spec = searcher.auto_search()
    assert isinstance(spec, CombinatorialSpecification)
    for i in range(20):
        gp = spec.random_sample_object_of_size(i)
        assert all(cell == (0, 0) for cell in gp.pos)
        assert gp.patt.avoids(Perm((2, 1, 0)), Perm((0, 2, 1, 3)))
    av = Av([Perm((2, 1, 0)), Perm((0, 2, 1, 3))])
    for i in range(10):
        assert set(av.of_length(i)) == set(
            gp.patt for gp in spec.generate_objects_of_size(i))
    assert [spec.count_objects_of_size(i) for i in range(50)] == [
        1,
        1,
        2,
        5,
        13,
        32,
        72,
        148,
        281,
        499,
        838,
        1343,
        2069,
        3082,
        4460,
        6294,
        8689,
        11765,
        15658,
        20521,
        26525,
        33860,
        42736,
        53384,
        66057,
        81031,
        98606,
        119107,
        142885,
        170318,
        201812,
        237802,
        278753,
        325161,
        377554,
        436493,
        502573,
        576424,
        658712,
        750140,
        851449,
        963419,
        1086870,
        1222663,
        1371701,
        1534930,
        1713340,
        1907966,
        2119889,
        2350237,
    ]
コード例 #23
0
 def formal_step(self) -> str:
     cls = Av(min(self.symmetries))
     if len(self.symmetries) == 1:
         return f"No cell is {cls}"
     return f"No cell is a symmetry of {cls}"