Beispiel #1
0
    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,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 Hilion_parabolic(k=1):
        """
        Automorphism given in Section 2 of [Hilion].

        This automorphism has a parabolic orbit inside F_4.

        REFERENCES:

        [Hilion] A. Hilion

        """
        F=FreeGroup(4)
        phi=FreeGroupAutomorphism("a->a,b->ba,c->caa,d->dc",F)
        if k>1:
            phi=phi*pow(F.dehn_twist(c,a),k-1)
        return phi
    def Hilion_parabolic(k=1):
        """
        Automorphism given in Section 2 of [Hilion].

        This automorphism has a parabolic orbit inside F_4.

        REFERENCES:

        [Hilion] A. Hilion, Dynamique des automorphismes des groupes
        libres, Thesis (Toulouse, 2004).

        """
        F=FreeGroup(4)
        phi=FreeGroupAutomorphism("a->a,b->ba,c->caa,d->dc",F)
        if k>1:
            phi=phi*pow(F.dehn_twist(c,a),k-1)
        return phi
Beispiel #5
0
    def Hilion_parabolic(k=1):
        """
        Automorphism given in Section 2 of [Hilion].

        This automorphism has a parabolic orbit inside F_4.

        REFERENCES:

        [Hilion] A. Hilion, Dynamique des automorphismes des groupes
        libres, Thesis (Toulouse, 2004).

        """
        F = FreeGroup(4)
        phi = FreeGroupAutomorphism("a->a,b->ba,c->caa,d->dc", F)
        if k > 1:
            phi = phi * pow(F.dehn_twist(c, a), k - 1)
        return phi
Beispiel #6
0
    def Bestvina_Handel_train_track_1_9():
        """
        Automorphism given as Example 1.9 in [BH-train-track]

        This automorphism cannot be represented by an absolute train-track. But
        the representation on the rose is a relative train-track.

        REFERENCES:

        [BH-train-track] M. Bestvina, M.  Handel, Train tracks and
        automorphisms of free groups, Annals of Math, 135, 1-51, 1992.
        """
        return FreeGroupAutomorphism("a->ba,b->bba,c->cAbaB", FreeGroup(3))
Beispiel #7
0
    def Bestvina_Handel_train_track_3_6():
        """
        Automorphism given as Example 3.6 in [BH-train-track].

        This automorphism is train-track on the rose and has an indivisble
        Nielsen path in A.b which is essential.

        REFERENCES:

        [BH-train-track] M. Bestvina, M.  Handel, Train tracks and
        automorphisms of free groups, Annals of Math, 135, 1-51, 1992.

        """
        return FreeGroupAutomorphism("a->ba,b->bba", FreeGroup(2))
Beispiel #8
0
    def Levitt_Lustig_periodic():
        """
        Automorphism of F_3 given in Section 2 of [LL-periodic].

        This is an atoroidal iwip. It is positive and thus train-track
        on the rose.

        REFERENCES:
        
        [LL-periodic] G. Levitt, and M. Lustig, Automorphisms of free
        groups have asymptotically periodic dynamics,

        """
        return FreeGroupAutomorphism("a->cb,b->a,c->ba", FreeGroup(3))
Beispiel #9
0
    def Clay_Pettet_twisting_out():
        """
        Automorphism of F_3 given in Section 2 of [CP-twisting].

        This is an atoroidal iwip. It is positive and thus train-track
        on the rose.

        REFERENCES:
        
        [CP-twisting] M. Clay, and A. Pettet, Twisting out fully
        irreducible automorphisms, ArXiv:0906.4050

        """
        return FreeGroupAutomorphism("a->b,b->c,c->ab", FreeGroup(3))
Beispiel #10
0
    def Bestvina_Handel_train_track_1_1():
        """
        Automorphism given as Example 1.1 in [BH-train-track]. 

        This automorphism is iwip and not geometric nor
        parageometric. Its representative on the rose is
        train-track. Its inverse is also train-track on the rose.

        REFERENCES:

        [BH-train-track] M. Bestvina, M.  Handel, Train tracks and
        automorphisms of free groups, Annals of Math, 135, 1-51, 1992.
        """
        return FreeGroupAutomorphism("a->b,b->c,c->d,d->ADBC", FreeGroup(4))
Beispiel #11
0
    def Bestvina_Handel_train_track_5_16():
        """
        Automorphism given as Example 5.16 in [BH-train-track].

        This automorphism occurs as a pseudo-Anosov homeomorphism of
        the four-times punctured phere. Thus is it reducible.

        REFERENCES:

        [BH-train-track] M. Bestvina, M.  Handel, Train tracks and
        automorphisms of free groups, Annals of Math, 135, 1-51, 1992.

        """
        return FreeGroupAutomorphism("a->a,b->CAbac,c->CAbacacACABac",
                                     FreeGroup(3))
Beispiel #12
0
    def Cohen_Lustig_7_3():
        """

        Automorphism given as example 7.3 in [CL-dynamics].

        This is an atoroidal iwip.

        REFERENCES:

        [CL-dynamics] M. Cohen, M. Lustig, on the dynamics and the
        fixed subgroup of a free group automorphism, Inventiones
        Math. 96, 613-638, 1989.

        """
        return FreeGroupAutomorphism("a->cabaa,b->baa,c->caba", FreeGroup(3))
Beispiel #13
0
    def Cohen_Lustig_1_6():
        """

        Automorphism given as example 1.6 in [CL-dynamics].

        It is reducible.

        REFERENCES:

        [CL-dynamics] M. Cohen, M. Lustig, on the dynamics and the
        fixed subgroup of a free group automorphism, Inventiones
        Math. 96, 613-638, 1989.

        """
        return FreeGroupAutomorphism(
            "a->cccaCCC,b->CaccAbC,c->accAbccaCCBaCCAccccACCC", FreeGroup(3))
Beispiel #14
0
    def Handel_Mosher_axes_5_5():
        """
        Automorphism given in Section 5.5 of [HM-axes]

        This automorphism phi is iwip and not geometric. Both phi and
        phi.inverse() are train-track on the rose. phi has expansion
        factor 6.0329 while phi.inverse() has expansion factor
        4.49086.

        REFERENCES:

        [HM-axes] M. Handel, L. Mosher, axes
        in Outer space, Mem. Amer. Math. Soc. 213, 2011.

        """
        return FreeGroupAutomorphism("a->bacaaca,b->baca,c->caaca",
                                     FreeGroup(3))
Beispiel #15
0
    def Handel_Mosher_parageometric_1():
        """
        Automorphism given in the introduction of [HM-parageometric].

        This automorphism phi is iwip, not geometric and
        parageometric. Both phi and phi.inverse() are train-track on
        the rose. phi has expansion factor 1.46557 while phi.inverse()
        has expansion factor 1.3247.

        REFERENCES:

        [HM-parageometric] M. Handel, L. Mosher, parageometric outer
        automorphisms of free groups, Transactions of
        Amer. Math. Soc. 359, 3153-3183, 2007.

        """
        return FreeGroupAutomorphism("a->ac,b->a,c->b", FreeGroup(3))
Beispiel #16
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))
Beispiel #17
0
    def Handel_Mosher_inverse_with_same_lambda():
        """
        Example given in the introduction of [HM-parageometric].

        This is an iwip automorphisms that has the same expansion factor as its
        inverse: 3.199. It is not geometric and not parageometric.

        REFERECENCES:

        [HM-parageometric] M. Handel, L. Mosher, parageometric outer
        automorphisms of free groups, Transactions of
        Amer. Math. Soc. 359, 3153-3183, 2007.
        """
        F = FreeGroup(3)
        theta = pow(FreeGroupAutomorphism("a->b,b->c,c->Ba", F), 4)
        psi = FreeGroupAutomorphism("a->b,b->a,c->c", F)
        return psi * theta * psi * theta.inverse()
Beispiel #18
0
    def Turner_Stallings():
        """
        Automorphism of F_4 given in [Turner].

        This automorphism comes from an idea of Stallings and although
        it is very short, it has a very long fixed word. 

        It is a reducible automorphism.

        REFERENCES:

        [Turner] E. C. Turner, Finding indivisible Nielsen paths for a
        train tracks map, Proc. of a work- shop held at Heriot-Watt Univ.,
        Edinburg, 1993 (Lond. Math. Soc. Lect. Note Ser., 204), Cambridge,
        Cambridge Univ. Press., 1995, 300-313.
        """
        return FreeGroupAutomorphism("a->dac,b->CADac,c->CABac,d->CAbc",
                                     FreeGroup(4))
Beispiel #19
0
    def Bestvina_Handel_surface_homeo():
        """
        Automorphism of F_4 given in [BH] see also [Kapovich].

        This is a pseudo-Anosov mapping class of the 5-punctured
        sphere. Thus this is not an iwip. However, its representative
        on the rose in train-track.

        REFERENCES:
        
        [BH] M. Bestvina, and M. Handel, Train-tracks for surface
        homeomorphisms. Topology 34 (1995), no. 1, 109-140

        [Kapovich] Ilya Kapovich, Algorithmic detectability of iwip
        automorphisms, arXiv:1209.3732

        """

        return FreeGroupAutomorphism("a->b,b->c,c->dA,d->DC", FreeGroup(4))
Beispiel #20
0
    def _build_endmap(self, consolidate=False):
        """
        Builds the map on ends for graph_map.  Called when Core is initialized.
        """
        alph = self._graph_map.domain()._alphabet
        inv_alph = self._inv_graph_map.domain()._alphabet
        FA = FreeGroup(alph)
        FB = FreeGroup(inv_alph)
        for x in self._graph_map.domain().edge_labels():
            X = alph.inverse_letter(x)
            self._signed_ends[x] = []
            self._signed_ends[X] = []

        for x in self._inv_graph_map.domain().edge_labels():
            X = inv_alph.inverse_letter(x)
            inv_image_x = self._inv_graph_map(x)
            vp = ''  # vanishing path
            for a in inv_image_x:
                A = alph.inverse_letter(a)
                if vp == '' or vp[
                        -1] != X:  # coming from + side, no cancellation
                    self._signed_ends[a].append(vp + x)
                else:  # coming from - side, cancels x
                    self._signed_ends[a].append('-' + vp)  # - + vp #
                # add to vanishing path
                vp = str(FB.reduced_product(str(self._graph_map(A)), vp))
                # repeat for inverse, we've added to the vanishing path because we are
                # coming from the other side
                if vp == '' or vp[
                        -1] != X:  # coming from - side, no cancellation
                    self._signed_ends[A].append('-' + vp + x)  # - + vp + x
                else:  # coming from + side, cancels x
                    self._signed_ends[A].append(vp)

        if consolidate:
            for a in self._signed_ends.keys():
                removed_end = True
                N = 2 * inv_alph.cardinality(
                )  # should take into account the actual vertex...
                while removed_end:
                    removed_end = False
                    prefix = []
                    for e in self._signed_ends[a]:
                        prefix.append(e[:-1])
                    prefix_counts = dict(
                        (p, prefix.count(p)) for p in set(prefix))
                    for p in prefix_counts.keys():
                        p_opp = p[1:] if p[:1] == '-' else '-' + p
                        removed_ends = []
                        tails = []
                        if prefix_counts[p] == N - 1:
                            removed_end = True
                            for e in self._signed_ends[a]:
                                if e[:-1] == p:
                                    removed_ends.append(e)
                                    tails.append(e[-1:])
                            if p == '' or p == '-':
                                for aa in inv_alph:
                                    if aa not in tails:
                                        self._signed_ends[a].append(p_opp + aa)
                            else:
                                self._signed_ends[a].append(p)
                            for e in removed_ends:
                                self._signed_ends[a].remove(e)
                        if prefix_counts[
                                p] == N - 2 and p_opp in self._signed_ends[a]:
                            removed_end = True
                            for e in self._signed_ends[a]:
                                if e[:-1] == p:
                                    removed_ends.append(e)
                                    tails.append(e[-1:])
                            tails.append(inv_alph.inverse_letter(p[-1:]))
                            for aa in inv_alph:
                                if aa not in tails:
                                    self._signed_ends[a].append(p_opp + aa)
                            for e in removed_ends:
                                self._signed_ends[a].remove(e)
                            self._signed_ends[a].remove(p_opp)
Beispiel #21
0
    def _build_endmap(self,consolidate=False):
        """
        Builds the map on ends for graph_map.  Called when Core is initialized.
        """
        alph=self._graph_map.domain()._alphabet
        inv_alph=self._inv_graph_map.domain()._alphabet
        FA=FreeGroup(alph)
        FB=FreeGroup(inv_alph)
        for x in self._graph_map.domain().edge_labels():
            X=alph.inverse_letter(x)
            self._signed_ends[x]=[]
            self._signed_ends[X]=[]

        for x in self._inv_graph_map.domain().edge_labels():
            X=inv_alph.inverse_letter(x)
            inv_image_x = self._inv_graph_map(x)
            vp='' # vanishing path
            for a in inv_image_x:
                A=alph.inverse_letter(a)
                if vp=='' or vp[-1]!=X: # coming from + side, no cancellation
                    self._signed_ends[a].append(vp + x)
                else: # coming from - side, cancels x
                    self._signed_ends[a].append('-' + vp) # - + vp #
                # add to vanishing path
                vp=str(FB.reduced_product(str(self._graph_map(A)),vp))
                # repeat for inverse, we've added to the vanishing path because we are
	  	# coming from the other side
                if vp=='' or vp[-1]!=X: # coming from - side, no cancellation
                    self._signed_ends[A].append('-' + vp + x) # - + vp + x
                else: # coming from + side, cancels x
                    self._signed_ends[A].append(vp)

        if consolidate:
            for a in self._signed_ends.keys():
                removed_end=True
                N=2*inv_alph.cardinality() # should take into account the actual vertex...
                while removed_end:
                    removed_end=False
                    prefix=[]
                    for e in self._signed_ends[a]:
                        prefix.append(e[:-1])
                    prefix_counts=dict((p,prefix.count(p)) for p in set(prefix))
                    for p in prefix_counts.keys():
                        p_opp = p[1:] if p[:1]=='-' else '-'+p
                        removed_ends=[]
                        tails=[]
                        if prefix_counts[p]==N-1:
                            removed_end=True
                            for e in self._signed_ends[a]:
                                if e[:-1]==p:
                                    removed_ends.append(e)
                                    tails.append(e[-1:])
                            if p=='' or p=='-':
                                for aa in inv_alph:
                                    if aa not in tails: self._signed_ends[a].append(p_opp+aa)
                            else: self._signed_ends[a].append(p)
                            for e in removed_ends: self._signed_ends[a].remove(e)
                        if prefix_counts[p]==N-2 and p_opp in self._signed_ends[a]:
                            removed_end=True
                            for e in self._signed_ends[a]:
                                if e[:-1]==p:
                                    removed_ends.append(e)
                                    tails.append(e[-1:])
                            tails.append(inv_alph.inverse_letter(p[-1:]))
                            for aa in inv_alph:
                                if aa not in tails: self._signed_ends[a].append(p_opp+aa)
                            for e in removed_ends: self._signed_ends[a].remove(e)
                            self._signed_ends[a].remove(p_opp)
Beispiel #22
0
 def tribonacci():
     """
     Tribonacci automorphism.
     """
     return FreeGroupAutomorphism("a->ab,b->ac,c->a", FreeGroup(3))
Beispiel #23
0
    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)