示例#1
0
 def potential_new_obs(self) -> Set[GriddedPerm]:
     """
     Return the set of all subobstructions of the tiling.
     """
     subobs: Set[GriddedPerm] = set()
     for ob in self._tiling.obstructions:
         subobs.update(ob.all_subperms(proper=True))
     subobs.remove(GriddedPerm.empty_perm())
     return subobs
示例#2
0
def test_empty_perm():
    gp = GriddedPerm.empty_perm()
    assert gp.patt == Perm(())
    assert gp.pos == ()
    assert len(gp._cells) == 0
    assert GriddedPerm() == gp == GriddedPerm((), ())
示例#3
0
    def minimal_gridded_perms(self,
                              yield_non_minimal: bool = False
                              ) -> Iterator[GriddedPerm]:
        """
        Yield all minimal gridded perms on the tiling.

        If `yield_non_minimal` is True, then it will yield some gridded perms
        that are non-minimal, found by the initial_gp method. Even though it
        may not be minimal, this is useful when trying to determine whether or
        not a tiling is empty.
        """
        if not self.requirements:
            if GriddedPerm.empty_perm() not in self.obstructions:
                yield GriddedPerm.empty_perm()
            return
        if len(self.requirements) == 1:
            yield from self.requirements[0]
            return

        # a priority queue sorted by length of the gridded perm. This is
        # ensured by overwriting the __lt__ operator in the Info class.
        queue: List[QueuePacket] = []
        heapify(queue)

        initial_gps_to_auto_yield: Dict[int,
                                        Set[GriddedPerm]] = defaultdict(set)
        yielded: Set[GriddedPerm] = set()
        for gp in self._prepare_queue(queue):
            if yield_non_minimal:
                yielded.add(gp)
                yield gp
            else:
                initial_gps_to_auto_yield[len(gp)].add(gp)

        def yielded_subgridded_perm(gp: GriddedPerm) -> bool:
            """Return True if a subgridded perm was yielded."""
            return gp.contains(*yielded)

        def _process_work_packet(
            qpacket: QueuePacket,
            queue: List[QueuePacket],
        ) -> Iterator[GriddedPerm]:
            # now we try inserting a new point into the cell
            for (cell, localised) in self._get_cells_to_try(qpacket):
                # The `localised` bool tells us if we inserted into
                # a cell as it didn't contain the patterns in the
                # cell. If not, then we update the last cell, to
                # ensure we only insert into greater or equal cells
                next_cell = qpacket.last_cell if localised else cell
                # Insert a point in every way possible into cell, to the right
                # of any previously placed points in that cell.
                for idx, nextgp in self.insert_point(
                        qpacket.gp, cell, qpacket.mindices.get(cell, 0)):
                    # The work_packets_done is used to ensure the same
                    # task is not processed twice.
                    key = (nextgp, qpacket.gps, next_cell)
                    if key in work_packets_done:
                        continue
                    work_packets_done.add(key)
                    # Only work with gridded permutations avoiding the
                    # obstructions, and those which we haven't yielded a
                    # subgridded permutation.
                    if yielded_subgridded_perm(
                            nextgp) or not self.satisfies_obstructions(
                                nextgp, must_contain=cell):
                        continue
                    # Update the nextgp about the patterns that are
                    # contained in the subgridded permutation gp.
                    self.known_patts[nextgp].update(
                        self.known_patts[qpacket.gp])
                    # If it satisfies the requirements, then it is a
                    # a minimal gridded permutation
                    if self.satisfies_requirements(nextgp):
                        # Keep track to ensure we don't yield a gridded
                        # perm containing it.
                        yielded.add(nextgp)
                        yield nextgp
                    else:
                        # Update the minimum index that we inserted a
                        # a point into each cell.
                        next_mindices = {
                            c: i if i <= idx else i + 1
                            for c, i in qpacket.mindices.items() if c != cell
                        }
                        next_mindices[cell] = idx + 1
                        # Add the work to the queue
                        heappush(
                            queue,
                            QueuePacket(
                                nextgp,
                                qpacket.gps,
                                next_cell,
                                localised,
                                next_mindices,
                            ),
                        )

        work_packets_done: Set[WorkPackets] = set()
        curr_len = -1
        while queue:
            # take the next gridded permutation of the queue, together with the
            # theoretical counts to create a gridded permutation containing
            # each of gps.
            qpacket = heappop(queue)
            # if gp was one of the initial_gps that satisfied obs/reqs, but
            # we weren't sure at the time if it was minimal, then now is the
            # time to check and yield
            if curr_len != len(qpacket.gp):
                new_len = len(qpacket.gp)
                initial_to_yield = chain.from_iterable(
                    initial_gps_to_auto_yield.pop(i, tuple())
                    for i in range(curr_len + 1, new_len + 2))
                for gp in initial_to_yield:
                    if not yielded_subgridded_perm(gp):
                        yielded.add(gp)
                        yield gp
                curr_len = len(qpacket.gp)
            yield from _process_work_packet(qpacket, queue)
        # We yield any initial left after working on the work packet.
        # This happens in particular if you don't have any WP.
        initial_to_yield = chain.from_iterable(
            initial_gps_to_auto_yield.pop(i, tuple())
            for i in sorted(initial_gps_to_auto_yield))
        for gp in initial_to_yield:
            if not yielded_subgridded_perm(gp):
                yielded.add(gp)
                yield gp
示例#4
0
def test_all_cell_insertions_points(simple_tiling):
    point_insertion = CellInsertionFactory(maxreqlen=1)
    assert str(point_insertion) == "point insertion"
    rules = set(
        [tuple(s(simple_tiling).children) for s in point_insertion(simple_tiling)]
    )
    assert all(len(s) == 2 for s in rules)
    actual = set()
    actual.add(
        (
            Tiling(
                obstructions=[GriddedPerm(Perm((0,)), [(0, 1)])],
                requirements=[
                    [
                        GriddedPerm(Perm((0, 1)), [(0, 0), (1, 0)]),
                        GriddedPerm(Perm((0, 1)), [(0, 0), (1, 1)]),
                    ]
                ],
            ),
            Tiling(
                obstructions=[GriddedPerm(Perm((0,)), [(1, 0)])],
                requirements=[
                    [GriddedPerm(Perm((0,)), [(0, 1)])],
                    [GriddedPerm(Perm((0, 1)), [(0, 0), (1, 1)])],
                ],
            ),
        )
    )

    actual.add(
        (
            Tiling(
                obstructions=[
                    GriddedPerm(Perm((0,)), ((0, 1),)),
                    GriddedPerm(Perm((0,)), ((1, 0),)),
                ],
                requirements=[[GriddedPerm(Perm((0, 1)), ((0, 0), (1, 1)))]],
            ),
            Tiling(
                obstructions=[GriddedPerm(Perm((0,)), ((0, 1),))],
                requirements=[
                    [GriddedPerm(Perm((0,)), ((1, 0),))],
                    [
                        GriddedPerm(Perm((0, 1)), ((0, 0), (1, 0))),
                        GriddedPerm(Perm((0, 1)), ((0, 0), (1, 1))),
                    ],
                ],
            ),
        )
    )

    actual.add(
        (
            Tiling(obstructions=[GriddedPerm.empty_perm()]),
            Tiling(
                obstructions=[GriddedPerm(Perm((1, 0)), ((0, 1), (1, 0)))],
                requirements=[
                    [GriddedPerm(Perm((0,)), ((0, 0),))],
                    [
                        GriddedPerm(Perm((0, 1)), ((0, 0), (1, 0))),
                        GriddedPerm(Perm((0, 1)), ((0, 0), (1, 1))),
                    ],
                ],
            ),
        )
    )

    actual.add(
        (
            Tiling(requirements=[[GriddedPerm(Perm((0, 1)), ((0, 0), (1, 0)))]]),
            Tiling(
                obstructions=[GriddedPerm(Perm((1, 0)), ((0, 1), (1, 0)))],
                requirements=[
                    [GriddedPerm(Perm((0,)), ((1, 1),))],
                    [
                        GriddedPerm(Perm((0, 1)), ((0, 0), (1, 0))),
                        GriddedPerm(Perm((0, 1)), ((0, 0), (1, 1))),
                    ],
                ],
            ),
        )
    )
    assert rules == actual
示例#5
0
def test_empty_perm():
    gp = GriddedPerm.empty_perm()
    assert gp.patt == Perm(())
    assert gp.pos == ()