def simple_trans_row_len3(): return Tiling(obstructions=[Obstruction(Perm((0, 1)), [(0, 0), (1, 0)]), Obstruction(Perm((0, 1)), [(1, 0), (2, 0)]), Obstruction(Perm((0, 1)), [(2, 0), (3, 0)]), Obstruction(Perm((0, 1)), [(3, 0), (4, 0)])], requirements=[[Requirement(Perm((0,)), [(1, 0)])], [Requirement(Perm((0,)), [(2, 0)])], [Requirement(Perm((0,)), [(3, 0)])]])
def __init__(self, avoids=tuple(), contains=tuple(), tiling=None): if tiling is not None and isinstance(tiling, Tiling): self.tiling = tiling else: obs, reqs = stretch_av_and_co(avoids, contains, [(0, 1), (1, 0)]) reqs.extend([[Requirement.single_cell(Perm((0,)), (0, 1))], [Requirement.single_cell(Perm((0,)), (1, 0))]]) self.tiling = Tiling(obs, reqs)
def all_requirement_insertions(tiling, **kwargs): """Insert all possible requirements the obstruction allow.""" if kwargs.get("no_reqs", True) and tiling.requirements: return maxlen = kwargs.get("maxlen", 2) ignore_parent = kwargs.get("ignore_parent", False) obs_tiling = Tiling(tiling.obstructions, remove_empty=False, derive_empty=False, minimize=False, sorted_input=True) for length in range(1, maxlen + 1): for gp in obs_tiling.gridded_perms_of_length(length): if len(gp.factors()) == 1: av = Tiling( (tiling.obstructions + (Obstruction(gp.patt, gp.pos), )), tiling.requirements) co = Tiling(tiling.obstructions, (tiling.requirements) + ((Requirement(gp.patt, gp.pos), ), )) yield Rule(formal_step="Insert {}.".format(str(gp)), comb_classes=[av, co], 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')
def no_point_tiling(): """Returns a simple tiling with length of all obs and reqs at least 2. """ return Tiling(obstructions=[ Obstruction(Perm((1, 0)), [(0, 1), (0, 1)]), Obstruction(Perm((0, 1, 2)), [(0, 0), (1, 0), (1, 0)]), Obstruction(Perm((0, 1, 2)), [(1, 0), (1, 0), (2, 0)]), Obstruction(Perm((0, 2, 1)), [(0, 2), (0, 2), (1, 2)]), Obstruction(Perm((0, 2, 1)), [(0, 2), (1, 2), (1, 2)]) ], requirements=[[ Requirement(Perm((0, 1)), [(0, 0), (0, 0)]), Requirement(Perm((0, 1)), [(0, 0), (2, 0)]) ], [Requirement(Perm((0, 2, 1)), [(0, 1), (1, 1), (1, 1)])], [ Requirement(Perm((0, 1)), [(1, 1), (2, 1)]), Requirement(Perm((0, 1)), [(1, 1), (2, 2)]) ]])
def diverse_tiling(): """Returns a simple, but diverse tiling. The tiling has positive, possibly empty and empty cells and also few requirements and a long obstructions.""" return Tiling(obstructions=[ Obstruction(Perm((0, 2, 3, 1)), [(0, 0), (1, 1), (1, 1), (2, 0)]), Obstruction(Perm((0, 1)), [(1, 0), (1, 0)]), Obstruction(Perm((1, 0)), [(1, 0), (1, 0)]), Obstruction(Perm((0, 1)), [(2, 1), (2, 1)]), Obstruction(Perm((1, 0)), [(2, 1), (2, 1)]) ], requirements=[[ Requirement(Perm((0, 2, 1)), [(0, 1), (0, 2), (1, 2)]), Requirement(Perm((1, 0)), [(0, 2), (0, 1)]) ], [Requirement(Perm((0, )), [(1, 0)])], [Requirement(Perm((0, )), [(2, 0)])], [Requirement(Perm((0, )), [(2, 1)])]])
def test_factor_no_unions(simple_tiling, diverse_tiling, no_point_tiling): assert len(list(factor(simple_tiling))) == 0 assert len(list(factor(diverse_tiling))) == 0 tiling = Tiling(obstructions=[Obstruction(Perm((0, 1)), [(0, 0), (0, 0)])], requirements=[[ Requirement(Perm((0, 1)), [(1, 1), (1, 1)]), Requirement(Perm((0, 1)), [(1, 1), (1, 2)]) ]]) strats = [s.comb_classes for s in factor(tiling)] assert len(strats) == 1 factors = strats[0] assert set(factors) == set([ Tiling(requirements=[[ Requirement(Perm((0, 1)), [(0, 0), (0, 0)]), Requirement(Perm((0, 1)), [(0, 0), (0, 1)]) ]]), Tiling(obstructions=[Obstruction(Perm((0, 1)), [(0, 0), (0, 0)])]) ]) strats = [ s.comb_classes for s in factor(diverse_tiling, interleaving=True) ] assert len(strats) == 1 factors = strats[0] assert len(factors) == 4 print(diverse_tiling) assert set(factors) == set([ Tiling(obstructions=[ Obstruction(Perm((0, 2, 3, 1)), [(0, 0), (1, 1), (1, 1), (2, 0)]) ], requirements=[[Requirement(Perm((0, )), [(2, 0)])]]), Tiling(obstructions=[ Obstruction(Perm((0, 1)), [(0, 0), (0, 0)]), Obstruction(Perm((1, 0)), [(0, 0), (0, 0)]) ], requirements=[[Requirement(Perm((0, )), [(0, 0)])]]), Tiling(obstructions=[ Obstruction(Perm((0, 1)), [(0, 0), (0, 0)]), Obstruction(Perm((1, 0)), [(0, 0), (0, 0)]) ], requirements=[[Requirement(Perm((0, )), [(0, 0)])]]), Tiling(requirements=[[ Requirement(Perm((1, 0)), [(0, 2), (0, 1)]), Requirement(Perm((0, 2, 1)), [(0, 1), (0, 2), (1, 2)]) ]]) ])
def __init__(self, perm=Perm(), avoids=tuple(), contains=tuple(), tiling=None): if tiling is not None and isinstance(tiling, Tiling): self.tiling = tiling else: if not isinstance(perm, Perm) or not perm.is_simple(): raise ValueError("The first argument must be a simple Perm.") cells = [(i, v) for i, v in enumerate(perm)] obs, reqs = stretch_av_and_co(avoids, contains, cells) reqs.extend([[Requirement.single_cell(Perm((0,)), cell)] for cell in cells]) self.tiling = Tiling(obs, reqs)
def test_obstruction_transitivity(simple_trans_row, simple_trans_col, simple_trans_row_len2, simple_trans_row_len3): strat = obstruction_transitivity(simple_trans_row) assert strat.comb_classes[0] == Tiling( obstructions=[ Obstruction(Perm((0, 1)), [(0, 0), (1, 0)]), Obstruction(Perm((0, 1)), [(1, 0), (2, 0)]), Obstruction(Perm((0, 1)), [(0, 0), (2, 0)]) ], requirements=[[Requirement(Perm((0, )), [(1, 0)])]]) strat = obstruction_transitivity(simple_trans_col) assert strat.comb_classes[0] == Tiling( obstructions=[ Obstruction(Perm((0, 1)), [(0, 0), (0, 1)]), Obstruction(Perm((0, 1)), [(0, 1), (0, 2)]), Obstruction(Perm((0, 1)), [(0, 0), (0, 2)]) ], requirements=[[Requirement(Perm((0, )), [(0, 1)])]]) strat = obstruction_transitivity(simple_trans_row_len2) assert strat.comb_classes[0] == Tiling( obstructions=[ Obstruction(Perm((0, 1)), [(0, 0), (1, 0)]), Obstruction(Perm((0, 1)), [(0, 0), (2, 0)]), Obstruction(Perm((0, 1)), [(0, 0), (3, 0)]), Obstruction(Perm((0, 1)), [(1, 0), (2, 0)]), Obstruction(Perm((0, 1)), [(1, 0), (3, 0)]), Obstruction(Perm((0, 1)), [(2, 0), (3, 0)]) ], requirements=[[Requirement(Perm((0, )), [(1, 0)])], [Requirement(Perm((0, )), [(2, 0)])]]) strat = obstruction_transitivity(simple_trans_row_len3) assert strat.comb_classes[0] == Tiling( obstructions=[ Obstruction(Perm((0, 1)), [(0, 0), (1, 0)]), Obstruction(Perm((0, 1)), [(0, 0), (2, 0)]), Obstruction(Perm((0, 1)), [(0, 0), (3, 0)]), Obstruction(Perm((0, 1)), [(0, 0), (4, 0)]), Obstruction(Perm((0, 1)), [(1, 0), (2, 0)]), Obstruction(Perm((0, 1)), [(1, 0), (3, 0)]), Obstruction(Perm((0, 1)), [(1, 0), (4, 0)]), Obstruction(Perm((0, 1)), [(2, 0), (3, 0)]), Obstruction(Perm((0, 1)), [(2, 0), (4, 0)]), Obstruction(Perm((0, 1)), [(3, 0), (4, 0)]) ], requirements=[[Requirement(Perm((0, )), [(1, 0)])], [Requirement(Perm((0, )), [(2, 0)])], [Requirement(Perm((0, )), [(3, 0)])]])
def all_factor_insertions(tiling, **kwargs): ignore_parent = kwargs.get("ignore_parent", False) for gp in sorted(set(chain(tiling.obstructions, *tiling.requirements))): factors = gp.factors() if len(factors) != 1: for gp in factors: av = Tiling( (tiling.obstructions + (Obstruction(gp.patt, gp.pos), )), tiling.requirements) co = Tiling(tiling.obstructions, (tiling.requirements) + ((Requirement(gp.patt, gp.pos), ), )) yield Rule(formal_step="Insert {}.".format(str(gp)), comb_classes=[av, co], 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')
def col_insertion_helper(tiling, col, col_cells, regions=False): if col_cells is None: col_cells = tiling.cells_in_col(col) col_req = tuple(Requirement.single_cell(Perm((0, )), c) for c in col_cells) col_obs = tuple(Obstruction.single_cell(Perm((0, )), c) for c in col_cells) if regions: return ([ Tiling(tiling.obstructions + col_obs, tiling.requirements), Tiling(tiling.obstructions, tiling.requirements + (col_req, )) ], [{c: frozenset([c]) for c in tiling.active_cells}, {c: frozenset([c]) for c in tiling.active_cells}]) else: return [ Tiling(tiling.obstructions + col_obs, tiling.requirements), Tiling(tiling.obstructions, tiling.requirements + (col_req, )) ]
def row_insertion_helper(tiling, row, row_cells, regions=False): if row_cells is None: row_cells = tiling.cells_in_row(row) row_req = tuple(Requirement.single_cell(Perm((0, )), c) for c in row_cells) row_obs = tuple(Obstruction.single_cell(Perm((0, )), c) for c in row_cells) if regions: return ([ Tiling(tiling.obstructions + row_obs, tiling.requirements), Tiling(tiling.obstructions, tiling.requirements + (row_req, )) ], [{c: frozenset([c]) for c in tiling.active_cells}, {c: frozenset([c]) for c in tiling.active_cells}]) else: return [ Tiling(tiling.obstructions + row_obs, tiling.requirements), Tiling(tiling.obstructions, tiling.requirements + (row_req, )) ]
def test_all_cell_insertions(typical_redundant_requirements, typical_redundant_obstructions): tiling = Tiling(obstructions=typical_redundant_obstructions, requirements=typical_redundant_requirements) strats = list(all_cell_insertions(tiling, maxreqlen=3)) assert all(len(s.comb_classes) == 2 for s in strats) s = strats[-1] print(tiling) print(s.formal_step) print(s.comb_classes[0]) print(s.comb_classes[1]) assert s.comb_classes[0] == Tiling( obstructions=typical_redundant_obstructions + [Obstruction(Perm((0, 1, 2)), [(0, 1), (0, 1), (0, 1)])], requirements=typical_redundant_requirements) assert s.comb_classes[1] == Tiling( obstructions=typical_redundant_obstructions, requirements=typical_redundant_requirements + [[Requirement(Perm((0, 1, 2)), [(0, 1), (0, 1), (0, 1)])]])
def test_place_point_of_requirement(no_point_tiling): tiling = place_point_of_requirement(no_point_tiling, 2, 1, DIR_WEST) tiling2 = Tiling( obstructions=[ Obstruction(Perm((0, 1)), [(0, 1), (1, 3)]), Obstruction(Perm((0, 1)), [(2, 2), (2, 2)]), Obstruction(Perm((1, 0)), [(0, 1), (0, 1)]), Obstruction(Perm((1, 0)), [(0, 3), (0, 1)]), Obstruction(Perm((1, 0)), [(0, 3), (0, 3)]), Obstruction(Perm((1, 0)), [(2, 2), (2, 2)]), Obstruction(Perm((0, 1, 2)), [(0, 0), (1, 0), (1, 0)]), Obstruction(Perm((0, 1, 2)), [(0, 0), (1, 0), (3, 0)]), Obstruction(Perm((0, 1, 2)), [(0, 0), (3, 0), (3, 0)]), Obstruction(Perm((0, 1, 2)), [(1, 0), (1, 0), (4, 0)]), Obstruction(Perm((0, 1, 2)), [(1, 0), (3, 0), (4, 0)]), Obstruction(Perm((0, 1, 2)), [(3, 0), (3, 0), (4, 0)]), Obstruction(Perm((0, 2, 1)), [(0, 1), (1, 1), (1, 1)]), Obstruction(Perm((0, 2, 1)), [(0, 1), (1, 1), (3, 1)]), Obstruction(Perm((0, 2, 1)), [(0, 3), (1, 3), (1, 3)]), Obstruction(Perm((0, 2, 1)), [(0, 3), (1, 3), (3, 3)]), Obstruction(Perm((0, 2, 1)), [(0, 4), (0, 4), (1, 4)]), Obstruction(Perm((0, 2, 1)), [(0, 4), (0, 4), (3, 4)]), Obstruction(Perm((0, 2, 1)), [(0, 4), (1, 4), (1, 4)]), Obstruction(Perm((0, 2, 1)), [(0, 4), (1, 4), (3, 4)]), Obstruction(Perm((0, 2, 1)), [(0, 4), (3, 4), (3, 4)]) ], requirements=[[Requirement(Perm((0, )), [(2, 2)])], [ Requirement(Perm((0, 1)), [(0, 0), (0, 0)]), Requirement(Perm((0, 1)), [(0, 0), (4, 0)]) ], [Requirement(Perm((0, 1)), [(0, 1), (3, 1)])], [ Requirement(Perm((0, 1)), [(1, 1), (4, 1)]), Requirement(Perm((0, )), [(4, 3)]), Requirement(Perm((0, )), [(4, 4)]), Requirement(Perm((0, 1)), [(3, 1), (4, 1)]) ]]) assert tiling == tiling2
def simple_tiling(): return Tiling(obstructions=[Obstruction(Perm((1, 0)), [(0, 1), (1, 0)])], requirements=[[ Requirement(Perm((0, 1)), [(0, 0), (1, 0)]), Requirement(Perm((0, 1)), [(0, 0), (1, 1)]) ]])
def __init__(self, avoids=tuple(), contains=tuple()): obs, reqs = stretch_av_and_co(avoids, contains, [(0, 0)]) reqs.append([Requirement.single_cell(Perm((0,)), (0, 0))]) self.tiling = Tiling(obs, reqs)
def simple_trans_col(): return Tiling(obstructions=[Obstruction(Perm((0, 1)), [(0, 0), (0, 1)]), Obstruction(Perm((0, 1)), [(0, 1), (0, 2)])], requirements=[[Requirement(Perm((0,)), [(0, 1)])]])
def partial_place_point_of_requirement(tiling, req_index, point_index, force_dir): """ Places the point at point_index in requirement at req_index into tiling on its own row or onto its own column depending on force_dir. """ if len(tiling.requirements[req_index]) > 1: raise ValueError( "Requirement list at {} contains more than 1 requirement.".format( req_index)) # Determine if placing onto own row or column row = (force_dir == DIR_NORTH or force_dir == DIR_SOUTH) # The requirement requirement = tiling.requirements[req_index][0] # The cell containing the point cell = requirement.pos[point_index] # The rest of the requirements other_reqs = [ tiling.requirements[i] for i in range(len(tiling.requirements)) if i != req_index ] # Placing the forced occurrence of the point in the requirement new_req, forced_obstructions = requirement.partial_place_forced_point( point_index, force_dir) assert len(new_req) == 1 # New indices of the point. point_cell = (cell[0] if row else cell[0] + 1, cell[1] + 1 if row else cell[1]) # The set of new obstructions, consisting of the forced obstructions, other # obstructions where the point placement has been taken into account and # the 12, 21 in the cell. newobs = forced_obstructions + list( chain.from_iterable( ob.place_point(cell, DIR_NONE, partial=True, row=row) for ob in tiling.obstructions)) + [ Obstruction.single_cell(Perm((0, 1)), point_cell), Obstruction.single_cell(Perm((1, 0)), point_cell) ] # If a point cell, make sure neighbouring cells are empty by adding the # point obstructions. if cell in tiling.point_cells: if force_dir == DIR_EAST or force_dir == DIR_WEST: newobs = (newobs + [ Obstruction.single_cell(Perm((0, )), (point_cell[0] + 1, point_cell[1])), Obstruction.single_cell(Perm((0, )), (point_cell[0] - 1, point_cell[1])) ]) elif force_dir == DIR_NORTH or force_dir == DIR_SOUTH: newobs = (newobs + [ Obstruction.single_cell(Perm((0, )), (point_cell[0], point_cell[1] + 1)), Obstruction.single_cell(Perm((0, )), (point_cell[0], point_cell[1] - 1)) ]) # The new requirements, consisting of the requirement with the point # placed, other requirements where point placement has been taken into # account and the point requirement in the cell. newreqs = [ list( chain.from_iterable( req.place_point(cell, DIR_NONE, partial=True, row=row) for req in reqs)) for reqs in other_reqs ] + [new_req] + [[Requirement.single_cell(Perm((0, )), point_cell)]] return Tiling(obstructions=newobs, requirements=newreqs)
def __init__(self, avoids=tuple(), contains=tuple()): obs, reqs = stretch_av_and_co(avoids, contains, [(0, 0)]) obs.extend([Obstruction.single_cell(Perm((0, 1)), (0, 0)), Obstruction.single_cell(Perm((1, 0)), (0, 0))]) reqs.extend([[Requirement.single_cell(Perm((0,)), (0, 0))]]) self.tiling = Tiling(obs, reqs)
def test_place_point_of_requirement_point_only(diverse_tiling): tiling = place_point_of_requirement(diverse_tiling, 0, 0, DIR_WEST) assert tiling == Tiling( obstructions=[ Obstruction(Perm((0, )), [(1, 0)]), Obstruction(Perm((0, )), [(1, 2)]), Obstruction(Perm((0, )), [(2, 0)]), Obstruction(Perm((0, )), [(2, 2)]), Obstruction(Perm((0, 1)), [(2, 1), (2, 1)]), Obstruction(Perm((0, 1)), [(4, 3), (4, 3)]), Obstruction(Perm((1, 0)), [(2, 1), (2, 1)]), Obstruction(Perm((1, 0)), [(4, 3), (4, 3)]), Obstruction(Perm((0, 2, 3, 1)), [(0, 0), (1, 3), (1, 3), (4, 0)]), Obstruction(Perm((0, 2, 3, 1)), [(0, 0), (1, 3), (1, 3), (4, 2)]), Obstruction(Perm((0, 2, 3, 1)), [(0, 0), (1, 3), (3, 3), (4, 0)]), Obstruction(Perm((0, 2, 3, 1)), [(0, 0), (1, 3), (3, 3), (4, 2)]), Obstruction(Perm((0, 2, 3, 1)), [(0, 0), (3, 3), (3, 3), (4, 0)]), Obstruction(Perm((0, 2, 3, 1)), [(0, 0), (3, 3), (3, 3), (4, 2)]), Obstruction(Perm((0, 2, 3, 1)), [(0, 2), (1, 3), (1, 3), (4, 2)]), Obstruction(Perm((0, 2, 3, 1)), [(0, 2), (1, 3), (3, 3), (4, 2)]), Obstruction(Perm((0, 2, 3, 1)), [(0, 2), (3, 3), (3, 3), (4, 2)]) ], requirements=[[Requirement(Perm((0, )), [(2, 1)])], [Requirement(Perm((0, )), [(4, 3)])], [ Requirement(Perm((0, )), [(4, 0)]), Requirement(Perm((0, )), [(4, 2)]) ], [ Requirement(Perm((1, 0)), [(0, 4), (0, 3)]), Requirement(Perm((0, 2, 1)), [(0, 3), (0, 4), (1, 4)]), Requirement(Perm((0, 2, 1)), [(0, 3), (0, 4), (3, 4)]) ]]) assert tiling == place_point_of_requirement(diverse_tiling, 0, 0, DIR_EAST) assert tiling == place_point_of_requirement(diverse_tiling, 0, 0, DIR_NORTH) assert tiling == place_point_of_requirement(diverse_tiling, 0, 0, DIR_SOUTH) tiling = place_point_of_requirement(diverse_tiling, 1, 0, DIR_WEST) assert tiling == Tiling( obstructions=[ Obstruction(Perm((0, )), [(2, 0)]), Obstruction(Perm((0, )), [(2, 2)]), Obstruction(Perm((0, 1)), [(1, 0), (1, 0)]), Obstruction(Perm((0, 1)), [(1, 0), (1, 2)]), Obstruction(Perm((0, 1)), [(1, 2), (1, 2)]), Obstruction(Perm((0, 1)), [(3, 1), (3, 1)]), Obstruction(Perm((0, 1)), [(2, 3), (2, 3)]), Obstruction(Perm((0, 1)), [(2, 3), (4, 3)]), Obstruction(Perm((0, 1)), [(4, 3), (4, 3)]), Obstruction(Perm((1, 0)), [(1, 0), (1, 0)]), Obstruction(Perm((1, 0)), [(1, 2), (1, 0)]), Obstruction(Perm((1, 0)), [(1, 2), (1, 2)]), Obstruction(Perm((1, 0)), [(3, 1), (3, 1)]), Obstruction(Perm((1, 0)), [(2, 3), (2, 3)]), Obstruction(Perm((1, 0)), [(2, 3), (4, 3)]), Obstruction(Perm((1, 0)), [(4, 3), (4, 3)]), Obstruction(Perm((0, 1, 2)), [(0, 0), (1, 3), (1, 3)]), Obstruction(Perm((0, 2, 3, 1)), [(0, 2), (1, 3), (1, 3), (4, 2)]) ], requirements=[[Requirement(Perm((0, )), [(3, 1)])], [ Requirement(Perm((0, )), [(1, 0)]), Requirement(Perm((0, )), [(1, 2)]) ], [ Requirement(Perm((0, )), [(2, 3)]), Requirement(Perm((0, )), [(4, 3)]) ], [ Requirement(Perm((1, 0)), [(0, 4), (0, 3)]), Requirement(Perm((0, 2, 1)), [(0, 3), (0, 4), (1, 4)]) ]]) tiling = Tiling(requirements=[[Requirement(Perm((0, )), [(0, 0)])]]) assert place_point_of_requirement(tiling, 0, 0, DIR_SOUTH) == Tiling( obstructions=[ Obstruction(Perm((0, 1)), [(0, 0), (0, 0)]), Obstruction(Perm((1, 0)), [(0, 0), (0, 0)]) ], requirements=[[Requirement(Perm((0, )), [(0, 0)])]])
def place_requirement_list(tiling, req_list, direction, regions=False): """Return the list of tilings obtained by placing the direction-most point of a requirement list. This represents a batch strategy, where the direction-most point of each requirement in the list is placed.""" # Compute the points furthest in the given direction. min_points = minimum_points(req_list, direction) if len([c for _, c in min_points]) != len(set([c for _, c in min_points])): # Can't handle list requirements with more than req farthest in the # direction in same cell. return None # For each tiling, compute the tiling where this point is placed furthest # in that direction. res = [] if regions: forward_maps = [] for (idx, cell), req in zip(min_points, req_list): # Placing the forced occurrence of the point in the requirement new_req, forced_obstructions = req.place_forced_point(idx, direction) assert len(new_req) == 1 # Add the forced obstruction to ensure no other requirement has a point # further in that direction. forced_obstructions = (forced_obstructions + list( chain.from_iterable( r.other_req_forced_point(cell, direction) for r in req_list if r != req))) # New indices of the point point_cell = (cell[0] + 1, cell[1] + 1) # The set of new obstructions, consisting of the forced obstructions, # other obstructions where the point placement has been taken into # account and the 12, 21 in the cell. newobs = forced_obstructions + list( chain.from_iterable( ob.place_point(cell, DIR_NONE) for ob in tiling.obstructions)) + [ Obstruction.single_cell(Perm((0, 1)), point_cell), Obstruction.single_cell(Perm((1, 0)), point_cell) ] # The rest of the requirements other_reqs = [reqs for reqs in tiling.requirements if reqs != req_list] # The new requirements, consisting of the requirement with the point # placed, other requirements where point placement has been taken into # account and the point requirement in the cell. newreqs = [ list( chain.from_iterable( r.place_point(cell, DIR_NONE) for r in reqs)) for reqs in other_reqs ] + [new_req] + [[Requirement.single_cell(Perm((0, )), point_cell)]] placed_tiling = Tiling(newobs, newreqs) res.append(placed_tiling) if regions: def cell_map(c): mindex, minval = c maxdex = mindex + 1 maxval = minval + 1 if mindex >= cell[0]: maxdex += 2 if minval >= cell[1]: maxval += 2 if mindex > cell[0]: mindex += 2 if minval > cell[1]: minval += 2 return frozenset([(x, y) for x in range(mindex, maxdex) for y in range(minval, maxval)]) forward_maps.append({c: cell_map(c) for c in tiling.active_cells}) if regions: return res, forward_maps else: return res
def typical_requirements_with_local(): """Return a very typical list of requirements of a tiling, including some local length 1 requirements.""" return [[ Requirement(Perm((0, 1, 2)), ((0, 0), (1, 0), (2, 3))), Requirement(Perm((0, 1, 2)), ((0, 0), (1, 0), (2, 4))), Requirement(Perm((1, 0, 2)), ((0, 0), (1, 0), (2, 3))), Requirement(Perm((1, 0, 2)), ((0, 1), (1, 0), (2, 3))) ], [ Requirement(Perm((0, 1)), ((1, 0), (3, 0))), Requirement(Perm((0, 1)), ((2, 0), (2, 0))), Requirement(Perm((0, 1)), ((2, 0), (3, 0))), Requirement(Perm((0, 1)), ((2, 0), (3, 1))) ], [Requirement(Perm((0, )), ((3, 0), ))], [Requirement(Perm((1, 0)), ((2, 0), (2, 0)))], [Requirement(Perm((0, 2, 1)), ((0, 0), (2, 3), (2, 3)))]]
def typical_redundant_requirements(): """Returns a very typical list of requirements of a tiling. """ return [[ Requirement(Perm((0, 1, 2)), ((0, 0), (1, 0), (2, 3))), Requirement(Perm((0, 1, 2)), ((0, 0), (1, 0), (2, 4))), Requirement(Perm((1, 0, 2)), ((0, 0), (1, 0), (2, 3))), Requirement(Perm((1, 0, 2)), ((0, 1), (1, 0), (2, 3))) ], [ Requirement(Perm((0, 1, 2)), ((2, 3), (2, 3), (2, 3))), Requirement(Perm((1, 0, 2)), ((0, 0), (0, 0), (0, 0))), Requirement(Perm((0, 1, 2)), ((1, 0), (1, 0), (1, 0))) ], [ Requirement(Perm((0, 1)), ((1, 0), (3, 0))), Requirement(Perm((0, 1)), ((2, 0), (2, 0))), Requirement(Perm((0, 1)), ((2, 0), (3, 0))), Requirement(Perm((0, 1)), ((2, 0), (3, 1))) ], [ Requirement(Perm((1, 0)), ((3, 3), (3, 1))), Requirement(Perm((1, 0)), ((3, 1), (3, 1))), Requirement(Perm((1, 0)), ((3, 1), (3, 0))) ]]
def test_all_cell_insertions_points(simple_tiling): strats = [ s.comb_classes for s in all_cell_insertions(simple_tiling, maxreqlen=1) ] assert all(len(s) == 2 for s in strats) s = strats[0] assert s[0] == Tiling(obstructions=[Obstruction(Perm((0, )), [(0, 1)])], requirements=[[ Requirement(Perm((0, 1)), [(0, 0), (1, 0)]), Requirement(Perm((0, 1)), [(0, 0), (1, 1)]) ]]) assert s[1] == Tiling( obstructions=[Obstruction(Perm((0, )), [(1, 0)])], requirements=[[Requirement(Perm((0, )), [(0, 1)])], [Requirement(Perm((0, 1)), [(0, 0), (1, 1)])]]) s = strats[1] assert s[0] == Tiling( obstructions=[ Obstruction(Perm((0, )), ((0, 1), )), Obstruction(Perm((0, )), ((1, 0), )) ], requirements=[[Requirement(Perm((0, 1)), ((0, 0), (1, 1)))]]) assert s[1] == Tiling( obstructions=[Obstruction(Perm((0, )), ((0, 1), ))], requirements=[[Requirement(Perm((0, )), ((1, 0), ))], [ Requirement(Perm((0, 1)), ((0, 0), (1, 0))), Requirement(Perm((0, 1)), ((0, 0), (1, 1))) ]]) s = strats[2] assert s[0] == Tiling(obstructions=[Obstruction(Perm(tuple()), tuple())]) assert s[1] == Tiling( obstructions=[Obstruction(Perm((1, 0)), ((0, 1), (1, 0)))], requirements=[[Requirement(Perm((0, )), ((0, 0), ))], [ Requirement(Perm((0, 1)), ((0, 0), (1, 0))), Requirement(Perm((0, 1)), ((0, 0), (1, 1))) ]]) s = strats[3] assert s[0] == Tiling( requirements=[[Requirement(Perm((0, 1)), ((0, 0), (1, 0)))]]) assert s[1] == Tiling( obstructions=[Obstruction(Perm((1, 0)), ((0, 1), (1, 0)))], requirements=[[Requirement(Perm((0, )), ((1, 1), ))], [ Requirement(Perm((0, 1)), ((0, 0), (1, 0))), Requirement(Perm((0, 1)), ((0, 0), (1, 1))) ]])
def test_requirement_corroboration(typical_redundant_requirements, typical_redundant_obstructions): tiling = Tiling(obstructions=[Obstruction(Perm((1, 0)), [(0, 1), (1, 0)])], requirements=[[ Requirement(Perm((0, 1)), [(0, 0), (1, 0)]), Requirement(Perm((0, 1)), [(0, 0), (1, 1)]) ]]) reqins = list(strat.comb_classes for strat in requirement_corroboration(tiling, None)) assert len(reqins) == 2 strat1, strat2 = reqins assert len(strat1) == 2 til1, til2 = strat1 assert til1 == Tiling(obstructions=[ Obstruction(Perm((0, 1)), [(0, 0), (1, 0)]), Obstruction(Perm((1, 0)), [(0, 1), (1, 0)]) ], requirements=[[Requirement(Perm((0, )), [(0, 0)])], [Requirement(Perm((0, )), [(1, 1)])]]) assert til2 == Tiling( obstructions=[], requirements=[[Requirement(Perm((0, 1)), [(0, 0), (1, 0)])]]) tiling = Tiling(obstructions=typical_redundant_obstructions, requirements=typical_redundant_requirements) reqins = list(strat.comb_classes for strat in requirement_corroboration(tiling, None)) assert len(reqins) == sum( len(reqs) for reqs in tiling.requirements if len(reqs) > 1) til1, til2 = reqins[0] assert (set([til1, til2]) == set([ Tiling(requirements=[ [Requirement(Perm((0, 1)), ((2, 0), (3, 1)))], [Requirement(Perm((1, 0)), ((3, 2), (3, 1)))], [Requirement(Perm((0, 1, 2)), ((0, 0), (1, 0), (2, 2)))], [ Requirement(Perm((0, 1, 2)), ((2, 2), (2, 2), (2, 2))), Requirement(Perm((1, 0, 2)), ((0, 0), (0, 0), (0, 0))) ] ], obstructions=typical_redundant_obstructions), Tiling(requirements=[[Requirement(Perm((0, 1)), ((2, 0), (3, 1)))], [Requirement(Perm((1, 0)), ((3, 2), (3, 1)))], [ Requirement(Perm((0, 1, 2)), ((0, 0), (1, 0), (2, 3))), Requirement(Perm((1, 0, 2)), ((0, 0), (1, 0), (2, 2))), Requirement(Perm((1, 0, 2)), ((0, 1), (1, 0), (2, 2))) ], [ Requirement(Perm((0, 1, 2)), ((2, 2), (2, 2), (2, 2))), Requirement(Perm((1, 0, 2)), ((0, 0), (0, 0), (0, 0))) ]], obstructions=( typical_redundant_obstructions + [Obstruction(Perm((0, 1, 2)), ((0, 0), (1, 0), (2, 2)))])) ]))
def row_placements(tiling, row=True, positive=True, regions=False, **kwargs): """Places the points in a row (or col if row=False) in the given direction.""" if row: x = tiling.dimensions[1] y = tiling.dimensions[0] only_cell_in_col = tiling.only_cell_in_col directions = [DIR_NORTH, DIR_SOUTH] else: x = tiling.dimensions[0] y = tiling.dimensions[1] only_cell_in_col = tiling.only_cell_in_row directions = [DIR_EAST, DIR_WEST] rows = range(x) if kwargs.get("index") is not None: rows = [kwargs.get("index")] if kwargs.get("direction") is not None: directions = [kwargs["direction"]] if regions: forward_maps = [] direction = kwargs.get('direction') if direction is not None: if row: if direction == DIR_NORTH: directions = [DIR_NORTH] elif direction == DIR_SOUTH: directions = [DIR_SOUTH] else: raise ValueError("Can't place rows in direction.") else: if direction == DIR_EAST: directions = [DIR_EAST] elif direction == DIR_WEST: directions = [DIR_WEST] else: raise ValueError("Can't place cols in direction.") for i in rows: place = True cells_in_row = [] for j in range(y): cell = (j, i) if row else (i, j) if positive and cell not in tiling.positive_cells: place = False break cells_in_row.append(cell) if place: if (len(cells_in_row) != 1 or not cells_in_row[0] in tiling.point_cells or not only_cell_in_col(cells_in_row[0])): req_list = tuple( Requirement(Perm((0, )), (cell, )) for cell in cells_in_row) if not positive: """Adding the empty row case.""" empty_row_tiling = Tiling( tiling.obstructions + tuple( Obstruction(Perm((0, )), (cell, )) for cell in cells_in_row), tiling.requirements) if regions: forward_maps.append( {c: frozenset([c]) for c in tiling.active_cells}) for direction in directions: if regions: tilings, placed_maps = place_requirement_list( tiling, req_list, direction, regions=regions) if not positive: tilings = [empty_row_tiling] + tilings forward_maps.extend(placed_maps) yield tilings, forward_maps else: tilings = place_requirement_list( tiling, req_list, direction) if not positive: tilings = [empty_row_tiling] + tilings yield Rule(formal_step=("Placing {} {} in direction {}." "".format("row" if row else "col", i, direction, i, direction, int(positive))), comb_classes=tilings, ignore_parent=False, possibly_empty=[True for _ in tilings], inferable=[True for _ in tilings], workable=[True for _ in tilings], constructor='disjoint')
def positive_one_by_one(): return Tiling( obstructions=[Obstruction(Perm((0, 2, 1)), [(0, 0), (0, 0), (0, 0)])], requirements=[[Requirement(Perm((0, )), [(0, 0)])]])
def place_point_of_requirement(tiling, req_index, point_index, force_dir, **kwargs): """ Places the point at point_index in requirement at req_index into tiling. """ if len(tiling.requirements[req_index]) > 1: raise ValueError( "Requirement list at {} contains more than 1 requirement.".format( req_index)) # The requirement requirement = tiling.requirements[req_index][0] # The cell containing the point cell = requirement.pos[point_index] # The rest of the requirements other_reqs = [ tiling.requirements[i] for i in range(len(tiling.requirements)) if i != req_index ] # Placing the forced occurrence of the point in the requirement new_req, forced_obstructions = requirement.place_forced_point( point_index, force_dir) assert len(new_req) == 1 # New indices of the point point_cell = (cell[0] + 1, cell[1] + 1) # The set of new obstructions, consisting of the forced obstructions, other # obstructions where the point placement has been taken into account and # the 12, 21 in the cell. newobs = forced_obstructions + list( chain.from_iterable( ob.place_point(cell, DIR_NONE) for ob in tiling.obstructions)) + [ Obstruction.single_cell(Perm((0, 1)), point_cell), Obstruction.single_cell(Perm((1, 0)), point_cell) ] # The new requirements, consisting of the requirement with the point # placed, other requirements where point placement has been taken into # account and the point requirement in the cell. newreqs = [ list( chain.from_iterable( req.place_point(cell, DIR_NONE) for req in reqs)) for reqs in other_reqs ] + [new_req] + [[Requirement.single_cell(Perm((0, )), point_cell)]] placed_tiling = Tiling(obstructions=newobs, requirements=newreqs) if kwargs.get('regions', False): def cell_map(c): mindex, minval = c maxdex = mindex + 1 maxval = minval + 1 if mindex >= cell[0]: maxdex += 2 if minval >= cell[1]: maxval += 2 if mindex > cell[0]: mindex += 2 if minval > cell[1]: minval += 2 return set([ placed_tiling.forward_map[(x, y)] for x in range(mindex, maxdex) for y in range(minval, maxval) if ((x, y) in placed_tiling.forward_map and placed_tiling. forward_map[(x, y)] in placed_tiling.active_cells) ]) return [placed_tiling], [{c: cell_map(c) for c in tiling.active_cells}] return placed_tiling