def __mul__(self, other):
        # f*g means g comes first, then f
        # print self.domain.foliation
        # print self.codomain.foliation
        # print other.domain.foliation
        # print other.codomain.foliation
        # print self.edge_map
        # print other.edge_map
        new_vertex_map = {v:self.vertex_map[other.vertex_map[v]]
                          for v in other.vertex_map}
        new_edge_map = {e:self._map_path(other.edge_map[e])
                        for e in other.edge_map}

        new_map = TrainTrackMap(domain = other.domain,
                                codomain = self.codomain,
                                vertex_map = new_vertex_map,
                                edge_map = new_edge_map,
                                coding_list = other.coding_list + self.coding_list)
        # if new_map.edge_matrix() !=
        #        self.edge_matrix() * other.edge_matrix():
        # print new_map.edge_matrix(), '\n'
        # print other.edge_matrix() * self.edge_matrix(), '\n'
        # print self.edge_matrix(), '\n'
        # print other.edge_matrix(), '\n'
        # print other.domain._index_to_edge
        # print other.codomain._index_to_edge
        assert(new_map.edge_matrix() ==
               other.edge_matrix() * self.edge_matrix())
        # assert(new_map.small_matrix() ==
        #        other.small_matrix() * self.small_matrix())

        return new_map
    def is_iwip(self,verbose=False):
        """
        ``True`` if ``self`` is an iwip automorphism.

        ALGORITHM:

        0/ Look for a train-track representaive ``f`` for ``self``.

        1/ Try to reduce ``f`` (removing valence 1 or 2 vertices, invariant forests)

        2/ Check that the matrix has a power with strictly positive entries

        3/ Check the connectedness of local Whitehead graphs

        4/ Look for periodic Nielsen paths and periodic Nielsen loops.

        5/ If there are no periodic Nielsen loop then it is an
        atoroidal iwip [Kapo-algo]

        6/ If there is more than two Nielsen loops then it is not iwip

        7/ If there is one iwip check whether it is contained in a
        non-trivial free factor.

        SEE ALSO::
        
        TrainTrackMap.is_iwip()

        REFERENCES

        [Kapo-algo] I. Kapovich, Algorithmic detectability of iwip
        automorphisms, 2012, arXiv:1209.3732
        """
        from train_track_map import TrainTrackMap
        

        f=self.train_track(stable=True,relative=False,verbose=(verbose and verbose<1 and verbose-1))


        if verbose:
            print f
        

        if len(f._strata)>1:
            if verbose:
                print "Reducible"
            return False
        
        f=TrainTrackMap(f)


        return f.is_iwip(verbose)
Exemple #3
0
    def is_iwip(self, verbose=False):
        """
        ``True`` if ``self`` is an iwip automorphism.

        ALGORITHM:

        0/ Look for a train-track representaive ``f`` for ``self``.

        1/ Try to reduce ``f`` (removing valence 1 or 2 vertices, invariant forests)

        2/ Check that the matrix has a power with strictly positive entries

        3/ Check the connectedness of local Whitehead graphs

        4/ Look for periodic Nielsen paths and periodic Nielsen loops.

        5/ If there are no periodic Nielsen loop then it is an
        atoroidal iwip [Kapo-algo]

        6/ If there is more than two Nielsen loops then it is not iwip

        7/ If there is one iwip check whether it is contained in a
        non-trivial free factor.

        SEE ALSO::
        
        TrainTrackMap.is_iwip()

        REFERENCES

        [Kapo-algo] I. Kapovich, Algorithmic detectability of iwip
        automorphisms, 2012, arXiv:1209.3732
        """
        from train_track_map import TrainTrackMap

        f = self.train_track(stable=True,
                             relative=False,
                             verbose=(verbose and verbose < 1 and verbose - 1))

        if verbose:
            print f

        if len(f._strata) > 1:
            if verbose:
                print "Reducible"
            return False

        f = TrainTrackMap(f)

        return f.is_iwip(verbose)
Exemple #4
0
    def index_list(self, verbose=False):
        """Returns the index list of ``self`` provided it is an iwip
        automorphism.

        The index list is the list of indices of non-isogredient
        automorphisms in the outer class of ``self``. The index of an
        automorphism being computed from the number of attracting
        fixed points in the boundary of the free group and the rank of
        the fixed subgroup.

        Some authors (Mosher, Pfaff), use -1/2 our index definition.

        Some authors (Gaboriau, Jaeger, Levitt, Lustig), use 1/2 our index definition

        REFERENCES:

        [GJLL] D. Gaboriau, A. Jaeger, G. Levitt, M. Lustig, An index
        for counting fixed points of automorphisms of free
        groups. Duke Math. J., 93(3):425-452, 1998.

        [HM-axes] M. Handel, L. Mosher, Axes in Outer Space, Memoirs
        AMS 1004, Amer Mathematical Society, 2011.

        [Pfaff] C. Pfaff, Out(F_3) Index realization, arXiv:1311.4490.


        WARNING: ``self`` is assumed to be iwip (or at least to
        have an expanding absolute train-track representative).

        """

        from train_track_map import TrainTrackMap

        f = self.train_track(relative=False,
                             stable=False,
                             verbose=(verbose and verbose > 1 and verbose - 1))
        if f.is_train_track(verbose=(verbose and verbose > 1 and verbose - 1)):
            f = TrainTrackMap(f)
            return f.index_list(
                verbose=(verbose and verbose > 1 and verbose - 1))
        else:
            if verbose:
                print "self is not iwip, not implemented yet in this case"
        return False
    def index_list(self,verbose=False):
        """Returns the index list of ``self`` provided it is an iwip
        automorphism.

        The index list is the list of indices of non-isogredient
        automorphisms in the outer class of ``self``. The index of an
        automorphism being computed from the number of attracting
        fixed points in the boundary of the free group and the rank of
        the fixed subgroup.

        Some authors (Mosher, Pfaff), use -1/2 our index definition.

        Some authors (Gaboriau, Jaeger, Levitt, Lustig), use 1/2 our index definition

        REFERENCES:

        [GJLL] D. Gaboriau, A. Jaeger, G. Levitt, M. Lustig, An index
        for counting fixed points of automorphisms of free
        groups. Duke Math. J., 93(3):425-452, 1998.

        [HM-axes] M. Handel, L. Mosher, Axes in Outer Space, Memoirs
        AMS 1004, Amer Mathematical Society, 2011.

        [Pfaff] C. Pfaff, Out(F_3) Index realization, arXiv:1311.4490.


        WARNING: ``self`` is assumed to be iwip (or at least to
        have an expanding absolute train-track representative).

        """
        
        from train_track_map import TrainTrackMap

        f=self.train_track(relative=False,stable=False,verbose=(verbose and verbose>1 and verbose-1))
        if f.is_train_track(verbose=(verbose and verbose>1 and verbose-1)):
            f=TrainTrackMap(f)
            return f.index_list(verbose=(verbose and verbose>1 and verbose-1))
        else:
            if verbose: print "self is not iwip, not implemented yet in this case"
        return False
Exemple #6
0
    def train_track(self, stable=True, relative=True, verbose=False):
        """
        Computes a train-track representative of ``self``.

        According to the options computes a relative (or ends when
        finding a reduction) and/or stable (with at most one INP
        crossing each exponential stratum). ``verbose`` can be either True
        or a positive number giving details on the computations.

        OUTPUT:

        A topological representative of self.

        - If ``relative=False``, this topological representative is either
        an absolute train-track or fixes a subgraph (with a non
        contractible connected component).

        - If ``relative=True``, the output is either an absolute
          train-track or a relative train-track

        - If ``stable=True``, the output is either a stable absolute
          train-track or a stable relative train-track (if
          relative=False).

        """
        from train_track_map import TrainTrackMap

        f = self.rose_representative()
        f.train_track(verbose)
        if len(f._strata) == 1:
            f = TrainTrackMap(f)
        if stable and len(f._strata) == 1:
            f.stabilize(verbose)
        if relative and len(f._strata) > 1:
            if stable:
                f.stable_relative_train_track(verbose)
            else:
                f.relative_train_track(verbose)
        return f
    def train_track(self,stable=True,relative=True,verbose=False):
        """
        Computes a train-track representative of ``self``.

        According to the options computes a relative (or ends when
        finding a reduction) and/or stable (with at most one INP
        crossing each exponential stratum). ``verbose`` can be either True
        or a positive number giving details on the computations.

        OUTPUT:

        A topological representative of self.

        - If ``relative=False``, this topological representative is either
        an absolute train-track or fixes a subgraph (with a non
        contractible connected component).

        - If ``relative=True``, the output is either an absolute
          train-track or a relative train-track

        - If ``stable=True``, the output is either a stable absolute
          train-track or a stable relative train-track (if
          relative=False).

        """
        from train_track_map import TrainTrackMap

        f=self.rose_representative()
        f.train_track(verbose)
        if len(f._strata)==1:
            f=TrainTrackMap(f)
        if stable and len(f._strata)==1:
            f.stabilize(verbose)
        if relative and len(f._strata)>1:
            if stable:
                f.stable_relative_train_track(verbose)
            else:
                f.relative_train_track(verbose)
        return f