def multiplicative_subgroups(self): r""" Return generators for each subgroup of `(\ZZ/N\ZZ)^*`. EXAMPLES:: sage: Integers(5).multiplicative_subgroups() ([2], [4], []) sage: Integers(15).multiplicative_subgroups() ([11, 7], [4, 11], [8], [11], [14], [7], [4], []) sage: Integers(2).multiplicative_subgroups() ([],) sage: len(Integers(341).multiplicative_subgroups()) 80 """ from sage.groups.abelian_gps.abelian_group import AbelianGroup from sage.misc.misc import mul U = self.unit_gens() G = AbelianGroup([x.multiplicative_order() for x in U]) rawsubs = G.subgroups() mysubs = [] for G in rawsubs: mysubs.append([]) for s in G.gens(): mysubs[-1].append(mul([U[i] ** s.list()[i] for i in xrange(len(U))])) return tuple(mysubs) # make it immutable, so that we can cache
def multiplicative_subgroups(self): r""" Return generators for each subgroup of `(\ZZ/N\ZZ)^*`. EXAMPLES:: sage: Integers(5).multiplicative_subgroups() ([2], [4], []) sage: Integers(15).multiplicative_subgroups() ([11, 7], [4, 11], [8], [11], [14], [7], [4], []) sage: Integers(2).multiplicative_subgroups() ([],) sage: len(Integers(341).multiplicative_subgroups()) 80 """ from sage.groups.abelian_gps.abelian_group import AbelianGroup from sage.misc.misc import mul U = self.unit_gens() G = AbelianGroup([x.multiplicative_order() for x in U]) rawsubs = G.subgroups() mysubs = [] for G in rawsubs: mysubs.append([]) for s in G.gens(): mysubs[-1].append( mul([U[i]**s.list()[i] for i in xrange(len(U))])) return tuple(mysubs) # make it immutable, so that we can cache
def subgroups_of_finite_abelian_group(A): assert len(A.invariants()) == len(A.gens()) B = AbelianGroup( A.invariants() ) # A is an instance of FGP_Module, which is not a subclass of AbelianGroup # The Sage function AbelianGroup.subgroups is *really, really* slow (as of version 8.1) for BB in reversed( B.subgroups()): # I prefer to get smaller subgroups first yield A.submodule([ A.sum((gen.exponents()[i] * A.gens()[i] for i in range(len(A.gens())))) for gen in BB.gens() ])