Пример #1
0
 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
Пример #2
0
 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
Пример #3
0
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
Пример #4
0
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()
        ])
Пример #5
0
        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)
Пример #6
0
 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([])
Пример #7
0
    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)
Пример #8
0
    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)
Пример #9
0
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