def decomposition_function(self, tiling: Tiling) -> Tuple[Tiling]: return (tiling.add_obstructions(self.gps),)
def test_row_col_seperation( not_separable_tilings, seperable_tiling1, seperable_tiling2, seperable_tiling3 ): t = Tiling( obstructions=[ GriddedPerm(Perm((0, 1)), ((0, 0),) * 2), GriddedPerm(Perm((0, 1)), ((1, 0),) * 2), GriddedPerm(Perm((0, 1)), ((0, 0), (1, 0))), ] ) rcs = RowColumnSeparationStrategy()(t) assert rcs.children[0] == Tiling( obstructions=[ GriddedPerm(Perm((0, 1)), ((0, 1),) * 2), GriddedPerm(Perm((0, 1)), ((1, 0),) * 2), ] ) for t in not_separable_tilings: with pytest.raises(StrategyDoesNotApply) as excinfo: RowColumnSeparationStrategy()(t).children assert "row and column separation does not apply" in str(excinfo) t1_sep = Tiling( obstructions=( GriddedPerm(Perm((0,)), ((0, 0),)), GriddedPerm(Perm((0,)), ((0, 1),)), GriddedPerm(Perm((0,)), ((1, 0),)), GriddedPerm(Perm((0,)), ((1, 2),)), GriddedPerm(Perm((0,)), ((2, 1),)), GriddedPerm(Perm((0,)), ((2, 2),)), GriddedPerm(Perm((0, 1, 2)), ((0, 2), (0, 2), (0, 2))), GriddedPerm(Perm((0, 1, 2)), ((1, 1), (1, 1), (1, 1))), GriddedPerm(Perm((0, 1, 2)), ((2, 0), (2, 0), (2, 0))), ), requirements=(), ) t2_sep = Tiling( obstructions=( GriddedPerm(Perm((0,)), ((0, 0),)), GriddedPerm(Perm((0,)), ((0, 1),)), GriddedPerm(Perm((0,)), ((0, 2),)), GriddedPerm(Perm((0,)), ((0, 3),)), GriddedPerm(Perm((0,)), ((1, 0),)), GriddedPerm(Perm((0,)), ((1, 2),)), GriddedPerm(Perm((0,)), ((1, 3),)), GriddedPerm(Perm((0,)), ((1, 4),)), GriddedPerm(Perm((0,)), ((2, 1),)), GriddedPerm(Perm((0,)), ((2, 2),)), GriddedPerm(Perm((0,)), ((2, 4),)), GriddedPerm(Perm((0,)), ((3, 1),)), GriddedPerm(Perm((0,)), ((3, 3),)), GriddedPerm(Perm((0,)), ((3, 4),)), GriddedPerm(Perm((0,)), ((4, 1),)), GriddedPerm(Perm((0,)), ((4, 2),)), GriddedPerm(Perm((0,)), ((4, 3),)), GriddedPerm(Perm((0,)), ((4, 4),)), GriddedPerm(Perm((0, 1)), ((2, 0), (3, 0))), GriddedPerm(Perm((0, 1)), ((3, 0), (4, 0))), GriddedPerm(Perm((0, 1, 2)), ((0, 4), (0, 4), (0, 4))), GriddedPerm(Perm((0, 1, 2)), ((1, 1), (1, 1), (1, 1))), GriddedPerm(Perm((0, 1, 2)), ((2, 0), (2, 0), (2, 0))), GriddedPerm(Perm((0, 1, 2)), ((2, 3), (2, 3), (2, 3))), GriddedPerm(Perm((0, 1, 2)), ((3, 0), (3, 0), (3, 0))), GriddedPerm(Perm((0, 1, 2)), ((3, 2), (3, 2), (3, 2))), GriddedPerm(Perm((0, 1, 2)), ((4, 0), (4, 0), (4, 0))), ), requirements=(), ) t3_sep = Tiling( obstructions=( GriddedPerm(Perm((0,)), ((0, 0),)), GriddedPerm(Perm((0,)), ((1, 0),)), GriddedPerm(Perm((0,)), ((2, 1),)), GriddedPerm(Perm((0,)), ((3, 1),)), GriddedPerm(Perm((0, 1, 2)), ((0, 1), (0, 1), (0, 1))), GriddedPerm(Perm((0, 1, 2)), ((1, 1), (1, 1), (1, 1))), GriddedPerm(Perm((0, 1, 2)), ((2, 0), (2, 0), (2, 0))), GriddedPerm(Perm((0, 1, 2)), ((3, 0), (3, 0), (3, 0))), ), requirements=(), ) assert RowColumnSeparationStrategy()(seperable_tiling1).children[0] == t1_sep assert RowColumnSeparationStrategy()(seperable_tiling2).children[0] == t2_sep assert RowColumnSeparationStrategy()(seperable_tiling3).children[0] == t3_sep
def test_json(all_tilings): for tiling in all_tilings: assert Tiling.from_json(json.dumps(tiling.to_jsonable())) == tiling
for sym in til_syms: sym_database.add(sym(tiling)) return sym_database if __name__ == "__main__": import sys old_db = sys.argv[1] print("Reading database") database = set() f = open(old_db, 'r') for line in f: compression = b64decode(line.encode()) tiling = Tiling.decompress(compression) database.add(tiling) f.close() print("Computing symmetries") database = get_symmetry(database) print("Writing symmetry databse") with_sym = old_db.split('.')[0] + "_symmetry.txt" f = open(with_sym, 'w') for tiling in database: compression = b64encode(tiling.compress()).decode() f.write(compression + "\n") f.close()
def tiling_no_trans_row(): return Tiling(obstructions=[ GriddedPerm((0, 1), [(0, 0), (1, 0)]), GriddedPerm((0, 1), [(1, 0), (2, 0)]), ])
def test_multiple_separation(): """ Test that the row column separation is idempotent. This tilings needs two pass of the algorithm to stabilize. """ t = Tiling( obstructions=( GriddedPerm(Perm((0, )), ((0, 0), )), GriddedPerm(Perm((0, )), ((0, 1), )), GriddedPerm(Perm((0, )), ((0, 3), )), GriddedPerm(Perm((0, )), ((1, 0), )), GriddedPerm(Perm((0, )), ((1, 2), )), GriddedPerm(Perm((0, )), ((1, 3), )), GriddedPerm(Perm((0, )), ((1, 4), )), GriddedPerm(Perm((0, )), ((2, 1), )), GriddedPerm(Perm((0, )), ((2, 3), )), GriddedPerm(Perm((0, )), ((3, 0), )), GriddedPerm(Perm((0, )), ((3, 1), )), GriddedPerm(Perm((0, )), ((3, 2), )), GriddedPerm(Perm((0, )), ((3, 4), )), GriddedPerm(Perm((0, )), ((4, 1), )), GriddedPerm(Perm((0, )), ((4, 3), )), GriddedPerm(Perm((0, 1)), ((0, 2), (0, 2))), GriddedPerm(Perm((0, 1)), ((0, 2), (2, 2))), GriddedPerm(Perm((0, 1)), ((0, 4), (4, 4))), GriddedPerm(Perm((0, 1)), ((1, 1), (1, 1))), GriddedPerm(Perm((0, 1)), ((2, 0), (2, 0))), GriddedPerm(Perm((0, 1)), ((2, 2), (2, 2))), GriddedPerm(Perm((0, 1)), ((2, 2), (2, 4))), GriddedPerm(Perm((0, 1)), ((2, 4), (2, 4))), GriddedPerm(Perm((0, 1)), ((2, 4), (4, 4))), GriddedPerm(Perm((0, 1)), ((3, 3), (3, 3))), GriddedPerm(Perm((0, 1)), ((4, 0), (4, 4))), GriddedPerm(Perm((0, 1)), ((4, 2), (4, 2))), GriddedPerm(Perm((0, 1)), ((4, 2), (4, 4))), GriddedPerm(Perm((1, 0)), ((0, 2), (2, 2))), GriddedPerm(Perm((1, 0)), ((1, 1), (1, 1))), GriddedPerm(Perm((1, 0)), ((2, 2), (2, 0))), GriddedPerm(Perm((1, 0)), ((2, 2), (2, 2))), GriddedPerm(Perm((1, 0)), ((2, 2), (4, 2))), GriddedPerm(Perm((1, 0)), ((2, 4), (2, 2))), GriddedPerm(Perm((1, 0)), ((2, 4), (4, 4))), GriddedPerm(Perm((1, 0)), ((3, 3), (3, 3))), GriddedPerm(Perm((1, 0)), ((4, 4), (4, 2))), GriddedPerm(Perm((0, 1, 2)), ((0, 2), (0, 4), (0, 4))), GriddedPerm(Perm((0, 1, 2)), ((0, 2), (0, 4), (2, 4))), GriddedPerm(Perm((0, 1, 2)), ((0, 4), (0, 4), (0, 4))), GriddedPerm(Perm((0, 1, 2)), ((0, 4), (0, 4), (2, 4))), GriddedPerm(Perm((0, 1, 2)), ((2, 0), (4, 0), (4, 0))), GriddedPerm(Perm((0, 1, 2)), ((2, 0), (4, 0), (4, 2))), GriddedPerm(Perm((0, 1, 2)), ((4, 0), (4, 0), (4, 2))), GriddedPerm(Perm((0, 2, 1)), ((0, 2), (0, 4), (4, 4))), GriddedPerm(Perm((0, 2, 1)), ((2, 0), (2, 2), (4, 0))), GriddedPerm(Perm((0, 2, 1)), ((2, 0), (4, 4), (4, 0))), GriddedPerm(Perm((1, 0, 2)), ((2, 2), (4, 0), (4, 2))), GriddedPerm(Perm((1, 0, 2)), ((4, 4), (4, 4), (4, 4))), GriddedPerm(Perm((1, 2, 0)), ((4, 4), (4, 4), (4, 4))), GriddedPerm(Perm((2, 0, 1)), ((4, 4), (4, 4), (4, 4))), GriddedPerm(Perm((0, 2, 1, 3)), ((4, 0), (4, 0), (4, 0), (4, 0))), GriddedPerm(Perm((0, 2, 3, 1)), ((4, 0), (4, 0), (4, 0), (4, 0))), GriddedPerm(Perm((0, 3, 1, 2)), ((4, 0), (4, 0), (4, 0), (4, 0))), GriddedPerm(Perm((0, 3, 1, 2)), ((4, 0), (4, 2), (4, 0), (4, 0))), GriddedPerm(Perm((1, 2, 0, 3)), ((4, 0), (4, 0), (4, 0), (4, 0))), GriddedPerm(Perm((2, 0, 1, 3)), ((2, 0), (4, 0), (4, 0), (4, 0))), GriddedPerm(Perm((2, 0, 1, 3)), ((4, 0), (4, 0), (4, 0), (4, 0))), ), requirements=( (GriddedPerm(Perm((0, )), ((1, 1), )), ), (GriddedPerm(Perm((0, )), ((2, 2), )), ), (GriddedPerm(Perm((0, )), ((3, 3), )), ), ), ) rcs = RowColSeparation(t) seprated_tiling = rcs.separated_tiling() expected_tiling = Tiling( obstructions=( GriddedPerm(Perm((0, )), ((0, 0), )), GriddedPerm(Perm((0, )), ((0, 1), )), GriddedPerm(Perm((0, )), ((0, 2), )), GriddedPerm(Perm((0, )), ((0, 3), )), GriddedPerm(Perm((0, )), ((0, 4), )), GriddedPerm(Perm((0, )), ((0, 5), )), GriddedPerm(Perm((0, )), ((0, 6), )), GriddedPerm(Perm((0, )), ((1, 0), )), GriddedPerm(Perm((0, )), ((1, 1), )), GriddedPerm(Perm((0, )), ((1, 3), )), GriddedPerm(Perm((0, )), ((1, 4), )), GriddedPerm(Perm((0, )), ((1, 5), )), GriddedPerm(Perm((0, )), ((1, 6), )), GriddedPerm(Perm((0, )), ((1, 7), )), GriddedPerm(Perm((0, )), ((2, 0), )), GriddedPerm(Perm((0, )), ((2, 2), )), GriddedPerm(Perm((0, )), ((2, 3), )), GriddedPerm(Perm((0, )), ((2, 4), )), GriddedPerm(Perm((0, )), ((2, 5), )), GriddedPerm(Perm((0, )), ((2, 6), )), GriddedPerm(Perm((0, )), ((2, 7), )), GriddedPerm(Perm((0, )), ((3, 0), )), GriddedPerm(Perm((0, )), ((3, 1), )), GriddedPerm(Perm((0, )), ((3, 2), )), GriddedPerm(Perm((0, )), ((3, 4), )), GriddedPerm(Perm((0, )), ((3, 5), )), GriddedPerm(Perm((0, )), ((3, 6), )), GriddedPerm(Perm((0, )), ((3, 7), )), GriddedPerm(Perm((0, )), ((4, 0), )), GriddedPerm(Perm((0, )), ((4, 1), )), GriddedPerm(Perm((0, )), ((4, 2), )), GriddedPerm(Perm((0, )), ((4, 3), )), GriddedPerm(Perm((0, )), ((4, 4), )), GriddedPerm(Perm((0, )), ((4, 6), )), GriddedPerm(Perm((0, )), ((4, 7), )), GriddedPerm(Perm((0, )), ((5, 0), )), GriddedPerm(Perm((0, )), ((5, 1), )), GriddedPerm(Perm((0, )), ((5, 2), )), GriddedPerm(Perm((0, )), ((5, 3), )), GriddedPerm(Perm((0, )), ((5, 4), )), GriddedPerm(Perm((0, )), ((5, 5), )), GriddedPerm(Perm((0, )), ((5, 7), )), GriddedPerm(Perm((0, )), ((6, 0), )), GriddedPerm(Perm((0, )), ((6, 1), )), GriddedPerm(Perm((0, )), ((6, 2), )), GriddedPerm(Perm((0, )), ((6, 3), )), GriddedPerm(Perm((0, )), ((6, 5), )), GriddedPerm(Perm((0, )), ((6, 6), )), GriddedPerm(Perm((0, )), ((6, 7), )), GriddedPerm(Perm((0, )), ((7, 1), )), GriddedPerm(Perm((0, )), ((7, 2), )), GriddedPerm(Perm((0, )), ((7, 3), )), GriddedPerm(Perm((0, )), ((7, 4), )), GriddedPerm(Perm((0, )), ((7, 5), )), GriddedPerm(Perm((0, )), ((7, 6), )), GriddedPerm(Perm((0, )), ((7, 7), )), GriddedPerm(Perm((0, 1)), ((1, 2), (1, 2))), GriddedPerm(Perm((0, 1)), ((2, 1), (2, 1))), GriddedPerm(Perm((0, 1)), ((3, 3), (3, 3))), GriddedPerm(Perm((0, 1)), ((4, 5), (4, 5))), GriddedPerm(Perm((0, 1)), ((6, 4), (6, 4))), GriddedPerm(Perm((1, 0)), ((1, 2), (1, 2))), GriddedPerm(Perm((1, 0)), ((3, 3), (3, 3))), GriddedPerm(Perm((1, 0)), ((4, 5), (4, 5))), GriddedPerm(Perm((1, 0)), ((5, 6), (6, 4))), GriddedPerm(Perm((0, 1, 2)), ((0, 7), (0, 7), (0, 7))), GriddedPerm(Perm((1, 0, 2)), ((5, 6), (5, 6), (5, 6))), GriddedPerm(Perm((1, 2, 0)), ((5, 6), (5, 6), (5, 6))), GriddedPerm(Perm((2, 0, 1)), ((5, 6), (5, 6), (5, 6))), GriddedPerm(Perm((0, 2, 1, 3)), ((7, 0), (7, 0), (7, 0), (7, 0))), GriddedPerm(Perm((0, 2, 3, 1)), ((7, 0), (7, 0), (7, 0), (7, 0))), GriddedPerm(Perm((0, 3, 1, 2)), ((7, 0), (7, 0), (7, 0), (7, 0))), GriddedPerm(Perm((1, 2, 0, 3)), ((7, 0), (7, 0), (7, 0), (7, 0))), GriddedPerm(Perm((2, 0, 1, 3)), ((7, 0), (7, 0), (7, 0), (7, 0))), ), requirements=( (GriddedPerm(Perm((0, )), ((1, 2), )), ), (GriddedPerm(Perm((0, )), ((3, 3), )), ), (GriddedPerm(Perm((0, )), ((4, 5), )), ), ), ) assert seprated_tiling == expected_tiling
def test_pre_check_diff_basis(self): t = Tiling(obstructions=[ GriddedPerm((0, 1, 2), ((0, 0), ) * 3), GriddedPerm((0, 1), ((0, 1), ) * 2), ]) assert not ComponentFusion(t, row_idx=0)._pre_check()
def test_algorithms_sliding(): for tc, (t1, t2) in enumerate(t_cases): l1 = list(generate_all_slided_tilings(t1)) if t2 is None: assert l1 == [] continue l2 = list(generate_all_slided_tilings(t2)) assert len(l1) == 1 assert l1[0] == t2 if tc > 0: assert len(l2) == 1 assert l2[0] == t1 else: assert len(l2) == 2 assert set(l2) == { t1, Tiling( obstructions=( GriddedPerm((0, 1), ((0, 0), (0, 0))), GriddedPerm((0, 1, 2), ((0, 0), (1, 0), (1, 0))), GriddedPerm((0, 1, 2), ((0, 0), (1, 0), (2, 0))), GriddedPerm((0, 1, 2), ((0, 0), (2, 0), (2, 0))), GriddedPerm((0, 1, 2), ((1, 0), (1, 0), (1, 0))), GriddedPerm((0, 1, 2), ((1, 0), (1, 0), (2, 0))), GriddedPerm((0, 1, 2), ((1, 0), (2, 0), (2, 0))), GriddedPerm((0, 1, 2), ((2, 0), (2, 0), (2, 0))), ), requirements=(), assumptions=(), ), } lis = [ Tiling( obstructions=( GriddedPerm((0, 1), ((1, 0), (1, 0))), GriddedPerm((0, 1), ((3, 0), (3, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (0, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (1, 0))), GriddedPerm((0, 1, 2), ((2, 0), (2, 0), (2, 0))), GriddedPerm((0, 1, 2), ((2, 0), (2, 0), (3, 0))), ), requirements=(), assumptions=(), ), Tiling( obstructions=( GriddedPerm((0, 1), ((0, 0), (0, 0))), GriddedPerm((0, 1), ((2, 0), (2, 0))), GriddedPerm((0, 1, 2), ((0, 0), (1, 0), (1, 0))), GriddedPerm((0, 1, 2), ((1, 0), (1, 0), (1, 0))), GriddedPerm((0, 1, 2), ((2, 0), (3, 0), (3, 0))), GriddedPerm((0, 1, 2), ((3, 0), (3, 0), (3, 0))), ), requirements=(), assumptions=(), ), Tiling( obstructions=( GriddedPerm((0, 1), ((1, 0), (1, 0))), GriddedPerm((0, 1), ((2, 0), (2, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (0, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (1, 0))), GriddedPerm((0, 1, 2), ((2, 0), (3, 0), (3, 0))), GriddedPerm((0, 1, 2), ((3, 0), (3, 0), (3, 0))), ), requirements=(), assumptions=(), ), Tiling( obstructions=( GriddedPerm((0, 1), ((0, 0), (0, 0))), GriddedPerm((0, 1), ((3, 0), (3, 0))), GriddedPerm((0, 1, 2), ((0, 0), (1, 0), (1, 0))), GriddedPerm((0, 1, 2), ((1, 0), (1, 0), (1, 0))), GriddedPerm((0, 1, 2), ((2, 0), (2, 0), (2, 0))), GriddedPerm((0, 1, 2), ((2, 0), (2, 0), (3, 0))), ), requirements=(), assumptions=(), ), ] s = {lis[0]} while True: len_before = len(s) ss = set() for tt in s: ss.update(generate_all_slided_tilings(tt)) s.update(ss) if len(s) == len_before: break assert s == set(lis)
def test_slide(): tcases = [ ( Tiling( obstructions=( GriddedPerm((0, 1), ((2, 0), (2, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (0, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (1, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (2, 0))), GriddedPerm((0, 1, 2), ((0, 0), (1, 0), (1, 0))), GriddedPerm((0, 1, 2), ((0, 0), (1, 0), (2, 0))), GriddedPerm((0, 1, 2), ((1, 0), (1, 0), (1, 0))), GriddedPerm((0, 1, 2), ((1, 0), (1, 0), (2, 0))), ), requirements=(), assumptions=(), ), Tiling( obstructions=( GriddedPerm((0, 1), ((1, 0), (1, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (0, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (1, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (2, 0))), GriddedPerm((0, 1, 2), ((0, 0), (1, 0), (2, 0))), GriddedPerm((0, 1, 2), ((0, 0), (2, 0), (2, 0))), GriddedPerm((0, 1, 2), ((1, 0), (2, 0), (2, 0))), GriddedPerm((0, 1, 2), ((2, 0), (2, 0), (2, 0))), ), requirements=(), assumptions=(), ), (1, 2), 7, ), ( Tiling( obstructions=( GriddedPerm((0, 1, 2, 3, 4), ((1, 0),) * 5), GriddedPerm((0, 1), ((3, 0), (3, 0))), GriddedPerm((0, 1, 2, 3, 4), ((1, 0),) * 4 + ((3, 0),)), GriddedPerm((4, 3, 2, 1), ((0, 0),) * 4), GriddedPerm((2, 3, 1, 0), ((2, 0),) * 4), GriddedPerm((0, 2, 1), ((4, 0),) * 3), GriddedPerm((1, 2, 0), ((1, 0), (2, 0), (4, 0))), GriddedPerm((2, 1, 0), ((2, 0), (3, 0), (4, 0))), GriddedPerm( (4, 1, 2, 3, 0), ((0, 0), (0, 0), (1, 0), (1, 0), (4, 0)) ), GriddedPerm( (4, 1, 2, 3, 0), ((0, 0), (0, 0), (1, 0), (3, 0), (4, 0)) ), ) ), Tiling( obstructions=( GriddedPerm((0, 1, 2, 3, 4), ((3, 0),) * 5), GriddedPerm((0, 1), ((1, 0), (1, 0))), GriddedPerm((0, 1, 2, 3, 4), ((1, 0),) + ((3, 0),) * 4), GriddedPerm((4, 3, 2, 1), ((0, 0),) * 4), GriddedPerm((2, 3, 1, 0), ((2, 0),) * 4), GriddedPerm((0, 2, 1), ((4, 0),) * 3), GriddedPerm((1, 2, 0), ((1, 0), (2, 0), (4, 0))), GriddedPerm((2, 1, 0), ((2, 0), (3, 0), (4, 0))), GriddedPerm( (4, 1, 2, 3, 0), ((0, 0), (0, 0), (3, 0), (3, 0), (4, 0)) ), GriddedPerm( (4, 1, 2, 3, 0), ((0, 0), (0, 0), (1, 0), (3, 0), (4, 0)) ), ) ), (1, 3), 6, ), ( Tiling( obstructions=( GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (0, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (1, 0))), GriddedPerm((0, 1), ((1, 0), (1, 0))), GriddedPerm((1, 2, 3, 0), ((0, 0), (0, 0), (2, 0), (2, 0))), GriddedPerm((1, 2, 3, 0), ((0, 0), (1, 0), (2, 0), (2, 0))), ), requirements=(((GriddedPerm((0, 2, 1), ((2, 0), (2, 0), (2, 0))),),)), ), Tiling( obstructions=( GriddedPerm((0, 1, 2), ((1, 0), (1, 0), (1, 0))), GriddedPerm((0, 1, 2), ((0, 0), (1, 0), (1, 0))), GriddedPerm((0, 1), ((0, 0), (0, 0))), GriddedPerm((1, 2, 3, 0), ((1, 0), (1, 0), (2, 0), (2, 0))), GriddedPerm((1, 2, 3, 0), ((0, 0), (1, 0), (2, 0), (2, 0))), ), requirements=(((GriddedPerm((0, 2, 1), ((2, 0), (2, 0), (2, 0))),),)), ), (), # default 7, ), ] for t1, t2, cols, up_to in tcases: visited = set() expected = set(t2.gridded_perms(up_to)) for gp in t1.gridded_perms(up_to): sl = Sliding.slide_gp(gp, *cols) assert sl not in visited visited.add(sl) assert sl in expected expected.remove(sl) assert len(expected) == 0 visited = set() expected = set(t1.gridded_perms(up_to)) for gp in t2.gridded_perms(up_to): sl = Sliding.slide_gp_inverse(gp, *cols) assert sl not in visited visited.add(sl) assert sl in expected expected.remove(sl) assert len(expected) == 0
def rules_to_check(): return [ RequirementInsertionStrategy( gps=frozenset({GriddedPerm(Perm((0, )), ((0, 0), ))}), ignore_parent=True)(Tiling( obstructions=( GriddedPerm(Perm((0, 1)), ((0, 0), (0, 0))), GriddedPerm(Perm((0, 1)), ((0, 0), (1, 0))), GriddedPerm(Perm((0, 1)), ((1, 0), (1, 0))), GriddedPerm(Perm((1, 0)), ((0, 0), (1, 0))), GriddedPerm(Perm((1, 0)), ((1, 0), (1, 0))), ), requirements=((GriddedPerm(Perm((0, )), ((1, 0), )), ), ), assumptions=(TrackingAssumption( (GriddedPerm(Perm((0, )), ((0, 0), )), )), ), )), RequirementInsertionStrategy( gps=frozenset({GriddedPerm(Perm((0, )), ((2, 0), ))}), ignore_parent=True)(Tiling( obstructions=( GriddedPerm(Perm((0, 1)), ((1, 0), (1, 0))), GriddedPerm(Perm((0, 1)), ((2, 0), (2, 0))), GriddedPerm(Perm((0, 1)), ((2, 0), (3, 0))), GriddedPerm(Perm((0, 1)), ((3, 0), (3, 0))), GriddedPerm(Perm((1, 0)), ((0, 0), (2, 0))), GriddedPerm(Perm((1, 0)), ((0, 0), (3, 0))), GriddedPerm(Perm((1, 0)), ((2, 0), (2, 0))), GriddedPerm(Perm((1, 0)), ((2, 0), (3, 0))), GriddedPerm(Perm((1, 0)), ((3, 0), (3, 0))), GriddedPerm(Perm((0, 1, 2)), ((0, 0), (0, 0), (0, 0))), GriddedPerm(Perm((0, 1, 2)), ((0, 0), (0, 0), (1, 0))), GriddedPerm(Perm((0, 1, 2)), ((0, 0), (0, 0), (2, 0))), GriddedPerm(Perm((0, 1, 2)), ((0, 0), (0, 0), (3, 0))), GriddedPerm(Perm((0, 1, 2)), ((0, 0), (1, 0), (2, 0))), GriddedPerm(Perm((0, 1, 2)), ((0, 0), (1, 0), (3, 0))), GriddedPerm(Perm((0, 2, 1)), ((0, 0), (0, 0), (1, 0))), GriddedPerm(Perm((1, 0, 2)), ((0, 0), (0, 0), (0, 0))), ), requirements=( (GriddedPerm(Perm((0, )), ((0, 0), )), ), (GriddedPerm(Perm((0, )), ((3, 0), )), ), ), assumptions=(TrackingAssumption( (GriddedPerm(Perm((0, )), ((3, 0), )), )), ), )).to_equivalence_rule().to_reverse_rule(), FusionStrategy(col_idx=1, tracked=True)(Tiling( obstructions=( GriddedPerm(Perm((0, )), ((0, 0), )), GriddedPerm(Perm((0, )), ((1, 0), )), GriddedPerm(Perm((0, )), ((1, 1), )), GriddedPerm(Perm((0, )), ((2, 0), )), GriddedPerm(Perm((0, )), ((2, 1), )), GriddedPerm(Perm((0, )), ((3, 1), )), GriddedPerm(Perm((0, )), ((3, 2), )), GriddedPerm(Perm((0, 1)), ((1, 2), (1, 2))), GriddedPerm(Perm((0, 1)), ((1, 2), (2, 2))), GriddedPerm(Perm((0, 1)), ((2, 2), (2, 2))), GriddedPerm(Perm((0, 1)), ((3, 0), (3, 0))), GriddedPerm(Perm((0, 1, 2)), ((0, 1), (0, 1), (0, 2))), GriddedPerm(Perm((0, 1, 2)), ((0, 1), (0, 2), (0, 2))), GriddedPerm(Perm((0, 1, 2)), ((0, 1), (0, 2), (1, 2))), GriddedPerm(Perm((0, 1, 2)), ((0, 1), (0, 2), (2, 2))), GriddedPerm(Perm((0, 2, 1)), ((0, 1), (0, 1), (0, 1))), GriddedPerm(Perm((0, 2, 1)), ((0, 1), (1, 2), (1, 2))), GriddedPerm(Perm((0, 2, 1)), ((0, 1), (1, 2), (2, 2))), GriddedPerm(Perm((0, 2, 1)), ((0, 1), (2, 2), (2, 2))), GriddedPerm(Perm((1, 0, 2)), ((0, 2), (0, 1), (1, 2))), GriddedPerm(Perm((1, 0, 2)), ((0, 2), (0, 1), (2, 2))), GriddedPerm(Perm((2, 0, 1)), ((0, 1), (0, 1), (0, 1))), GriddedPerm(Perm((0, 1, 3, 2)), ((0, 2), (0, 2), (0, 2), (0, 2))), GriddedPerm(Perm((0, 1, 3, 2)), ((0, 2), (0, 2), (0, 2), (1, 2))), GriddedPerm(Perm((0, 1, 3, 2)), ((0, 2), (0, 2), (0, 2), (2, 2))), GriddedPerm(Perm((0, 1, 3, 2)), ((0, 2), (0, 2), (1, 2), (1, 2))), GriddedPerm(Perm((0, 1, 3, 2)), ((0, 2), (0, 2), (1, 2), (2, 2))), GriddedPerm(Perm((0, 1, 3, 2)), ((0, 2), (0, 2), (2, 2), (2, 2))), GriddedPerm(Perm((0, 2, 1, 3)), ((0, 2), (0, 2), (0, 2), (0, 2))), GriddedPerm(Perm((0, 2, 1, 3)), ((0, 2), (0, 2), (0, 2), (1, 2))), GriddedPerm(Perm((0, 2, 1, 3)), ((0, 2), (0, 2), (0, 2), (2, 2))), GriddedPerm(Perm((0, 2, 3, 1)), ((0, 2), (0, 2), (0, 2), (0, 2))), GriddedPerm(Perm((0, 2, 3, 1)), ((0, 2), (0, 2), (0, 2), (1, 2))), GriddedPerm(Perm((0, 2, 3, 1)), ((0, 2), (0, 2), (0, 2), (2, 2))), GriddedPerm(Perm((0, 2, 3, 1)), ((0, 2), (0, 2), (1, 2), (1, 2))), GriddedPerm(Perm((0, 2, 3, 1)), ((0, 2), (0, 2), (1, 2), (2, 2))), GriddedPerm(Perm((0, 2, 3, 1)), ((0, 2), (0, 2), (2, 2), (2, 2))), GriddedPerm(Perm((2, 0, 1, 3)), ((0, 2), (0, 2), (0, 2), (0, 2))), GriddedPerm(Perm((2, 0, 1, 3)), ((0, 2), (0, 2), (0, 2), (1, 2))), GriddedPerm(Perm((2, 0, 1, 3)), ((0, 2), (0, 2), (0, 2), (2, 2))), ), requirements=( (GriddedPerm(Perm((0, )), ((1, 2), )), ), (GriddedPerm(Perm((0, )), ((2, 2), )), ), (GriddedPerm(Perm((0, )), ((3, 0), )), ), ), assumptions=(TrackingAssumption(( GriddedPerm(Perm((0, )), ((2, 2), )), GriddedPerm(Perm((0, )), ((3, 0), )), )), ), )), RequirementInsertionStrategy( gps=frozenset({GriddedPerm(Perm((0, )), ((0, 2), ))}), ignore_parent=True)(Tiling( obstructions=( GriddedPerm(Perm((0, 1)), ((0, 1), (0, 1))), GriddedPerm(Perm((0, 1)), ((0, 1), (0, 2))), GriddedPerm(Perm((0, 1)), ((0, 2), (0, 2))), GriddedPerm(Perm((1, 0)), ((0, 1), (0, 0))), GriddedPerm(Perm((1, 0)), ((0, 1), (0, 1))), GriddedPerm(Perm((1, 0)), ((0, 2), (0, 0))), GriddedPerm(Perm((1, 0)), ((0, 2), (0, 1))), GriddedPerm(Perm((1, 0)), ((0, 2), (0, 2))), GriddedPerm(Perm((0, 1, 2)), ((0, 0), (0, 0), (0, 0))), GriddedPerm(Perm((0, 1, 2)), ((0, 0), (0, 0), (0, 1))), GriddedPerm(Perm((0, 1, 2)), ((0, 0), (0, 0), (0, 2))), GriddedPerm(Perm((0, 2, 1)), ((0, 0), (0, 0), (0, 0))), GriddedPerm(Perm((1, 2, 0)), ((0, 0), (0, 0), (0, 0))), ), requirements=((GriddedPerm(Perm((0, )), ((0, 1), )), ), ), assumptions=(TrackingAssumption( (GriddedPerm(Perm((0, )), ((0, 2), )), )), ), )).to_equivalence_rule().to_reverse_rule(), ]
def generate_all_slided_tilings(tiling): sliding = Sliding(tiling) for av_12, av_123 in sliding.slidable_pairs(): yield sliding.slide_column(av_12, av_123) t_cases = [ ( Tiling( obstructions=( GriddedPerm((0, 1), ((2, 0), (2, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (0, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (1, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (2, 0))), GriddedPerm((0, 1, 2), ((0, 0), (1, 0), (1, 0))), GriddedPerm((0, 1, 2), ((0, 0), (1, 0), (2, 0))), GriddedPerm((0, 1, 2), ((1, 0), (1, 0), (1, 0))), GriddedPerm((0, 1, 2), ((1, 0), (1, 0), (2, 0))), ), requirements=(), assumptions=(), ), Tiling( obstructions=( GriddedPerm((0, 1), ((1, 0), (1, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (0, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (1, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (2, 0))), GriddedPerm((0, 1, 2), ((0, 0), (1, 0), (2, 0))), GriddedPerm((0, 1, 2), ((0, 0), (2, 0), (2, 0))), GriddedPerm((0, 1, 2), ((1, 0), (2, 0), (2, 0))),
def __call__(self, comb_class: Tiling) -> Iterator[Rule]: for assumption in comb_class.assumptions: without = comb_class.remove_assumption(assumption) strategy = AddAssumptionsStrategy((assumption, )) yield strategy(without)
def decomposition_function(self, comb_class: Tiling) -> Tuple[Tiling]: if any(assumption in comb_class.assumptions for assumption in self.assumptions): raise StrategyDoesNotApply( "The assumption is already on the tiling.") return (comb_class.add_assumptions(self.assumptions), )
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
def row_and_column_separation(tiling, **kwargs): # First we calculate the set of inequalities for all the rows and columns row_ineqs, col_ineqs = row_and_column_inequalities_of_tiling(tiling) separated_rows, separated_cols = [], [] # When creating the new tiling, we need to keep track of the shifted cell # we add, in case a cell appears on a separated row and column inferred = False row_map = {} shift = 0 for row in range(tiling.dimensions[1]): inequalities = row_ineqs[row] if inequalities: # Calculate the separation, described in the function row_separations = sorted(separations(inequalities), key=lambda x: (len(x), x)) separation = row_separations[-1] inferred = True if len(row_separations) != 1 else inferred else: separation = [[c for c in tiling.cells_in_row(row)]] for index, cells in enumerate(separation): for cell in cells: row_map[cell] = cell[1] + shift + index shift += len(separation) - 1 if len(separation) > 1: separated_rows.append(row) col_map = {} shift = 0 for col in range(tiling.dimensions[0]): # Calculate the separation, described in the function inequalities = col_ineqs[col] if inequalities: # sort them by length, i.e. number of parts in the separation column_separations = sorted(separations(inequalities), key=lambda x: (len(x), x)) separation = column_separations[-1] inferred = True if len(column_separations) != 1 else inferred else: separation = [[c for c in tiling.cells_in_col(col)]] for index, cells in enumerate(separation): for cell in cells: col_map[cell] = cell[0] + shift + index shift += len(separation) - 1 if len(separation) > 1: separated_cols.append(col) if inferred: def cell_map(c): return (col_map[c], row_map[c]) obstructions = [ob.minimize(cell_map) for ob in tiling.obstructions if not ob.is_point_perm() and not ob.minimize(cell_map).contradictory()] requirements = [[req.minimize(cell_map) for req in reqs] for reqs in tiling.requirements] separated_tiling = Tiling(obstructions=obstructions, requirements=requirements) # we only return it if it is different formal_step = "Separated rows [{}] and columns [{}]".format( ", ".join(map(str, separated_rows)), ", ".join(map(str, separated_cols))) if kwargs.get('regions', False): fwd_map = separated_tiling.forward_map return ([separated_tiling], [{c: set([fwd_map[cell_map(c)]]) for c in tiling.active_cells if (cell_map(c) in fwd_map and fwd_map[cell_map(c)] in separated_tiling.active_cells)}]) return InferralRule(formal_step, separated_tiling)
def reverse_fusion_rules(): t = Tiling( obstructions=( GriddedPerm((0, 1, 2), ((1, 0), (1, 0), (1, 0))), GriddedPerm((0, 1, 2), ((1, 0), (1, 0), (2, 0))), GriddedPerm((0, 1, 2), ((1, 0), (1, 0), (3, 0))), GriddedPerm((0, 1, 2), ((1, 0), (1, 0), (4, 0))), GriddedPerm((0, 1, 2), ((1, 0), (2, 0), (2, 0))), GriddedPerm((0, 1, 2), ((1, 0), (2, 0), (3, 0))), GriddedPerm((0, 1, 2), ((1, 0), (2, 0), (4, 0))), GriddedPerm((0, 1, 2), ((1, 0), (3, 0), (3, 0))), GriddedPerm((0, 1, 2), ((1, 0), (3, 0), (4, 0))), GriddedPerm((0, 1, 2), ((1, 0), (4, 0), (4, 0))), GriddedPerm((0, 1, 2), ((2, 0), (2, 0), (2, 0))), GriddedPerm((0, 1, 2), ((2, 0), (2, 0), (3, 0))), GriddedPerm((0, 1, 2), ((2, 0), (2, 0), (4, 0))), GriddedPerm((0, 1, 2), ((2, 0), (3, 0), (3, 0))), GriddedPerm((0, 1, 2), ((2, 0), (3, 0), (4, 0))), GriddedPerm((0, 1, 2), ((2, 0), (4, 0), (4, 0))), GriddedPerm((0, 1, 2), ((3, 0), (3, 0), (3, 0))), GriddedPerm((0, 1, 2), ((3, 0), (3, 0), (4, 0))), GriddedPerm((0, 1, 2), ((3, 0), (4, 0), (4, 0))), GriddedPerm((0, 1, 2), ((4, 0), (4, 0), (4, 0))), GriddedPerm((0, 1, 2, 3), ((0, 0), (0, 0), (0, 0), (0, 0))), GriddedPerm((0, 1, 2, 3), ((0, 0), (0, 0), (0, 0), (1, 0))), GriddedPerm((0, 1, 2, 3), ((0, 0), (0, 0), (0, 0), (2, 0))), GriddedPerm((0, 1, 2, 3), ((0, 0), (0, 0), (0, 0), (3, 0))), GriddedPerm((0, 1, 2, 3), ((0, 0), (0, 0), (0, 0), (4, 0))), GriddedPerm((0, 1, 2, 3), ((0, 0), (0, 0), (1, 0), (1, 0))), GriddedPerm((0, 1, 2, 3), ((0, 0), (0, 0), (1, 0), (2, 0))), GriddedPerm((0, 1, 2, 3), ((0, 0), (0, 0), (1, 0), (3, 0))), GriddedPerm((0, 1, 2, 3), ((0, 0), (0, 0), (1, 0), (4, 0))), GriddedPerm((0, 1, 2, 3), ((0, 0), (0, 0), (2, 0), (2, 0))), GriddedPerm((0, 1, 2, 3), ((0, 0), (0, 0), (2, 0), (3, 0))), GriddedPerm((0, 1, 2, 3), ((0, 0), (0, 0), (2, 0), (4, 0))), GriddedPerm((0, 1, 2, 3), ((0, 0), (0, 0), (3, 0), (3, 0))), GriddedPerm((0, 1, 2, 3), ((0, 0), (0, 0), (3, 0), (4, 0))), GriddedPerm((0, 1, 2, 3), ((0, 0), (0, 0), (4, 0), (4, 0))), ), requirements=(), assumptions=(), ) left_overlap = TrackingAssumption.from_cells([(0, 0), (1, 0)]) left = TrackingAssumption.from_cells([(1, 0)]) right = TrackingAssumption.from_cells([(2, 0)]) right_overlap = TrackingAssumption.from_cells([(2, 0), (3, 0)]) # Only track left of the fuse region t1 = t.add_assumptions([left_overlap, right_overlap, left]) yield FusionStrategy(col_idx=1, tracked=True)(t1).to_reverse_rule(0) # Only track right of the fuse region t2 = t.add_assumptions([left_overlap, right_overlap, right]) yield FusionStrategy(col_idx=1, tracked=True)(t2).to_reverse_rule(0) # Only track the bottom of the fuse region yield FusionStrategy(row_idx=1, tracked=True)(t1.rotate270()).to_reverse_rule(0) # Only track the top of the fuse region yield FusionStrategy(row_idx=1, tracked=True)(t2.rotate270()).to_reverse_rule(0) # Track both side of the fuse region t3 = t.add_assumptions([left_overlap, right_overlap, left, right]) yield FusionStrategy(col_idx=1, tracked=True)(t3).to_reverse_rule(0) yield FusionStrategy(row_idx=1, tracked=True)(t3.rotate270()).to_reverse_rule(0)
def test_separated_tiling( not_separable_tilings, separable_tiling1, separable_tiling2, separable_tiling3, separable_tiling4, ): t = Tiling(obstructions=[ GriddedPerm(Perm((0, 1)), ((0, 0), ) * 2), GriddedPerm(Perm((0, 1)), ((1, 0), ) * 2), GriddedPerm(Perm((0, 1)), ((0, 0), (1, 0))), ]) rcs = RowColSeparation(t) print(t) print(rcs.separated_tiling()) assert rcs.separated_tiling() == Tiling(obstructions=[ GriddedPerm(Perm((0, 1)), ((0, 1), ) * 2), GriddedPerm(Perm((0, 1)), ((1, 0), ) * 2), ]) for t in not_separable_tilings: rcs = RowColSeparation(t) assert t == rcs.separated_tiling() t1_sep = Tiling( obstructions=( GriddedPerm(Perm((0, )), ((0, 0), )), GriddedPerm(Perm((0, )), ((0, 1), )), GriddedPerm(Perm((0, )), ((1, 0), )), GriddedPerm(Perm((0, )), ((1, 2), )), GriddedPerm(Perm((0, )), ((2, 1), )), GriddedPerm(Perm((0, )), ((2, 2), )), GriddedPerm(Perm((0, 1, 2)), ((0, 2), (0, 2), (0, 2))), GriddedPerm(Perm((0, 1, 2)), ((1, 1), (1, 1), (1, 1))), GriddedPerm(Perm((0, 1, 2)), ((2, 0), (2, 0), (2, 0))), ), requirements=(), ) t2_sep = Tiling( obstructions=( GriddedPerm(Perm((0, )), ((0, 0), )), GriddedPerm(Perm((0, )), ((0, 1), )), GriddedPerm(Perm((0, )), ((0, 2), )), GriddedPerm(Perm((0, )), ((0, 3), )), GriddedPerm(Perm((0, )), ((1, 0), )), GriddedPerm(Perm((0, )), ((1, 2), )), GriddedPerm(Perm((0, )), ((1, 3), )), GriddedPerm(Perm((0, )), ((1, 4), )), GriddedPerm(Perm((0, )), ((2, 1), )), GriddedPerm(Perm((0, )), ((2, 2), )), GriddedPerm(Perm((0, )), ((2, 4), )), GriddedPerm(Perm((0, )), ((3, 1), )), GriddedPerm(Perm((0, )), ((3, 3), )), GriddedPerm(Perm((0, )), ((3, 4), )), GriddedPerm(Perm((0, )), ((4, 1), )), GriddedPerm(Perm((0, )), ((4, 2), )), GriddedPerm(Perm((0, )), ((4, 3), )), GriddedPerm(Perm((0, )), ((4, 4), )), GriddedPerm(Perm((0, 1)), ((2, 0), (3, 0))), GriddedPerm(Perm((0, 1)), ((3, 0), (4, 0))), GriddedPerm(Perm((0, 1, 2)), ((0, 4), (0, 4), (0, 4))), GriddedPerm(Perm((0, 1, 2)), ((1, 1), (1, 1), (1, 1))), GriddedPerm(Perm((0, 1, 2)), ((2, 0), (2, 0), (2, 0))), GriddedPerm(Perm((0, 1, 2)), ((2, 3), (2, 3), (2, 3))), GriddedPerm(Perm((0, 1, 2)), ((3, 0), (3, 0), (3, 0))), GriddedPerm(Perm((0, 1, 2)), ((3, 2), (3, 2), (3, 2))), GriddedPerm(Perm((0, 1, 2)), ((4, 0), (4, 0), (4, 0))), ), requirements=(), ) t3_sep = Tiling( obstructions=( GriddedPerm(Perm((0, )), ((0, 0), )), GriddedPerm(Perm((0, )), ((1, 0), )), GriddedPerm(Perm((0, )), ((2, 1), )), GriddedPerm(Perm((0, )), ((3, 1), )), GriddedPerm(Perm((0, 1, 2)), ((0, 1), (0, 1), (0, 1))), GriddedPerm(Perm((0, 1, 2)), ((1, 1), (1, 1), (1, 1))), GriddedPerm(Perm((0, 1, 2)), ((2, 0), (2, 0), (2, 0))), GriddedPerm(Perm((0, 1, 2)), ((3, 0), (3, 0), (3, 0))), ), requirements=(), ) t4_sep = Tiling( obstructions=( GriddedPerm(Perm((0, 1)), ((0, 2), ) * 2), GriddedPerm(Perm((0, 1)), ((1, 1), ) * 2), GriddedPerm(Perm((0, 1)), ((2, 0), ) * 2), GriddedPerm(Perm((0, 1)), ((3, 0), ) * 2), GriddedPerm(Perm((1, 0)), ((0, 2), (2, 0))), ), requirements=((GriddedPerm(Perm((0, )), ((1, 1), )), ), ), ) assert RowColSeparation(separable_tiling1).separated_tiling() == t1_sep assert RowColSeparation(separable_tiling2).separated_tiling() == t2_sep assert RowColSeparation(separable_tiling3).separated_tiling() == t3_sep assert RowColSeparation(separable_tiling4).separated_tiling() == t4_sep # Test for the empty tiling empty_tiling = Tiling(obstructions=[GriddedPerm(Perm((0, )), ((0, 0), ))]) assert RowColSeparation(empty_tiling).separated_tiling() == empty_tiling
def factor(tiling, **kwargs): """ The factor strategy that decomposes a tiling into its connected factors. The factors are the connected components of the graph of the tiling, where vertices are the cells. Two vertices are connected if there exists a obstruction or requirement occupying both cells. Two cells are also connected if they share the same row or column unless the interleaving or point_interleaving keyword arguments are set to True. When point interleavings are allowed, two cells in the same row or column are not connected. When general interleavings are allowed, two cells in the same row or column are not connected. """ interleaving = kwargs.get("interleaving", False) point_interleaving = kwargs.get("point_interleaving", False) n, m = tiling.dimensions def cell_to_int(cell): return cell[0] * m + cell[1] def int_to_cell(i): return (i // m, i % m) cells = list(tiling.active_cells) uf = UnionFind(n * m) # Unite by obstructions for ob in tiling.obstructions: for i in range(len(ob.pos)): for j in range(i+1, len(ob.pos)): uf.unite(cell_to_int(ob.pos[i]), cell_to_int(ob.pos[j])) # Unite by requirements for req_list in tiling.requirements: req_cells = list(union_reduce(req.pos for req in req_list)) for i in range(len(req_cells)): for j in range(i + 1, len(req_cells)): uf.unite(cell_to_int(req_cells[i]), cell_to_int(req_cells[j])) # If interleaving not allowed, unite by row/col if not interleaving: for i in range(len(cells)): for j in range(i+1, len(cells)): c1, c2 = cells[i], cells[j] if (point_interleaving and (c1 in tiling.point_cells or c2 in tiling.point_cells)): continue if c1[0] == c2[0] or c1[1] == c2[1]: uf.unite(cell_to_int(c1), cell_to_int(c2)) # Collect the connected components of the cells all_components = {} for cell in cells: i = uf.find(cell_to_int(cell)) if i in all_components: all_components[i].append(cell) else: all_components[i] = [cell] component_cells = list(set(cells) for cells in all_components.values()) # If the tiling is a single connected component if len(component_cells) <= 1: return # Collect the factors of the tiling factors = [] strategy = [] # the vanilla factors for cell_component in component_cells: obstructions = [ob for ob in tiling.obstructions if ob.pos[0] in cell_component] requirements = [req for req in tiling.requirements if req[0].pos[0] in cell_component] if obstructions or requirements: factors.append((obstructions, requirements)) strategy.append(Tiling(obstructions=obstructions, requirements=requirements, minimize=False)) if kwargs.get("workable", True): work = [True for _ in strategy] else: work = [False for _ in strategy] yield Rule("The factors of the tiling.", strategy, inferable=[False for _ in strategy], workable=work, possibly_empty=[False for _ in strategy], ignore_parent=kwargs.get("workable", True), constructor='cartesian') if kwargs.get("unions", False): for partition in partition_list(factors): strategy = [] for part in partition: obstructions, requirements = zip(*part) strategy.append(Tiling(obstructions=chain(*obstructions), requirements=chain(*requirements), minimize=False)) yield Rule("The union of factors of the tiling", strategy, possibly_empty=[False for _ in strategy], inferable=[False for _ in strategy], workable=[False for _ in strategy], constructor='cartesian')
def test_backmap2(): t = Tiling( obstructions=( GriddedPerm(Perm((0, 1)), ((0, 0), (1, 2))), GriddedPerm(Perm((0, 1)), ((0, 0), (2, 2))), GriddedPerm(Perm((0, 1)), ((0, 2), (0, 2))), GriddedPerm(Perm((0, 1)), ((1, 0), (2, 0))), GriddedPerm(Perm((0, 1)), ((1, 1), (1, 1))), GriddedPerm(Perm((0, 1)), ((2, 0), (2, 0))), GriddedPerm(Perm((1, 0)), ((0, 0), (0, 0))), GriddedPerm(Perm((1, 0)), ((0, 0), (1, 0))), GriddedPerm(Perm((1, 0)), ((0, 0), (2, 0))), GriddedPerm(Perm((1, 0)), ((0, 2), (1, 2))), GriddedPerm(Perm((1, 0)), ((1, 0), (2, 0))), GriddedPerm(Perm((1, 0)), ((1, 1), (1, 0))), GriddedPerm(Perm((1, 0)), ((1, 2), (1, 0))), GriddedPerm(Perm((1, 0)), ((1, 2), (1, 2))), GriddedPerm(Perm((1, 0)), ((1, 2), (2, 2))), GriddedPerm(Perm((1, 0)), ((2, 2), (2, 2))), GriddedPerm(Perm((0, 1, 2)), ((1, 0), (1, 1), (1, 2))), GriddedPerm(Perm((0, 1, 2)), ((1, 0), (1, 1), (2, 2))), GriddedPerm(Perm((0, 1, 2)), ((1, 0), (1, 2), (1, 2))), GriddedPerm(Perm((0, 1, 2)), ((1, 0), (1, 2), (2, 2))), GriddedPerm(Perm((0, 2, 1)), ((0, 0), (1, 0), (1, 0))), GriddedPerm(Perm((0, 2, 1)), ((1, 0), (1, 0), (1, 0))), GriddedPerm(Perm((1, 0, 2)), ((1, 0), (1, 0), (1, 1))), GriddedPerm(Perm((1, 0, 2)), ((1, 0), (1, 0), (1, 2))), GriddedPerm(Perm((1, 2, 0)), ((1, 0), (1, 0), (1, 0))), GriddedPerm(Perm((2, 0, 1)), ((1, 0), (1, 0), (1, 0))), GriddedPerm(Perm((2, 1, 0)), ((0, 2), (2, 2), (2, 0))), ), requirements=((GriddedPerm(Perm((0, )), ((1, 0), )), ), ), ) cellmap1 = { (0, 0): (0, 0), (0, 2): (0, 3), (1, 0): (1, 1), (1, 1): (2, 2), (1, 2): (2, 3), (2, 2): (3, 3), } cellmap2 = { (0, 0): (0, 0), (0, 3): (0, 3), (1, 1): (1, 1), (2, 2): (3, 2), (2, 3): (2, 4), (3, 3): (4, 3), } final_cell_map = { (0, 0): (0, 0), (0, 2): (0, 3), (1, 0): (1, 1), (1, 1): (3, 2), (1, 2): (2, 4), (2, 2): (4, 3), } print(t) rcs1 = _RowColSeparationSingleApplication(t) t1 = rcs1.separated_tiling() print(t1) assert rcs1.get_cell_map() == cellmap1 rcs2 = _RowColSeparationSingleApplication(t1) t2 = rcs2.separated_tiling() print(t2) assert rcs2.get_cell_map() == cellmap2 rcs = RowColSeparation(t) assert rcs.separated_tiling() == t2 assert RowColSeparation(t).get_cell_map() == final_cell_map
from tilings.strategies.sliding import SlidingFactory tiling = Tiling( obstructions=( GriddedPerm((0, 1), ((2, 0), (2, 0))), GriddedPerm((0, 1, 2), ((1, 0), (1, 0), (1, 0))), GriddedPerm((0, 1, 2), ((1, 0), (1, 0), (2, 0))), GriddedPerm((0, 1, 2), ((1, 0), (1, 0), (3, 0))), GriddedPerm((0, 1, 2), ((1, 0), (2, 0), (3, 0))), GriddedPerm((0, 1, 2), ((1, 0), (3, 0), (3, 0))), GriddedPerm((0, 1, 2), ((2, 0), (3, 0), (3, 0))), GriddedPerm((0, 1, 2), ((3, 0), (3, 0), (3, 0))), GriddedPerm((3, 0, 1, 2), ((0, 0), (0, 0), (0, 0), (0, 0))), GriddedPerm((3, 0, 1, 2), ((0, 0), (0, 0), (0, 0), (1, 0))), GriddedPerm((3, 0, 1, 2), ((0, 0), (0, 0), (0, 0), (2, 0))), GriddedPerm((3, 0, 1, 2), ((0, 0), (0, 0), (0, 0), (3, 0))), GriddedPerm((3, 0, 1, 2), ((0, 0), (0, 0), (1, 0), (1, 0))), GriddedPerm((3, 0, 1, 2), ((0, 0), (0, 0), (1, 0), (2, 0))), GriddedPerm((3, 0, 1, 2), ((0, 0), (0, 0), (1, 0), (3, 0))), GriddedPerm((3, 0, 1, 2), ((0, 0), (0, 0), (2, 0), (3, 0))), GriddedPerm((3, 0, 1, 2), ((0, 0), (0, 0), (3, 0), (3, 0))), ), requirements=(), assumptions=( TrackingAssumption((GriddedPerm( (0, ), ((2, 0), )), GriddedPerm((0, ), ((3, 0), )))), TrackingAssumption((GriddedPerm((0, ), ((3, 0), )), )), ), )
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 test_repr_tiling(client): tiling = Tiling.from_string("123_4132") key = base64.b64encode(tiling.to_bytes()).decode("utf-8") res = post(client, _REPR_PATH, key) assert_code_and_mimetype(res) assert repr(tiling) == res.json
def test_obstruction_transitivity( self, simple_trans_row, simple_trans_col, simple_trans_row_len2, simple_trans_row_len3, no_trans_row, tiling_no_trans_row, no_trans_col, tiling_no_trans_col, with_empty_inf_cell, ): assert simple_trans_row.obstruction_transitivity() == Tiling( obstructions=[ GriddedPerm((0, 1), [(0, 0), (1, 0)]), GriddedPerm((0, 1), [(1, 0), (2, 0)]), GriddedPerm((0, 1), [(0, 0), (2, 0)]), ], requirements=[[GriddedPerm((0, ), [(1, 0)])]], ) assert simple_trans_col.obstruction_transitivity() == Tiling( obstructions=[ GriddedPerm((0, 1), [(0, 0), (0, 1)]), GriddedPerm((0, 1), [(0, 1), (0, 2)]), GriddedPerm((0, 1), [(0, 0), (0, 2)]), ], requirements=[[GriddedPerm((0, ), [(0, 1)])]], ) assert simple_trans_row_len2.obstruction_transitivity() == Tiling( obstructions=[ GriddedPerm((0, 1), [(0, 0), (1, 0)]), GriddedPerm((0, 1), [(0, 0), (2, 0)]), GriddedPerm((0, 1), [(0, 0), (3, 0)]), GriddedPerm((0, 1), [(1, 0), (2, 0)]), GriddedPerm((0, 1), [(1, 0), (3, 0)]), GriddedPerm((0, 1), [(2, 0), (3, 0)]), ], requirements=[ [GriddedPerm((0, ), [(1, 0)])], [GriddedPerm((0, ), [(2, 0)])], ], ) assert simple_trans_row_len3.obstruction_transitivity() == Tiling( obstructions=[ GriddedPerm((0, 1), [(0, 0), (1, 0)]), GriddedPerm((0, 1), [(0, 0), (2, 0)]), GriddedPerm((0, 1), [(0, 0), (3, 0)]), GriddedPerm((0, 1), [(0, 0), (4, 0)]), GriddedPerm((0, 1), [(1, 0), (2, 0)]), GriddedPerm((0, 1), [(1, 0), (3, 0)]), GriddedPerm((0, 1), [(1, 0), (4, 0)]), GriddedPerm((0, 1), [(2, 0), (3, 0)]), GriddedPerm((0, 1), [(2, 0), (4, 0)]), GriddedPerm((0, 1), [(3, 0), (4, 0)]), ], requirements=[ [GriddedPerm((0, ), [(1, 0)])], [GriddedPerm((0, ), [(2, 0)])], [GriddedPerm((0, ), [(3, 0)])], ], ) assert no_trans_row.obstruction_transitivity() == tiling_no_trans_row assert no_trans_col.obstruction_transitivity() == tiling_no_trans_col t = Tiling( obstructions=[ GriddedPerm((0, 1), ((2, 0), (2, 0))), GriddedPerm((1, 0), ((1, 0), (1, 0))), GriddedPerm((1, 0), ((1, 0), (2, 0))), GriddedPerm((1, 0), ((2, 0), (2, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (0, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (1, 0))), GriddedPerm((0, 1, 2), ((0, 0), (0, 0), (2, 0))), GriddedPerm((0, 1, 2), ((0, 0), (1, 0), (1, 0))), GriddedPerm((0, 1, 2), ((0, 0), (1, 0), (2, 0))), GriddedPerm((0, 1, 2), ((1, 0), (1, 0), (1, 0))), GriddedPerm((0, 1, 2), ((1, 0), (1, 0), (2, 0))), GriddedPerm((3, 2, 1, 0), ((0, 0), (0, 0), (0, 0), (0, 0))), GriddedPerm((3, 2, 1, 0), ((0, 0), (0, 0), (0, 0), (1, 0))), GriddedPerm((3, 2, 1, 0), ((0, 0), (0, 0), (0, 0), (2, 0))), ], requirements=[[GriddedPerm((0, 1), ((1, 0), (2, 0)))]], ) assert with_empty_inf_cell.obstruction_transitivity() == t
def decomposition_function(self, tiling: Tiling) -> Tuple[Tiling, ...]: return tuple(tiling.sub_tiling(cells) for cells in self.partition)
def tiling_no_trans_col(): return Tiling(obstructions=[ GriddedPerm((0, 1), [(0, 0), (0, 1)]), GriddedPerm((0, 1), [(0, 1), (0, 2)]), ])
def __call__(self, comb_class: Tiling) -> Iterator[Rule[Tiling, GriddedPerm]]: for req_list in comb_class.requirements: remove_req = comb_class.remove_requirement(req_list) yield RequirementInsertionStrategy(req_list)(remove_req)
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 tplaced(): t = Tiling.from_string("132") return t.place_point_in_cell((0, 0), 1)