-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
608 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
from .core_strategies import core_strategies | ||
from .insertion_encodable import InsertionEncodingStrategy | ||
|
||
fast_enumeration_strategies = [InsertionEncodingStrategy] + core_strategies | ||
|
||
long_enumeration_strategies = [] | ||
|
||
all_enumeration_strategies = (fast_enumeration_strategies + | ||
long_enumeration_strategies) | ||
|
||
|
||
def find_strategies(basis, long_runnning=True): | ||
""" | ||
Test all enumeration strategies against the basis and return a list of | ||
potentially useful strategies. If `long_runnning` is False, test only the | ||
strategies that can be tested quickly. | ||
""" | ||
if long_runnning: | ||
strategies = all_enumeration_strategies | ||
else: | ||
strategies = fast_enumeration_strategies | ||
working_strategies = [] | ||
for Strategy in strategies: | ||
strategy_object = Strategy(basis) | ||
if strategy_object.applies(): | ||
working_strategies.append(strategy_object) | ||
return working_strategies |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
from abc import ABC, abstractmethod | ||
|
||
from permuta.permutils.symmetry import all_symmetry_sets | ||
|
||
|
||
class EnumerationStrategy(ABC): | ||
"""Abstract class for a strategy to enumerate a permutation classes""" | ||
|
||
def __init__(self, basis): | ||
ABC.__init__(self) | ||
self._basis = frozenset(basis) | ||
|
||
@property | ||
def basis(self): | ||
return self._basis | ||
|
||
@classmethod | ||
def reference(cls): | ||
"""A reference for the strategy.""" | ||
raise NotImplementedError | ||
|
||
@abstractmethod | ||
def applies(self): | ||
""" | ||
Return True if the strategy can be used for the basis | ||
""" | ||
pass | ||
|
||
|
||
class EnumerationStrategyWithSymmetry(EnumerationStrategy): | ||
""" | ||
Abstract class for a strategy to enumerate a permutation classes. | ||
Each symmetry of the inputed basis is tested against the strategy. | ||
""" | ||
|
||
def __init__(self, basis): | ||
super().__init__(basis) | ||
self._apply_basis = None | ||
|
||
@property | ||
def basis(self): | ||
""" | ||
The symmetry of the inputed basis to which the strategy applies to. | ||
""" | ||
if self._basis is None: | ||
self.applies() | ||
return self._basis | ||
|
||
def applies(self): | ||
""" | ||
Check if the strategy applies to any symmetry. | ||
""" | ||
for b in map(frozenset, all_symmetry_sets(self._basis)): | ||
if self._applies_to_symmetry(b): | ||
self._apply_basis = b | ||
return True | ||
return False | ||
|
||
@abstractmethod | ||
def _applies_to_symmetry(self, b): | ||
""" | ||
Check if the strategy applies to this particular symmetry. | ||
""" | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
from abc import abstractmethod, abstractproperty, abstractstaticmethod | ||
|
||
from permuta import Av, MeshPatt, Perm | ||
from permuta.descriptors import Basis | ||
from permuta.enumeration_strategies.abstract_strategy import \ | ||
EnumerationStrategyWithSymmetry | ||
|
||
R_U = Perm((1, 2, 0, 3)) | ||
C_U = Perm((2, 0, 1, 3)) | ||
R_D = Perm((1, 3, 0, 2)) | ||
C_D = Perm((2, 0, 3, 1)) | ||
|
||
|
||
# Abstract Core Strategy | ||
|
||
class CoreStrategy(EnumerationStrategyWithSymmetry): | ||
""" | ||
Abstract class for a core related strategy. | ||
""" | ||
@abstractproperty | ||
def patterns_needed(): | ||
""" | ||
Return the set of patterns that are needed for the strategy to be | ||
useful. | ||
""" | ||
pass | ||
|
||
@abstractstaticmethod | ||
def is_valid_extension(patt): | ||
""" | ||
Determine if the pattern satisfies the condition for strategy to apply. | ||
""" | ||
pass | ||
|
||
def _applies_to_symmetry(self, b): | ||
""" | ||
Check if the core strategy applies to the basis or any of its symmetry. | ||
INPUT: | ||
- `b`: a set of permutations. | ||
""" | ||
assert isinstance(b, frozenset) | ||
perm_class = Av(b) | ||
patterns_are_contained = all(p not in perm_class for p in | ||
self.patterns_needed) | ||
extensions_are_valid = all(self.is_valid_extension(patt) for patt in | ||
b.difference(self.patterns_needed)) | ||
return patterns_are_contained and extensions_are_valid | ||
|
||
@classmethod | ||
def reference(cls): | ||
return ('Enumeration of Permutation Classes and Weighted Labelled ' | ||
'Independent Sets: Corollary {}').format(cls.corr_number) | ||
|
||
@property | ||
@staticmethod | ||
def corr_number(): | ||
"""The number of the corollary in the that gives this strategy.""" | ||
raise NotImplementedError | ||
|
||
# Tool functions | ||
|
||
|
||
def fstrip(perm): | ||
""" | ||
Remove the leading 1 if the permutation is the sum of 1 + p. | ||
""" | ||
if perm[0] == 0: | ||
return Perm.from_iterable(perm[1:]) | ||
else: | ||
return perm | ||
|
||
|
||
def bstrip(perm): | ||
""" | ||
Remove the trailing n if the permutation is the sum of p + 1. | ||
""" | ||
if perm[-1] == len(perm)-1: | ||
return Perm.from_iterable(perm[:-1]) | ||
else: | ||
return perm | ||
|
||
|
||
def zero_plus_skewind(perm): | ||
""" | ||
Return True if the permutation is of the form 1 + p where p is a | ||
skew-indecomposable permutations | ||
""" | ||
return perm[0] == 0 and not fstrip(perm).skew_decomposable() | ||
|
||
|
||
def zero_plus_sumind(perm): | ||
""" | ||
Return True if the permutation is of the form 1 + p where p is a | ||
sum-indecomposable permutations | ||
""" | ||
return perm[0] == 0 and not fstrip(perm).sum_decomposable() | ||
|
||
|
||
def zero_plus_perm(perm): | ||
""" | ||
Return True if the permutation starts with a zero. | ||
""" | ||
return perm[0] == 0 | ||
|
||
|
||
def last_sum_component(p): | ||
""" | ||
Return the last sum component of a permutation. | ||
""" | ||
n = len(p) | ||
i = 1 | ||
comp = set([p[n-i]]) | ||
while comp != set(range(n-i, n)): | ||
i += 1 | ||
comp.add(p[n-i]) | ||
return Perm.to_standard(p[n-i:n]) | ||
|
||
|
||
def last_skew_component(p): | ||
""" | ||
Return the last skew component of a permutation. | ||
""" | ||
n = len(p) | ||
i = 1 | ||
comp = set([p[n-i]]) | ||
while comp != set(range(0, i)): | ||
i += 1 | ||
comp.add(p[n-i]) | ||
return Perm.to_standard(p[n-i:n]) | ||
|
||
|
||
# Core Strategies | ||
|
||
class RuCuCoreStrategy(CoreStrategy): | ||
""" | ||
This strategies uses independent set of the up-core graph to enumerate a | ||
class as inflation of an independent set. | ||
""" | ||
patterns_needed = frozenset([R_U, C_U]) | ||
is_valid_extension = staticmethod(zero_plus_skewind) | ||
corr_number = '4.3' | ||
|
||
|
||
class RdCdCoreStrategy(CoreStrategy): | ||
""" | ||
This strategies uses independent set of the down-core graph to enumerate a | ||
class as inflation of an independent set. | ||
""" | ||
patterns_needed = frozenset([R_D, C_D]) | ||
is_valid_extension = staticmethod(zero_plus_sumind) | ||
corr_number = '4.6' | ||
|
||
|
||
class RuCuRdCdCoreStrategy(CoreStrategy): | ||
patterns_needed = frozenset([R_D, C_D, R_U, C_U]) | ||
is_valid_extension = staticmethod(zero_plus_perm) | ||
corr_number = '5.4' | ||
|
||
|
||
class RuCuCdCoreStrategy(CoreStrategy): | ||
patterns_needed = frozenset([R_U, C_U, C_D]) | ||
is_valid_extension = staticmethod(zero_plus_skewind) | ||
corr_number = '6.3' | ||
|
||
|
||
class RdCdCuCoreStrategy(CoreStrategy): | ||
patterns_needed = frozenset([R_D, C_D, C_U]) | ||
corr_number = '7.4' | ||
|
||
@staticmethod | ||
def is_valid_extension(patt): | ||
return zero_plus_sumind(bstrip(patt)) | ||
|
||
|
||
class RdCuCoreStrategy(CoreStrategy): | ||
patterns_needed = frozenset([R_D, C_U]) | ||
corr_number = '8.3' | ||
|
||
@staticmethod | ||
def is_valid_extension(patt): | ||
return (zero_plus_skewind(patt) and | ||
zero_plus_sumind(bstrip(patt))) | ||
|
||
|
||
class Rd2134CoreStrategy(CoreStrategy): | ||
patterns_needed = frozenset([R_D, Perm((1, 0, 2, 3))]) | ||
corr_number = '9.5' | ||
|
||
@staticmethod | ||
def is_valid_extension(patt): | ||
mp = MeshPatt(Perm((1, 0)), [(0, 1), (0, 2), (1, 0), (1, 1), (1, 2), | ||
(2, 1), (2, 2)]) | ||
last_comp = last_sum_component(fstrip(patt)) | ||
return (patt[0] == 0 and fstrip(patt).avoids(mp) and | ||
(last_comp not in Av([Perm((0, 1))]) or len(last_comp) == 1)) | ||
|
||
|
||
class Ru2143CoreStrategy(CoreStrategy): | ||
patterns_needed = frozenset([R_U, Perm((1, 0, 3, 2))]) | ||
corr_number = '10.5' | ||
|
||
@staticmethod | ||
def is_valid_extension(patt): | ||
mp = MeshPatt(Perm((0, 1)), [(0, 1), (0, 2), (1, 0), (1, 1), (1, 2), | ||
(2, 1), (2, 2)]) | ||
patt = fstrip(patt) | ||
return (patt.avoids(mp) and | ||
last_skew_component(patt) not in Av([Perm((1, 0))])) | ||
|
||
|
||
core_strategies = [ | ||
RuCuCoreStrategy, | ||
RdCdCoreStrategy, | ||
RuCuRdCdCoreStrategy, | ||
RuCuCdCoreStrategy, | ||
RdCdCuCoreStrategy, | ||
RdCuCoreStrategy, | ||
Rd2134CoreStrategy, | ||
Ru2143CoreStrategy, | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
""" | ||
Enumeration strategies related to the insertion encoding. | ||
""" | ||
|
||
from permuta.enumeration_strategies.abstract_strategy import \ | ||
EnumerationStrategy | ||
from permuta.permutils.insertion_encodable import is_insertion_encodable | ||
|
||
|
||
class InsertionEncodingStrategy(EnumerationStrategy): | ||
|
||
def applies(self): | ||
return is_insertion_encodable(self.basis) |
Oops, something went wrong.