def __iter__(self): r""" Naive algorithm to give the elements of the conjugacy class. .. TODO:: Implement a non-naive algorithm, cf. for instance G. Butler: "An Inductive Schema for Computing Conjugacy Classes in Permutation Groups", Math. of Comp. Vol. 62, No. 205 (1994) EXAMPLES: Groups of permutations:: sage: G = SymmetricGroup(3) sage: g = G((1,2)) sage: C = ConjugacyClass(G,g) sage: sorted(C) [(2,3), (1,2), (1,3)] It works for infinite groups:: sage: a = matrix(ZZ,2,[1,1,0,1]) sage: b = matrix(ZZ,2,[1,0,1,1]) sage: G = MatrixGroup([a,b]) # takes 1s sage: a = G(a) sage: C = ConjugacyClass(G, a) sage: it = iter(C) sage: [next(it) for _ in range(5)] [ [1 1] [ 2 1] [ 0 1] [ 3 1] [ 3 4] [0 1], [-1 0], [-1 2], [-4 -1], [-1 -1] ] We check that two matrices are in C:: sage: b = G(b) sage: m1 = b * a * ~b sage: m2 = ~b * a * b sage: any(x == m1 for x in C) True sage: any(x == m2 for x in C) True """ from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet g = self._representative gens = self._parent.monoid_generators() R = RecursivelyEnumeratedSet([g], lambda y: [c*y*c**-1 for c in gens], structure=None) return R.breadth_first_search_iterator()
def __iter__(self): r""" Naive algorithm to give the elements of the conjugacy class. .. TODO:: Implement a non-naive algorithm, cf. for instance G. Butler: "An Inductive Schema for Computing Conjugacy Classes in Permutation Groups", Math. of Comp. Vol. 62, No. 205 (1994) EXAMPLES: Groups of permutations:: sage: G = SymmetricGroup(3) sage: g = G((1,2)) sage: C = ConjugacyClass(G,g) sage: sorted(C) [(2,3), (1,2), (1,3)] It works for infinite groups:: sage: a = matrix(ZZ,2,[1,1,0,1]) sage: b = matrix(ZZ,2,[1,0,1,1]) sage: G = MatrixGroup([a,b]) # takes 1s sage: a = G(a) sage: C = ConjugacyClass(G, a) sage: it = iter(C) sage: [next(it) for _ in range(5)] # random (nothing guarantees enumeration order) [ [1 1] [ 2 1] [ 0 1] [ 3 1] [ 3 4] [0 1], [-1 0], [-1 2], [-4 -1], [-1 -1] ] We check that two matrices are in C:: sage: b = G(b) sage: m1 = b * a * ~b sage: m2 = ~b * a * b sage: any(x == m1 for x in C) True sage: any(x == m2 for x in C) True """ from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet g = self._representative gens = self._parent.monoid_generators() R = RecursivelyEnumeratedSet([g], lambda y: [c * y * c**-1 for c in gens], structure=None) return R.breadth_first_search_iterator()
def connected_component_iterator(self, roots=None): r""" Return an iterator over the connected component of the root. This method overwrites the methods :meth:`slabbe.discrete_subset.DiscreteSubset.connected_component_iterator`, because for billiard words, we go only in one direction in each axis which allows to use a forest structure for the enumeration. INPUT: - ``roots`` - list of some elements immutable in self EXAMPLES:: sage: from slabbe import BilliardCube sage: p = BilliardCube([1,pi,sqrt(7)]) sage: root = vector((0,0,0)) sage: root.set_immutable() sage: it = p.connected_component_iterator(roots=[root]) sage: [next(it) for _ in range(5)] [(0, 0, 0), (0, 1, 0), (0, 1, 1), (0, 2, 1), (1, 2, 1)] :: sage: p = BilliardCube([1,pi,7.45], start=(10.2,20.4,30.8)) sage: it = p.connected_component_iterator() sage: [next(it) for _ in range(5)] [(10.2000000000000, 20.4000000000000, 30.8000000000000), (10.2000000000000, 20.4000000000000, 31.8000000000000), (10.2000000000000, 21.4000000000000, 31.8000000000000), (10.2000000000000, 21.4000000000000, 32.8000000000000), (10.2000000000000, 21.4000000000000, 33.8000000000000)] """ roots = roots if roots else [self.an_element()] if not all(root in self for root in roots): raise ValueError("roots (=%s) must all be in self(=%s)" % (roots, self)) #for root in roots: # root.set_immutable() C = RecursivelyEnumeratedSet(seeds=roots, successors=self.children, structure='forest') return C.breadth_first_search_iterator()
def connected_component_iterator(self, roots=None): r""" Return an iterator over the connected component of the root. This method overwrites the methods :meth:`slabbe.discrete_subset.DiscreteSubset.connected_component_iterator`, because for billiard words, we go only in one direction in each axis which allows to use a forest structure for the enumeration. INPUT: - ``roots`` - list of some elements immutable in self EXAMPLES:: sage: from slabbe import BilliardCube sage: p = BilliardCube([1,pi,sqrt(7)]) sage: root = vector((0,0,0)) sage: root.set_immutable() sage: it = p.connected_component_iterator(roots=[root]) sage: [next(it) for _ in range(5)] [(0, 0, 0), (0, 1, 0), (0, 1, 1), (0, 2, 1), (1, 2, 1)] :: sage: p = BilliardCube([1,pi,7.45], start=(10.2,20.4,30.8)) sage: it = p.connected_component_iterator() sage: [next(it) for _ in range(5)] [(10.2000000000000, 20.4000000000000, 30.8000000000000), (10.2000000000000, 20.4000000000000, 31.8000000000000), (10.2000000000000, 21.4000000000000, 31.8000000000000), (10.2000000000000, 21.4000000000000, 32.8000000000000), (10.2000000000000, 21.4000000000000, 33.8000000000000)] """ roots = roots if roots else [self.an_element()] if not all(root in self for root in roots): raise ValueError("roots (=%s) must all be in self(=%s)" % (roots, self)) #for root in roots: # root.set_immutable() C = RecursivelyEnumeratedSet(seeds=roots, successors=self.children, structure='forest') return C.breadth_first_search_iterator()