def __init__(self, basis, quiet=False): self._basis = basis self._max_basis_length = max([len(b) for b in self._basis]) self._class = AvClass(basis, 1) self._configs_checked = set() self._automaton_ready = False self._root = Configuration((0, ), self._basis, 'm') self._perm = Configuration((1, ), self._basis, 'f') self._tree = {self._root: self._root.children()} self._automaton = {self._root: list(self._root.children())} self._has_inssch = False self._reductions = {} self._automaton_ready = False if self.has_inssch(): self._has_inssch = True else: syms = PermSet(self._basis).all_syms() for S in syms: self._basis = S if self.has_inssch(): self._has_inssch = True if not quiet: print( 'Av({}) does not have an insertion scheme, but its symmetry Av({}) does.' .format(basis, S)) break if not self._has_inssch: if not quiet: print( 'Neither this class nor its symmetries has an insertion scheme.' )
def __init__(self, basis, quiet=False): self._basis = basis self._max_basis_length = max([len(b) for b in self._basis]) self._class = AvClass(basis, 1) self._configs_checked = set() self._automaton_ready = False self._root = Configuration((0,), self._basis, 'm') self._perm = Configuration((1,), self._basis, 'f') self._tree = {self._root: self._root.children()} self._automaton = {self._root: list(self._root.children())} self._has_inssch = False self._reductions = {} self._automaton_ready = False if self.has_inssch(): self._has_inssch = True else: syms = PermSet(self._basis).all_syms() for S in syms: self._basis = S if self.has_inssch(): self._has_inssch = True if not quiet: print('Av({}) does not have an insertion scheme, but its symmetry Av({}) does.'.format(basis, S)) break if not self._has_inssch: if not quiet: print('Neither this class nor its symmetries has an insertion scheme.')
class InsertionScheme(): _tree = {} _basis = [] _max_basis_length = 0 _automaton = {} _root = None _configs_checked = set() _automaton_ready = False _has_inssch = False _reductions = {} _class = [] def __init__(self, basis, quiet=False): self._basis = basis self._max_basis_length = max([len(b) for b in self._basis]) self._class = AvClass(basis, 1) self._configs_checked = set() self._automaton_ready = False self._root = Configuration((0,), self._basis, 'm') self._perm = Configuration((1,), self._basis, 'f') self._tree = {self._root: self._root.children()} self._automaton = {self._root: list(self._root.children())} self._has_inssch = False self._reductions = {} self._automaton_ready = False if self.has_inssch(): self._has_inssch = True else: syms = PermSet(self._basis).all_syms() for S in syms: self._basis = S if self.has_inssch(): self._has_inssch = True if not quiet: print('Av({}) does not have an insertion scheme, but its symmetry Av({}) does.'.format(basis, S)) break if not self._has_inssch: if not quiet: print('Neither this class nor its symmetries has an insertion scheme.') def has_inssch(self): types = [ PermSet([Permutation(321), Permutation(2143), Permutation(2413)]), PermSet([Permutation(123), Permutation(3142), Permutation(3412)]), PermSet([Permutation(132), Permutation(312)]), PermSet([Permutation(213), Permutation(231)]) ] return all([any([all([b.avoids(p) for p in B]) for b in self._basis]) for B in types]) def follow_reduce(self,config): while config in self._reductions.keys(): config = self._reductions[config] return config def build_rules(self, verbose=True, make_class=False, class_bound=100): configs_to_check = [Configuration((0,), self._basis)] while len(configs_to_check) > 0: if verbose: # print '\tstates to check:',len(configs_to_check),', nodes in tree:',len(self._tree.keys()),', states:', len(self._automaton) s_to_print = '\tstates to check: {}, nodes in tree: {}, states: {}'.format( len(configs_to_check), len(self._tree.keys()), len(self._automaton)) print(s_to_print) configs_to_check.sort(key=len) current_config = configs_to_check[0] if verbose: print('\nChecking: ',current_config) self._configs_checked.add(current_config) if current_config.is_permutation(): if verbose: print(current_config,' is not reducible') configs_to_check.remove(current_config) continue length_to_check = self._max_basis_length + current_config.num_slots() - 2 reducible = False order_to_check = sorted(range(len(current_config)), key=lambda i : current_config[i], reverse=True) checked_already = list() for i in order_to_check: if current_config[i] == 0 or (i > 0 and i < len(current_config)-1 and current_config[i-1] == 0 and current_config[i+1] == 0): continue second_config = Configuration(current_config[:i]+current_config[i+1:], self._basis, '?') if second_config in checked_already: continue checked_already.append(second_config) if verbose: # print 'Checking isomorphism (depth='+str(length_to_check)+'):',current_config, '<->', second_config print('Checking isomorphism (depth={}): {} <-> {}'.format( length_to_check, current_config, second_config)) if self.check_isomorphism(current_config, second_config, length_to_check, make_class, class_bound): self._reductions[current_config] = second_config if verbose: print(current_config,' is reducible to ',second_config) if current_config in self._automaton.keys(): del self._automaton[current_config] for config in self._automaton.keys(): if current_config in self._automaton[config]: self._automaton[config].remove(current_config) self._automaton[config].append(self.follow_reduce(second_config)) configs_to_check.append(second_config) reducible = True break if not reducible: if verbose: print(current_config,'is not reducible') if make_class and len(self._class) < len(current_config) + 2 and len(current_config) + 2 <= class_bound: if verbose: # print '\t\t\tExtending class length from ', (len(self._class) - 1), 'to', (len(current_config) + 2), 'for', current_config, '(!)' print('\t\t\tExtending class length from {} to {} for {} (!)'.format( len(self._class - 1), len(current_config) + 2, current_config)) self._class.extend_to_length(len(current_config)+2) if verbose: print('\t\t\t\tDone!') # print '3' TTT = current_config.valid_children(self._class) self._automaton[current_config] = list(TTT) configs_to_check.extend(TTT) configs_to_check.remove(current_config) configs_to_check = list(set(configs_to_check).difference(self._configs_checked)) self.standardize_perms() self._automaton_ready = True def standardize_perms(self): for config in self._automaton.keys(): for c in self._automaton[config]: if c.is_permutation(): self._automaton[config].remove(c) self._automaton[config].append(self._perm) def check_isomorphism(self, c1, c2, depth, make_class=False, class_bound=100): # print '\t\tCI:',depth,c1,c2,len(self._tree.keys()) if depth == 0 or c1.is_permutation() or c2.is_permutation(): if c1.is_permutation() != c2.is_permutation(): pass # print c1,c2 return c1.is_permutation() == c2.is_permutation() if c1 not in self._tree.keys(): if make_class and len(self._class) < len(c1) + 3 and len(c1) + 2 <= class_bound: print('\t\t\tExtending class length from ', (len(self._class)-1), 'to', (len(c1) + 2), 'for', c1, '(@)') self._class.extend_to_length(len(c1)+2) print('\t\t\t\tDone!') # print '1',c1,len(c1) self._tree[c1] = c1.valid_children(self._class) if c2 not in self._tree.keys(): if make_class and len(self._class) < len(c2) + 3 and len(c2) + 2 <= class_bound: print('\t\t\tExtending class length from ', (len(self._class)-1), 'to', (len(c2) + 2), 'for', c2, '(#)') self._class.extend_to_length(len(c2)+2) print('\t\t\t\tDone!') # print '2' self._tree[c2] = c2.valid_children(self._class) c1kids = {c._type : c for c in self._tree[c1]} c2kids = {c._type : c for c in self._tree[c2]} if set(c1kids.keys()) != set(c2kids.keys()): # print c1,c2,c1kids,c2kids return False # if random.randint(1,1000) == 535: # print '\tnum states:',len(self._tree), '\tdepth:',depth return all([self.check_isomorphism(c1kids[i], c2kids[i], depth-1, make_class, class_bound) for i in c1kids.keys()]) def gf(self, verbose=False, show_series=False): if not self._automaton_ready: self.build_rules(verbose=verbose) states = self._automaton.keys() states.append(self._perm) x = sympy.Symbol('x') transitions = [] for s1 in states: t = [] for s2 in states: if s1 in self._automaton.keys() and s2 in self._automaton[s1]: t.append(self._automaton[s1].count(s2)*x) else: t.append(0) transitions.append(t) M = (sympy.eye(len(states))-sympy.Matrix(transitions)) ** -1 f = (1+M[states.index(self._root),states.index(self._perm)]).factor() if show_series: print(f.series(x,0,11)) return f
class InsertionScheme(): _tree = {} _basis = [] _max_basis_length = 0 _automaton = {} _root = None _configs_checked = set() _automaton_ready = False _has_inssch = False _reductions = {} _class = [] def __init__(self, basis, quiet=False): self._basis = basis self._max_basis_length = max([len(b) for b in self._basis]) self._class = AvClass(basis, 1) self._configs_checked = set() self._automaton_ready = False self._root = Configuration((0, ), self._basis, 'm') self._perm = Configuration((1, ), self._basis, 'f') self._tree = {self._root: self._root.children()} self._automaton = {self._root: list(self._root.children())} self._has_inssch = False self._reductions = {} self._automaton_ready = False if self.has_inssch(): self._has_inssch = True else: syms = PermSet(self._basis).all_syms() for S in syms: self._basis = S if self.has_inssch(): self._has_inssch = True if not quiet: print( 'Av({}) does not have an insertion scheme, but its symmetry Av({}) does.' .format(basis, S)) break if not self._has_inssch: if not quiet: print( 'Neither this class nor its symmetries has an insertion scheme.' ) def has_inssch(self): types = [ PermSet([Permutation(321), Permutation(2143), Permutation(2413)]), PermSet([Permutation(123), Permutation(3142), Permutation(3412)]), PermSet([Permutation(132), Permutation(312)]), PermSet([Permutation(213), Permutation(231)]) ] return all([ any([all([b.avoids(p) for p in B]) for b in self._basis]) for B in types ]) def follow_reduce(self, config): while config in self._reductions.keys(): config = self._reductions[config] return config def build_rules(self, verbose=True, make_class=False, class_bound=100): configs_to_check = [Configuration((0, ), self._basis)] while len(configs_to_check) > 0: if verbose: # print '\tstates to check:',len(configs_to_check),', nodes in tree:',len(self._tree.keys()),', states:', len(self._automaton) s_to_print = '\tstates to check: {}, nodes in tree: {}, states: {}'.format( len(configs_to_check), len(self._tree.keys()), len(self._automaton)) print(s_to_print) configs_to_check.sort(key=len) current_config = configs_to_check[0] if verbose: print('\nChecking: ', current_config) self._configs_checked.add(current_config) if current_config.is_permutation(): if verbose: print(current_config, ' is not reducible') configs_to_check.remove(current_config) continue length_to_check = self._max_basis_length + current_config.num_slots( ) - 2 reducible = False order_to_check = sorted(range(len(current_config)), key=lambda i: current_config[i], reverse=True) checked_already = list() for i in order_to_check: if current_config[i] == 0 or (i > 0 and i < len(current_config) - 1 and current_config[i - 1] == 0 and current_config[i + 1] == 0): continue second_config = Configuration( current_config[:i] + current_config[i + 1:], self._basis, '?') if second_config in checked_already: continue checked_already.append(second_config) if verbose: # print 'Checking isomorphism (depth='+str(length_to_check)+'):',current_config, '<->', second_config print('Checking isomorphism (depth={}): {} <-> {}'.format( length_to_check, current_config, second_config)) if self.check_isomorphism(current_config, second_config, length_to_check, make_class, class_bound): self._reductions[current_config] = second_config if verbose: print(current_config, ' is reducible to ', second_config) if current_config in self._automaton.keys(): del self._automaton[current_config] for config in self._automaton.keys(): if current_config in self._automaton[config]: self._automaton[config].remove(current_config) self._automaton[config].append( self.follow_reduce(second_config)) configs_to_check.append(second_config) reducible = True break if not reducible: if verbose: print(current_config, 'is not reducible') if make_class and len( self._class) < len(current_config) + 2 and len( current_config) + 2 <= class_bound: if verbose: # print '\t\t\tExtending class length from ', (len(self._class) - 1), 'to', (len(current_config) + 2), 'for', current_config, '(!)' print( '\t\t\tExtending class length from {} to {} for {} (!)' .format(len(self._class - 1), len(current_config) + 2, current_config)) self._class.extend_to_length(len(current_config) + 2) if verbose: print('\t\t\t\tDone!') # print '3' TTT = current_config.valid_children(self._class) self._automaton[current_config] = list(TTT) configs_to_check.extend(TTT) configs_to_check.remove(current_config) configs_to_check = list( set(configs_to_check).difference(self._configs_checked)) self.standardize_perms() self._automaton_ready = True def standardize_perms(self): for config in self._automaton.keys(): for c in self._automaton[config]: if c.is_permutation(): self._automaton[config].remove(c) self._automaton[config].append(self._perm) def check_isomorphism(self, c1, c2, depth, make_class=False, class_bound=100): # print '\t\tCI:',depth,c1,c2,len(self._tree.keys()) if depth == 0 or c1.is_permutation() or c2.is_permutation(): if c1.is_permutation() != c2.is_permutation(): pass # print c1,c2 return c1.is_permutation() == c2.is_permutation() if c1 not in self._tree.keys(): if make_class and len( self._class) < len(c1) + 3 and len(c1) + 2 <= class_bound: print('\t\t\tExtending class length from ', (len(self._class) - 1), 'to', (len(c1) + 2), 'for', c1, '(@)') self._class.extend_to_length(len(c1) + 2) print('\t\t\t\tDone!') # print '1',c1,len(c1) self._tree[c1] = c1.valid_children(self._class) if c2 not in self._tree.keys(): if make_class and len( self._class) < len(c2) + 3 and len(c2) + 2 <= class_bound: print('\t\t\tExtending class length from ', (len(self._class) - 1), 'to', (len(c2) + 2), 'for', c2, '(#)') self._class.extend_to_length(len(c2) + 2) print('\t\t\t\tDone!') # print '2' self._tree[c2] = c2.valid_children(self._class) c1kids = {c._type: c for c in self._tree[c1]} c2kids = {c._type: c for c in self._tree[c2]} if set(c1kids.keys()) != set(c2kids.keys()): # print c1,c2,c1kids,c2kids return False # if random.randint(1,1000) == 535: # print '\tnum states:',len(self._tree), '\tdepth:',depth return all([ self.check_isomorphism(c1kids[i], c2kids[i], depth - 1, make_class, class_bound) for i in c1kids.keys() ]) def gf(self, verbose=False, show_series=False): if not self._automaton_ready: self.build_rules(verbose=verbose) states = self._automaton.keys() states.append(self._perm) x = sympy.Symbol('x') transitions = [] for s1 in states: t = [] for s2 in states: if s1 in self._automaton.keys() and s2 in self._automaton[s1]: t.append(self._automaton[s1].count(s2) * x) else: t.append(0) transitions.append(t) M = (sympy.eye(len(states)) - sympy.Matrix(transitions))**-1 f = (1 + M[states.index(self._root), states.index(self._perm)]).factor() if show_series: print(f.series(x, 0, 11)) return f