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