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 RealProjectiveSpace(n): """ Return real `n`-dimensional projective space, as a simplicial set. This is constructed as the `n`-skeleton of the nerve of the group of order 2, and therefore has a single non-degenerate simplex in each dimension up to `n`. EXAMPLES:: sage: simplicial_sets.RealProjectiveSpace(7) RP^7 sage: RP5 = simplicial_sets.RealProjectiveSpace(5) sage: RP5.homology() {0: 0, 1: C2, 2: 0, 3: C2, 4: 0, 5: Z} sage: RP5 RP^5 sage: latex(RP5) RP^{5} sage: BC2 = simplicial_sets.RealProjectiveSpace(Infinity) sage: latex(BC2) RP^{\infty} """ if n == Infinity: X = AbelianGroup([2]).nerve() X.rename('RP^oo') X.rename_latex('RP^{\\infty}') else: X = RealProjectiveSpace(Infinity).n_skeleton(n) X.rename('RP^{}'.format(n)) X.rename_latex('RP^{{{}}}'.format(n)) return X
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() ])
def free(index_set=None, names=None, **kwds): r""" Return the free commutative group. INPUT: - ``index_set`` -- (optional) an index set for the generators; if an integer, then this represents `\{0, 1, \ldots, n-1\}` - ``names`` -- a string or list/tuple/iterable of strings (default: ``'x'``); the generator names or name prefix EXAMPLES:: sage: Groups.Commutative.free(index_set=ZZ) Free abelian group indexed by Integer Ring sage: Groups().Commutative().free(ZZ) Free abelian group indexed by Integer Ring sage: Groups().Commutative().free(5) Multiplicative Abelian group isomorphic to Z x Z x Z x Z x Z sage: F.<x,y,z> = Groups().Commutative().free(); F Multiplicative Abelian group isomorphic to Z x Z x Z """ from sage.rings.all import ZZ if names is not None: if isinstance(names, str): if ',' not in names and index_set in ZZ: names = [names + repr(i) for i in range(index_set)] else: names = names.split(',') names = tuple(names) if index_set is None: index_set = ZZ(len(names)) if index_set in ZZ: from sage.groups.abelian_gps.abelian_group import AbelianGroup return AbelianGroup(index_set, names=names, **kwds) if index_set in ZZ: from sage.groups.abelian_gps.abelian_group import AbelianGroup return AbelianGroup(index_set, **kwds) from sage.groups.indexed_free_group import IndexedFreeAbelianGroup return IndexedFreeAbelianGroup(index_set, names=names, **kwds)
def homotopy_group(self, n): """ Return the n'th homotopy group of ``self`` INPUT: - ``n`` - the dimension of the homotopy group to be computed EXAMPLES:: sage: from sage.interfaces.kenzo import Sphere # optional - kenzo sage: s2 = Sphere(2) # optional - kenzo sage: p = s2.cartesian_product(s2) # optional - kenzo sage: p.homotopy_group(3) # optional - kenzo Multiplicative Abelian group isomorphic to Z x Z """ if n not in ZZ or n < 2: raise ValueError( "homotopy groups can only be computed for dimensions greater than 1" ) lgens = homotopy_list(self._kenzo, n).python() if lgens is not None: trgens = [0 if i == 1 else i for i in sorted(lgens)] return AbelianGroup(trgens) else: return AbelianGroup([])
def dft(self, chi = lambda x: x): """ A discrete Fourier transform "over `\QQ`" using exact `N`-th roots of unity. EXAMPLES:: sage: J = range(6) sage: A = [ZZ(1) for i in J] sage: s = IndexedSequence(A,J) sage: s.dft(lambda x:x^2) Indexed sequence: [6, 0, 0, 6, 0, 0] indexed by [0, 1, 2, 3, 4, 5] sage: s.dft() Indexed sequence: [6, 0, 0, 0, 0, 0] indexed by [0, 1, 2, 3, 4, 5] sage: G = SymmetricGroup(3) sage: J = G.conjugacy_classes_representatives() sage: s = IndexedSequence([1,2,3],J) # 1,2,3 are the values of a class fcn on G sage: s.dft() # the "scalar-valued Fourier transform" of this class fcn Indexed sequence: [8, 2, 2] indexed by [(), (1,2), (1,2,3)] sage: J = AbelianGroup(2,[2,3],names='ab') sage: s = IndexedSequence([1,2,3,4,5,6],J) sage: s.dft() # the precision of output is somewhat random and architecture dependent. Indexed sequence: [21.0000000000000, -2.99999999999997 - 1.73205080756885*I, -2.99999999999999 + 1.73205080756888*I, -9.00000000000000 + 0.0000000000000485744257349999*I, -0.00000000000000976996261670137 - 0.0000000000000159872115546022*I, -0.00000000000000621724893790087 - 0.0000000000000106581410364015*I] indexed by Multiplicative Abelian group isomorphic to C2 x C3 sage: J = CyclicPermutationGroup(6) sage: s = IndexedSequence([1,2,3,4,5,6],J) sage: s.dft() # the precision of output is somewhat random and architecture dependent. Indexed sequence: [21.0000000000000, -2.99999999999997 - 1.73205080756885*I, -2.99999999999999 + 1.73205080756888*I, -9.00000000000000 + 0.0000000000000485744257349999*I, -0.00000000000000976996261670137 - 0.0000000000000159872115546022*I, -0.00000000000000621724893790087 - 0.0000000000000106581410364015*I] indexed by Cyclic group of order 6 as a permutation group sage: p = 7; J = range(p); A = [kronecker_symbol(j,p) for j in J] sage: s = IndexedSequence(A,J) sage: Fs = s.dft() sage: c = Fs.list()[1]; [x/c for x in Fs.list()]; s.list() [0, 1, 1, -1, 1, -1, -1] [0, 1, 1, -1, 1, -1, -1] The DFT of the values of the quadratic residue symbol is itself, up to a constant factor (denoted c on the last line above). .. TODO:: Read the parent of the elements of S; if `\QQ` or `\CC` leave as is; if AbelianGroup, use abelian_group_dual; if some other implemented Group (permutation, matrix), call .characters() and test if the index list is the set of conjugacy classes. """ J = self.index_object() ## index set of length N N = len(J) S = self.list() F = self.base_ring() ## elements must be coercible into QQ(zeta_N) if not(J[0] in ZZ): G = J[0].parent() ## if J is not a range it is a group G if J[0] in ZZ and F.base_ring().fraction_field()==QQ: ## assumes J is range(N) zeta = CyclotomicField(N).gen() FT = [sum([S[i]*chi(zeta**(i*j)) for i in J]) for j in J] elif not(J[0] in ZZ) and G.is_abelian() and F == ZZ or (F.is_field() and F.base_ring()==QQ): if is_PermutationGroupElement(J[0]): ## J is a CyclicPermGp n = G.order() a = list(factor(n)) invs = [x[0]**x[1] for x in a] G = AbelianGroup(len(a),invs) ## assumes J is AbelianGroup(...) Gd = G.dual_group() FT = [sum([S[i]*chid(G.list()[i]) for i in range(N)]) for chid in Gd] elif not(J[0] in ZZ) and G.is_finite() and F == ZZ or (F.is_field() and F.base_ring()==QQ): ## assumes J is the list of conj class representatives of a ## PermuationGroup(...) or Matrixgroup(...) chi = G.character_table() FT = [sum([S[i]*chi[i,j] for i in range(N)]) for j in range(N)] else: raise ValueError("list elements must be in QQ(zeta_"+str(N)+")") return IndexedSequence(FT,J)
def RealProjectiveSpace(n): r""" Return real `n`-dimensional projective space, as a simplicial set. This is constructed as the `n`-skeleton of the nerve of the group of order 2, and therefore has a single non-degenerate simplex in each dimension up to `n`. EXAMPLES:: sage: simplicial_sets.RealProjectiveSpace(7) RP^7 sage: RP5 = simplicial_sets.RealProjectiveSpace(5) sage: RP5.homology() {0: 0, 1: C2, 2: 0, 3: C2, 4: 0, 5: Z} sage: RP5 RP^5 sage: latex(RP5) RP^{5} sage: BC2 = simplicial_sets.RealProjectiveSpace(Infinity) sage: latex(BC2) RP^{\infty} """ if n == Infinity: X = AbelianGroup([2]).nerve() X.rename('RP^oo') X.rename_latex('RP^{\\infty}') else: X = RealProjectiveSpace(Infinity).n_skeleton(n) X.rename('RP^{}'.format(n)) X.rename_latex('RP^{{{}}}'.format(n)) return X