コード例 #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])
コード例 #2
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])
コード例 #3
0
     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]
コード例 #4
0
    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]
コード例 #5
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))
コード例 #6
0
    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)
コード例 #7
0
    def __init__(self, data=None, alphabet=None):
        """
        INPUT:

        - ``data`` -- (default None) a list or dictionary
          from a list of edges: ``[initial_vertex,terminal_vertex,letter]``.
          a dictionnary that maps letters of the alphabet to lists
          ``(initial_vertex,terminal_vertex)``
        - ``alphabet`` -- (default None ) alphabet AlphabetWithInverses by default

        """

        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(letters)

        self._alphabet = alphabet

        DiGraph.__init__(self, data=data, loops=True, multiedges=True,
                         vertex_labels=True, pos=None, format=None,
                         weighted=None,
                         implementation='c_graph', sparse=True)


        # 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]
コード例 #8
0
ファイル: graph_map.py プロジェクト: ricwade/sage-train-track
    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)
コード例 #9
0
    def pullback(self, other):
        r"""
        Pullback of the graph maps ``self`` and ``other``.
        The codomain of ``self`` and ``other`` must be the same graph.

        The pullback is a graph map f:G3 -> G that makes the diagram commute:

            G3 -----> G1
            |  \      |
            |   \     | self
            |    \f   |
            |     \   |
            V     _\| V
            G2 -----> G
            ....other

        The pullback method can be used to find intersection of two subgroups
        of a Free Group.

        INPUT: 

        - ``other``: a graph map G2->G with ``self``: a graph map G1->G,

        OUTPUT: 
        
        A ``GraphMap`` f

        EXAMPLES::
  
            sage: G1 = GraphWithInverses.rose_graph(AlphabetWithInverses(2,type='x0'))
            sage: G2 = GraphWithInverses.rose_graph(AlphabetWithInverses(2,type='a0'))
            sage: G =  GraphWithInverses.rose_graph(AlphabetWithInverses(2))
            sage: n1 = WordMorphism({'x0':['a','a'],'x1':['b','a']})
            sage: n2 = WordMorphism({'a0':['b','a'],'a1':['b','b','b','a','B','a']})
            sage: f1 = GraphMap(G1,G,n1)
            sage: f2 = GraphMap(G2,G,n2)
            sage: print f1.pullback(f2)
            Graph map:
            Graph with inverses: a0: (0, 0)->(1, 2), a1: (0, 2)->(1, 0), a2: (0, 2)->(1, 3), a3: (0, 3)->(1, 4), a4: (0, 4)->(1, 3), a5: (1, 2)->(0, 0), a6: (1, 4)->(0, 3)
            Graph with inverses: a: 0->0, b: 0->0
            edge map: a0->b, a1->a, a2->b, a3->b, a4->a, a5->a, a6->a

        AUTHORS:

        - Radhika GUPTA
        """
        import itertools
        # First convert self and f2 into immersions
        self.stallings_folding()
        other.stallings_folding()

        G3 = GraphWithInverses()
        A = AlphabetWithInverses(0, type='a0')
        d = {}
        # get set of vertices
        V = []
        for i in itertools.product(self.domain().vertices(),
                                   other.domain().vertices()):
            V.append(i)

        # add edges
        for v in V:
            for w in V:
                for e1 in self.domain().alphabet().positive_letters():
                    if self.domain().initial_vertex(e1) == v[0] \
                            and self.domain().terminal_vertex(e1) == w[0]:
                        for e2 in other.domain().alphabet().positive_letters():
                            if other.domain().initial_vertex(e2) == v[1] \
                                    and other.domain().terminal_vertex(e2) == w[
                                        1]:
                                if self.image(e1) == other.image(e2):
                                    e = A.add_new_letter()
                                    G3.add_edge(v, w, e)
                                    # update dictionary to define map on G3
                                    d[e[0]] = self.image(e1)

        G3._alphabet = A
        n3 = WordMorphism(d)
        G = self.codomain()  # same as other.codomain()

        return GraphMap(G3, G, n3)
コード例 #10
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``.

        OUTPUT:
        A homotopy inverse of ``self``.

        WARNING:

        ``self`` is assumed to be a homotopy equivalence.

        EXAMPLES::

            sage: G = GraphWithInverses([[0,0,'a'],[0,1,'b'],[1,1,'c']])
            sage: A = AlphabetWithInverses(2)
            sage: H = GraphWithInverses.rose_graph(A)
            sage: f = GraphMap(G,H,"a->ab,b->b,c->B")
            sage: print f.inverse()
            Graph map:
            Graph with inverses: a: 0->0, b: 0->0
            Graph with inverses: a: 0->0, b: 0->1, c: 1->1
            edge map: a->abcB, b->bCB
        """

        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)
コード例 #11
0
 def __init__(self,alphabet):
     if not isinstance(alphabet,AlphabetWithInverses):
         alphabet=AlphabetWithInverses(alphabet)
     FiniteWords_over_OrderedAlphabet.__init__(self,alphabet)
コード例 #12
0
ファイル: graph_map.py プロジェクト: ricwade/sage-train-track
    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)