def __init__( self, interleaving: Optional[str] = None, unions: bool = False, ignore_parent: bool = True, workable: bool = True, tracked: bool = False, ) -> None: try: self.factor_algo, self.factor_class = self.FACTOR_ALGO_AND_CLASS[ interleaving ] except KeyError: raise InvalidOperationError( "Invalid interleaving option. Must be in {}, used {}".format( FactorFactory.FACTOR_ALGO_AND_CLASS.keys(), interleaving ) ) self.unions = unions self.ignore_parent = ignore_parent self.workable = workable self.tracked = tracked and self.factor_class in ( FactorWithInterleavingStrategy, FactorWithMonotoneInterleaving, )
def get_genf(self, **kwargs) -> Expr: """ Returns the generating function for the tiling. Raises an InvalidOperationError if the tiling is not verified. """ if not self.verified(): raise InvalidOperationError("The tiling is not verified")
def get_genf(self, **kwargs) -> Expr: # pylint: disable=too-many-return-statements if not self.verified(): raise InvalidOperationError("The tiling is not verified") funcs: Optional[Dict["Tiling", Function]] = kwargs.get("funcs") if funcs is None: funcs = {} if self.tiling.requirements: reqs = self.tiling.requirements[0] avoided = self.tiling.__class__( self.tiling.obstructions + reqs, self.tiling.requirements[1:], self.tiling.assumptions, ) without = self.tiling.__class__( self.tiling.obstructions, self.tiling.requirements[1:], self.tiling.assumptions, ) avgf = LocalEnumeration(avoided).get_genf(funcs=funcs) wogf = LocalEnumeration(without).get_genf(funcs=funcs) return wogf - avgf if self.tiling in funcs: return funcs[self.tiling] # also return something entirely different if the root class/not verified if self.tiling.dimensions == (1, 1): if self.tiling.is_epsilon(): return 1 if self.tiling == self.tiling.__class__.from_string("01_10"): return 1 + x if self.tiling in ( self.tiling.__class__.from_string("01"), self.tiling.__class__.from_string("10"), ): return 1 / (1 - x) if self.tiling in ( self.tiling.__class__.from_string("123"), self.tiling.__class__.from_string("321"), ): return sympify("-1/2*(sqrt(-4*x + 1) - 1)/x") # TODO: should this create a spec as in the strategy? raise NotImplementedError( f"Look up the combopal database for:\n{self.tiling}" ) gf = None if MonotoneTreeEnumeration(self.tiling).verified(): gf = MonotoneTreeEnumeration(self.tiling).get_genf() if DatabaseEnumeration(self.tiling).verified(): gf = DatabaseEnumeration(self.tiling).get_genf() if gf is not None: funcs[self.tiling] = gf return gf # TODO: should this create a spec as in the strategy? raise NotImplementedError( f"Not sure how to enumerate the tiling:\n{self.tiling}" )
def reverse(self) -> "RowColMap": """ Return the reverse map if possible. Otherwise raise an InvalidOperationError. """ row_map = {v: k for k, v in self._row_map.items()} col_map = {v: k for k, v in self._col_map.items()} if len(row_map) != len(self._row_map) or len(col_map) != len( self._col_map): raise InvalidOperationError("The map is not reversible.") return RowColMap(row_map=row_map, col_map=col_map, is_identity=self._is_identity)
def get_genf(self, **kwargs) -> Expr: # pylint: disable=too-many-locals if not self.verified(): raise InvalidOperationError("The tiling is not verified") if self.tiling.extra_parameters: raise NotImplementedError( "Not implemented monotone verified with extra parameters." ) try: start = next( c for c in self.tiling.active_cells if not self.tiling.is_monotone_cell(c) ) except StopIteration: start = next(iter(self.tiling.active_cells)) start_basis = self.tiling.cell_basis()[start][0] start_reqs = [[p] for p in self.tiling.cell_basis()[start][1]] start_tiling = self.tiling.from_perms( obstructions=start_basis, requirements=start_reqs ) start_gf = start_tiling.get_genf() F = start_gf.subs({x: x * self._cell_variable(start)}) visited = set([start]) for cell in self._cell_tree_traversal(start): interleaving_cells = self._visted_cells_aligned(cell, visited) substitutions = { scv: scv * self._tracking_var for scv in map(self._cell_variable, interleaving_cells) } F_tracked = F.subs(substitutions) minlen, maxlen = self._cell_num_point(cell) if maxlen is None: F = self._interleave_any_length(F_tracked, cell) if minlen > 0: F -= self._interleave_fixed_lengths(F_tracked, cell, 0, minlen - 1) else: F = self._interleave_fixed_lengths(F_tracked, cell, minlen, maxlen) visited.add(cell) F = simplify(F.subs({v: 1 for v in F.free_symbols if v != x})) # A simple test to warn us if the code is wrong if __debug__: lhs = taylor_expand(F, n=6) rhs = [len(list(self.tiling.objects_of_size(i))) for i in range(7)] assert lhs == rhs, f"Bad genf\n{lhs}\n{rhs}" return F
def get_genf(self, **kwargs) -> Expr: if not self.verified(): raise InvalidOperationError("The tiling is not verified") return sympify(self._get_tiling_entry()["genf"])