def __init__(self, data, group=None): """ Builds a FreeGroupAutomorphism from data. INPUT: - ``data`` - the data used to build the morphism - ``group`` - an optional free group """ if group is not None and not isinstance(group, FreeGroup): raise ValueError, "the group must be a Free Group" WordMorphism.__init__(self, data) if group is None: A = AlphabetWithInverses(self.domain().alphabet()) F = FreeGroup(A) else: F = group A = group.alphabet() self._domain = F self._codomain = F # unuseful... consistency with WordMorphism for letter in self._morph.keys(): self._morph[letter] = F.reduce(self._morph[letter]) self._morph[A.inverse_letter(letter)] = F.inverse_word( self._morph[letter])
def __init__(self, data=None, alphabet=None): self._initial = {} self._terminal = {} letters = [] if isinstance(data, dict): new_data = dict() for a in data: letters.append(a) if data[a][0] in new_data: if data[a][1] in new_data[data[a][0]]: new_data[data[a][0]][data[a][1]].append(a) else: new_data[data[a][0]][data[a][1]] = [a] else: new_data[data[a][0]] = {data[a][1]: [a]} data = new_data elif isinstance(data, list): new_data = dict() for e in data: letters.append(e[2]) if e[0] in new_data: if e[1] in new_data[e[0]]: new_data[e[0]][e[1]].append(e[2]) else: new_data[e[0]][e[1]] = [e[2]] else: new_data[e[0]] = {e[1]: [e[2]]} data = new_data if alphabet is None: from inverse_alphabet import AlphabetWithInverses alphabet = AlphabetWithInverses(self._initial.keys()) self._alphabet = alphabet DiGraph.__init__(self,data=data,loops=True,multiedges=True,vertex_labels=True,pos=None,format=None,\ boundary=[],weighted=None,implementation='c_graph',sparse=True) for e in self.edges(): self._initial[e[2]] = e[0] self._terminal[e[2]] = e[1] self._initial[alphabet.inverse_letter(e[2])] = e[1] self._terminal[alphabet.inverse_letter(e[2])] = e[0]
def Handel_Mosher_axes_3_4(): """ Automorphism given in Section 3.4 of [HM-axes] This automorphism is iwip, not geometric and is train-track on the rose. It has expansion factor 4.0795. Its inverse is not train-track on the rose and has expansion factor 2.46557. It also appears in Section 5.5 of the paper. REFERENCES: [HM-axes] M. Handel, L. Mosher, axes in Outer space, Mem. Amer. Math. Soc. 213, 2011. """ A = AlphabetWithInverses(['a', 'g', 'f'], ['A', 'G', 'F']) return FreeGroupAutomorphism("a->afgfgf,f->fgf,g->gfafg", FreeGroup(A))
def valence_3(rank): """ A strongly connected graph with all vertices of valence 3 and of given rank. ``rank`` is assumed to be greater or equal than 2. """ graph = dict() A = AlphabetWithInverses(3 * rank - 3) for i in xrange(rank - 2): graph[A[2 * i]] = (2 * i + 1, 2 * i + 3) graph[A[2 * i + 1]] = (2 * i + 1, 2 * i + 2) graph[A[i + 2 * rank - 4]] = (2 * i, 2 * i + 2) graph[A[3 * rank - 6]] = (2 * rank - 4, 2 * rank - 3) graph[A[3 * rank - 5]] = (0, 2 * rank - 3) graph[A[3 * rank - 4]] = (0, 1) return GraphWithInverses(graph, A)
def __init__(self,alphabet): if not isinstance(alphabet,AlphabetWithInverses): alphabet=AlphabetWithInverses(alphabet) FiniteWords_over_OrderedAlphabet.__init__(self,alphabet)
def inverse(self): """A homotopy inverse of ``self``. For ``t1=self.domain().spanning_tree()`` and ``t2=self.codomain().spanning_tree()``. The alphabet ``A`` is made of edges not in ``t1`` identified (by their order in the alphabets of the domain and codomain) to letters not in ``t2``. The automorphism ``phi`` of ``FreeGroup(A)`` is defined using ``t1`` and ``t2``. The inverse map is given by ``phi.inverse()`` using ``t1`` and edges from ``t2`` are mapped to a single point (the root of ``t1``). In particular the inverse maps all vertices to the root of ``t1``. WARNING: ``self`` is assumed to be a homotopy equivalence. """ from free_group import FreeGroup from free_group_automorphism import FreeGroupAutomorphism G1 = self.domain() A1 = G1.alphabet() t1 = G1.spanning_tree() G2 = self.codomain() A2 = G2.alphabet() t2 = G2.spanning_tree() A = AlphabetWithInverses(len(A1) - len(G1.vertices()) + 1) F = FreeGroup(A) map = dict() translate = dict() i = 0 for a in A1.positive_letters(): l = len(t1[G1.initial_vertex(a)]) - len(t1[G1.terminal_vertex(a)]) if (l!=1 or t1[G1.initial_vertex(a)][-1]!=A1.inverse_letter(a)) and\ (l!=-1 or t1[G1.terminal_vertex(a)][-1]!=a): # a is not in the spanning tree map[A[i]] = self(t1[G1.initial_vertex(a)] * Word([a]) * G1.reverse_path(t1[G1.terminal_vertex(a)])) translate[A[i]] = a translate[A.inverse_letter(A[i])] = A1.inverse_letter(a) i += 1 rename = dict() edge_map = dict() i = 0 for a in A2.positive_letters(): l = len(t2[G2.initial_vertex(a)]) - len(t2[G2.terminal_vertex(a)]) if (l!=1 or t2[G2.initial_vertex(a)][-1]!=A2.inverse_letter(a)) and\ (l!=-1 or t2[G2.terminal_vertex(a)][-1]!=a): # a is not in the spanning tree rename[a] = A[i] rename[A2.inverse_letter(a)] = A.inverse_letter(A[i]) i += 1 else: edge_map[a] = Word() for a in map: map[a] = F([rename[b] for b in map[a] if b in rename]) phi = FreeGroupAutomorphism(map, F) psi = phi.inverse() i = 0 for a in A2.positive_letters(): if a not in edge_map: result = Word() for b in psi.image(A[i]): c = translate[b] result = result * t1[G1.initial_vertex(c)] * Word( [c]) * G1.reverse_path(t1[G1.terminal_vertex(c)]) edge_map[a] = G1.reduce_path(result) i += 1 return GraphMap(G2, G1, edge_map)