From 7426b2bf079b9538f91ce418d463fd6a68d1e1e4 Mon Sep 17 00:00:00 2001 From: Bjarni Jens Kristinsson Date: Wed, 14 Aug 2019 16:47:54 +0000 Subject: [PATCH] Changed 'CombCov.get_subrules()' into a generator, made MeshTiling.get_subrules() a little bit smarted by not returning subrules with empty columns or rows (as they're duplicate of smaller MeshTilings) --- demo/mesh_tiling.py | 23 ++++++++++++++++------- demo/string_set.py | 14 +++++++------- setup.py | 2 +- tests/test_comb_cov.py | 2 +- tests/test_mesh_tiling.py | 7 ++++--- 5 files changed, 29 insertions(+), 19 deletions(-) diff --git a/demo/mesh_tiling.py b/demo/mesh_tiling.py index c7daf05..d58dd43 100644 --- a/demo/mesh_tiling.py +++ b/demo/mesh_tiling.py @@ -282,25 +282,33 @@ def get_subrules(self): "[ERROR] obstruction '{}' is neither a MeshPatt " "or Perm!".format(obstruction)) - subrules = set() + subrules = 1 + yield MeshTiling({}, {}) # always include the empty rule + for (dim_col, dim_row) in itertools.product( range(1, self.columns + self.MAX_COLUMN_DIMENSION), range(1, self.rows + self.MAX_ROW_DIMENSION) ): nr_of_cells = dim_col * dim_row - - for how_many_active_cells in range(self.MAX_ACTIVE_CELLS + 1): + for how_many_active_cells in range(min(dim_col, dim_row), + self.MAX_ACTIVE_CELLS + 1): for active_cells in itertools.product( cell_choices, repeat=how_many_active_cells): for combination in itertools.combinations( range(nr_of_cells), how_many_active_cells): requirements = {} obstructions = {} + active_cols = set() + active_rows = set() for i, cell_index in enumerate(combination): choice = active_cells[i] + c = cell_index % dim_col + active_cols.add(c) + r = cell_index // dim_col + active_rows.add(r) if choice.obstructions is not frozenset(): obstructions[(c, r)] = choice.obstructions @@ -308,15 +316,16 @@ def get_subrules(self): if choice.requirements is not frozenset(): requirements[(c, r)] = choice.requirements - mt = MeshTiling(obstructions, requirements) - subrules.add(mt) + if active_cols == set(range(dim_col)) and \ + active_rows == set(range(dim_row)): + subrules += 1 + yield MeshTiling(obstructions, requirements) logger.info( "Generated {} subrules with up to {} active cells with dimensions " "up to {}x{}".format( - len(subrules), self.MAX_ACTIVE_CELLS, + subrules, self.MAX_ACTIVE_CELLS, self.MAX_COLUMN_DIMENSION, self.MAX_ROW_DIMENSION)) - return list(subrules) def get_dimension(self): return (self.columns, self.rows) diff --git a/demo/string_set.py b/demo/string_set.py index 2d546c7..af339af 100644 --- a/demo/string_set.py +++ b/demo/string_set.py @@ -1,6 +1,5 @@ import itertools import logging -from typing import List from combcov import CombCov, Rule @@ -66,8 +65,8 @@ def get_elmnts(self, of_size): return strings_of_length - def get_subrules(self) -> List[Rule]: - rules = [] + def get_subrules(self): + rules = 0 prefixes = [] for n in range(self.max_prefix_size): prefixes.extend(self.get_elmnts(n + 1)) @@ -77,17 +76,18 @@ def get_subrules(self) -> List[Rule]: empty_string_set = StringSet(alphabet=self.alphabet, avoid=frozenset(self.alphabet), prefix=prefix) - rules.append(empty_string_set) + rules += 1 + yield empty_string_set # Regular rules of the from prefix + non-empty StringSet for prefix in prefixes: for avoiding_subset in self.get_all_avoiding_subsets(): substring_set = StringSet(self.alphabet, avoiding_subset, prefix) - rules.append(substring_set) + rules += 1 + yield substring_set - logger.info("Generated {} subrules".format(len(rules))) - return rules + logger.info("Generated {} subrules".format(rules)) def _key(self): return (self.alphabet, self.avoid, self.prefix) diff --git a/setup.py b/setup.py index 14a88c6..93c56d9 100755 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ def read(fname): setup( name="CombCov", - version="0.3.0", + version="0.3.1", author="Permuta Triangle", author_email="permutatriangle@gmail.com", description="Searching for combinatorial covers.", diff --git a/tests/test_comb_cov.py b/tests/test_comb_cov.py index d9d82c7..7e158e6 100644 --- a/tests/test_comb_cov.py +++ b/tests/test_comb_cov.py @@ -54,7 +54,7 @@ def test_print_solution_rainy(self) -> None: assert len(mocked_print.mock_calls) == 1 def test_too_many_subrules(self) -> None: - subrules = self.string_set.get_subrules() + subrules = list(self.string_set.get_subrules()) too_many = subrules + [self.string_set] + subrules correct_rules = self.comb_cov.rules diff --git a/tests/test_mesh_tiling.py b/tests/test_mesh_tiling.py index 07fb05b..0b18617 100644 --- a/tests/test_mesh_tiling.py +++ b/tests/test_mesh_tiling.py @@ -1,9 +1,10 @@ import unittest +from permuta import Av, MeshPatt, Perm, PermSet + import pytest from combcov import Rule from demo.mesh_tiling import Cell, MeshTiling, MockAvMeshPatt -from permuta import Av, MeshPatt, Perm, PermSet class MockAvMeshPattTests(unittest.TestCase): @@ -177,7 +178,7 @@ def test_subrules(self): self.root_mt.MAX_COLUMN_DIMENSION = 3 self.root_mt.MAX_ROW_DIMENSION = 2 self.root_mt.MAX_ACTIVE_CELLS = 3 - subrules = self.root_mt.get_subrules() + subrules = list(self.root_mt.get_subrules()) assert all(isinstance(rule, Rule) for rule in subrules) assert (self.empty_mt in subrules) assert (self.sub_mt in subrules) @@ -186,7 +187,7 @@ def test_subrules_too_small_dimensions(self): self.root_mt.MAX_COLUMN_DIMENSION = 2 self.root_mt.MAX_ROW_DIMENSION = 2 self.root_mt.MAX_ACTIVE_CELLS = 3 - subrules = self.root_mt.get_subrules() + subrules = list(self.root_mt.get_subrules()) assert all(isinstance(rule, Rule) for rule in subrules) assert (self.empty_mt in subrules) assert (self.sub_mt not in subrules)