Ejemplo n.º 1
0
Archivo: grs.py Proyecto: wdv4758h/sage
    def weight_distribution(self):
        r"""
        Returns the list whose `i`'th entry is the number of words of weight `i`
        in ``self``.

        Computing the weight distribution for a GRS code is very fast. Note that
        for random linear codes, it is computationally hard.

        EXAMPLES::

            sage: F = GF(11)
            sage: n, k = 10, 5
            sage: C = codes.GeneralizedReedSolomonCode(F.list()[:n], k)
            sage: C.weight_distribution()
            [1, 0, 0, 0, 0, 0, 2100, 6000, 29250, 61500, 62200]
        """
        d = self.minimum_distance()
        n = self.length()
        q = self.base_ring().order()
        s = var('s')
        wd = [1] + [0] * (d - 1)
        for i in range(d, n + 1):
            tmp = binomial(n, i) * (q - 1)
            wd.append(tmp * symbolic_sum(
                binomial(i - 1, s) * (-1)**s * q**(i - d - s), s, 0, i - d))
        return wd
Ejemplo n.º 2
0
def greedy_coefficient(self, d_vector, p, q):
    b = abs(self._B0[0, 1])
    c = abs(self._B0[1, 0])
    a1 = d_vector[0]
    a2 = d_vector[1]
    p = Integer(p)
    q = Integer(q)
    if p == 0 and q == 0:
        return 1
    sum1 = 0
    for k in range(1, p + 1):
        bin = 0
        if a2 - c * q + k - 1 >= k:
            bin = binomial(a2 - c * q + k - 1, k)
        sum1 += (-1)**(k - 1) * self.greedy_coefficient(d_vector, p - k,
                                                        q) * bin
    sum2 = 0
    for l in range(1, q + 1):
        bin = 0
        if a1 - b * p + l - 1 >= l:
            bin = binomial(a1 - b * p + l - 1, l)
        sum2 += (-1)**(l - 1) * self.greedy_coefficient(d_vector, p,
                                                        q - l) * bin
    #print "sum1=",sum1,"sum2=",sum2
    return max(sum1, sum2)
Ejemplo n.º 3
0
    def weight_distribution(self):
        r"""
        Returns the list whose `i`'th entry is the number of words of weight `i`
        in ``self``.

        Computing the weight distribution for a GRS code is very fast. Note that
        for random linear codes, it is computationally hard.

        EXAMPLES::

            sage: F = GF(11)
            sage: n, k = 10, 5
            sage: C = codes.GeneralizedReedSolomonCode(F.list()[:n], k)
            sage: C.weight_distribution()
            [1, 0, 0, 0, 0, 0, 2100, 6000, 29250, 61500, 62200]
        """
        d = self.minimum_distance()
        n = self.length()
        q = self.base_ring().order()
        s = var('s')
        wd = [1] + [0] * (d - 1)
        for i in range(d, n+1):
            tmp = binomial(n, i) * (q - 1)
            wd.append(tmp * symbolic_sum(binomial(i-1, s) * (-1) ** s * q ** (i - d - s), s, 0, i-d))
        return wd
Ejemplo n.º 4
0
 def cardinality(self):
     if self._max_deg == Infinity:
         return Infinity
     else:
         n = self._poly_ring.ngens()
         k1, k2 = self._min_deg, self._max_deg
         return binomial(n + k2, n) - binomial(n + k1 - 1, n)
Ejemplo n.º 5
0
    def _b_power_k_r(self, k, r):
        r"""
        An expression involving moebius inversion in the powersum generators.

        For a positive value of ``k``, this expression is

        .. MATH::

            \sum_{j=0}^r (-1)^{r-j}k^j\binom{r,j} \left(
            \frac{1}{k} \sum_{d|k} \mu(d/k) p_d \right)_k.

        INPUT:

        - ``k``, ``r`` -- positive integers

        OUTPUT:

        - an expression in the powersum basis of the symmetric functions

        EXAMPLES::

            sage: st = SymmetricFunctions(QQ).st()
            sage: st._b_power_k_r(1,1)
            -p[] + p[1]
            sage: st._b_power_k_r(2,2)
            p[] + 4*p[1] + p[1, 1] - 4*p[2] - 2*p[2, 1] + p[2, 2]
            sage: st._b_power_k_r(3,2)
            p[] + 5*p[1] + p[1, 1] - 5*p[3] - 2*p[3, 1] + p[3, 3]

        """
        p = self._p
        return p.sum( (-1)**(r-j) * k**j * binomial(r,j)
                      * p.prod(self._b_power_k(k) - i*p.one() for i in range(j))
                      for j in range(r+1) )
    def coproduct_on_basis(self, i):
        """
        The coproduct of a basis element.

        .. MATH::

            \Delta(P_i) = \sum_{j=0}^i P_{i-j} \otimes P_j

        INPUT:

        - ``i`` -- a non-negative integer

        OUTPUT:

        - an element of the tensor square of ``self``

        TESTS::

            sage: H = GradedHopfAlgebrasWithBasis(QQ).Connected().example()
            sage: H.monomial(3).coproduct()
            P0 # P3 + 3*P1 # P2 + 3*P2 # P1 + P3 # P0

        """
        return self.sum_of_terms(
            ((i-j, j), binomial(i, j))
            for j in range(i+1)
        )
    def coproduct_on_basis(self, i):
        """
        The coproduct of a basis element.

        .. MATH::

            \Delta(P_i) = \sum_{j=0}^i P_{i-j} \otimes P_j

        INPUT:

        - ``i`` -- a non-negative integer

        OUTPUT:

        - an element of the tensor square of ``self``

        TESTS::

            sage: H = GradedHopfAlgebrasWithBasis(QQ).Connected().example()
            sage: H.monomial(3).coproduct()
            P0 # P3 + 3*P1 # P2 + 3*P2 # P1 + P3 # P0

        """
        return self.sum_of_terms(
            ((i - j, j), binomial(i, j)) for j in range(i + 1))
Ejemplo n.º 8
0
    def __init__(self, fmodule, degree, name=None, latex_name=None):
        r"""
        TESTS::

            sage: from sage.tensor.modules.ext_pow_free_module import ExtPowerFreeModule
            sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
            sage: e = M.basis('e')
            sage: A = ExtPowerFreeModule(M, 2) ; A
            2nd exterior power of the Rank-3 free module M over the
             Integer Ring
            sage: TestSuite(A).run()

        """
        from sage.functions.other import binomial
        self._fmodule = fmodule
        self._degree = ZZ(degree)
        rank = binomial(fmodule._rank, degree)
        if name is None and fmodule._name is not None:
            name = r'/\^{}('.format(degree) + fmodule._name + ')'
        if latex_name is None and fmodule._latex_name is not None:
            latex_name = r'\Lambda^{' + str(degree) + r'}\left(' + \
                                       fmodule._latex_name + r'\right)'
        FiniteRankFreeModule.__init__(
            self,
            fmodule._ring,
            rank,
            name=name,
            latex_name=latex_name,
            start_index=fmodule._sindex,
            output_formatter=fmodule._output_formatter)
        fmodule._all_modules.add(self)
Ejemplo n.º 9
0
    def _b_power_k_r(self, k, r):
        r"""
        An expression involving Moebius inversion in the powersum generators.

        For a positive value of ``k``, this expression is

        .. MATH::

            \sum_{j=0}^r (-1)^{r-j}k^j\binom{r,j} \left(
            \frac{1}{k} \sum_{d|k} \mu(d/k) p_d \right)_k.

        INPUT:

        - ``k``, ``r`` -- positive integers

        OUTPUT:

        - an expression in the powersum basis of the symmetric functions

        EXAMPLES::

            sage: st = SymmetricFunctions(QQ).st()
            sage: st._b_power_k_r(1,1)
            -p[] + p[1]
            sage: st._b_power_k_r(2,2)
            p[] + 4*p[1] + p[1, 1] - 4*p[2] - 2*p[2, 1] + p[2, 2]
            sage: st._b_power_k_r(3,2)
            p[] + 5*p[1] + p[1, 1] - 5*p[3] - 2*p[3, 1] + p[3, 3]

        """
        p = self._p
        return p.sum(
            (-1)**(r - j) * k**j * binomial(r, j) *
            p.prod(self._b_power_k(k) - i * p.one() for i in range(j))
            for j in range(r + 1))
Ejemplo n.º 10
0
    def __init__(self, fmodule, degree, name=None, latex_name=None):
        r"""
        TESTS::

            sage: from sage.tensor.modules.ext_pow_free_module import ExtPowerFreeModule
            sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
            sage: e = M.basis('e')
            sage: A = ExtPowerFreeModule(M, 2) ; A
            2nd exterior power of the Rank-3 free module M over the
             Integer Ring
            sage: TestSuite(A).run()

        """
        from sage.functions.other import binomial
        self._fmodule = fmodule
        self._degree = degree
        rank = binomial(fmodule._rank, degree)
        if name is None and fmodule._name is not None:
            name = r'/\^{}('.format(degree) + fmodule._name + ')'
        if latex_name is None and fmodule._latex_name is not None:
            latex_name = r'\Lambda^{' + str(degree) + r'}\left(' + \
                                       fmodule._latex_name + r'\right)'
        FiniteRankFreeModule.__init__(self, fmodule._ring, rank,
                                      name=name, latex_name=latex_name,
                                      start_index=fmodule._sindex,
                             output_formatter=fmodule._output_formatter)
        # Unique representation:
        if self._degree == 1 or \
           self._degree in self._fmodule._exterior_powers:
            raise ValueError("the {}th exterior power of ".format(degree) +
                             "{}".format(self._fmodule) +
                             " has already been created")
        else:
            self._fmodule._exterior_powers[self._degree] = self
Ejemplo n.º 11
0
            def f(partition):
                n = 0
                m = 1
                for part in partition:
                    n += part
                    m *= q**binomial(part, 2) / q_factorial(part, q=q)

                return t**n * m
Ejemplo n.º 12
0
 def cx_n_a(self, n, a, c=1):
     if n == 0:
         return OrePolynomial1(self._parent, [c * a])
     res = OrePolynomial1(self._parent, [c * a]).px_n(n)
     for i in range(1, n + 1):
         a = self._parent._derivation(a)
         temp = OrePolynomial1(self._parent,
                               [c * binomial(n, i) * a]).px_n(n - i)
         res = res + temp
     return res
Ejemplo n.º 13
0
 def eqs_affine(x0, y0):
     r"""
     Make equation for the affine point x0, y0. Return a list of
     equations, each equation being a list of coefficients corresponding to
     the monomials in ``monomials``.
     """
     eqs = []
     for i in range(0, s):
         for j in range(0, s - i):
             eq = dict()
             for monomial in monomials:
                 ihat = monomial[0]
                 jhat = monomial[1]
                 if ihat >= i and jhat >= j:
                     icoeff = binomial(ihat, i) * x0**(ihat-i) \
                                 if ihat > i else 1
                     jcoeff = binomial(jhat, j) * y0**(jhat-j) \
                                 if jhat > j else 1
                     eq[monomial] = jcoeff * icoeff
             eqs.append([eq.get(monomial, 0) for monomial in monomials])
     return eqs
Ejemplo n.º 14
0
    def cardinality(self):
        r"""
        Return the cardinality of ``self``.

        EXAMPLES::

            sage: from sage.combinat.blob_algebra import BlobDiagrams
            sage: BD4 = BlobDiagrams(4)
            sage: BD4.cardinality()
            70
        """
        return binomial(2*self._n, self._n)
Ejemplo n.º 15
0
 def eqs_affine(x0, y0):
     r"""
     Make equation for the affine point x0, y0. Return a list of
     equations, each equation being a list of coefficients corresponding to
     the monomials in ``monomials``.
     """
     eqs = []
     for i in range(s):
         for j in range(s - i):
             eq = dict()
             for monomial in monomials:
                 ihat = monomial[0]
                 jhat = monomial[1]
                 if ihat >= i and jhat >= j:
                     icoeff = binomial(ihat, i) * x0**(ihat-i) \
                                 if ihat > i else 1
                     jcoeff = binomial(jhat, j) * y0**(jhat-j) \
                                 if jhat > j else 1
                     eq[monomial] = jcoeff * icoeff
             eqs.append([eq.get(monomial, 0) for monomial in monomials])
     return eqs
Ejemplo n.º 16
0
    def __init__(self, fmodule, degree, name=None, latex_name=None):
        r"""
        TESTS::

            sage: from sage.tensor.modules.ext_pow_free_module import ExtPowerDualFreeModule
            sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
            sage: e = M.basis('e')
            sage: A = ExtPowerDualFreeModule(M, 2) ; A
            2nd exterior power of the dual of the Rank-3 free module M over
             the Integer Ring
            sage: TestSuite(A).run()

        """
        from sage.functions.other import binomial
        self._fmodule = fmodule
        self._degree = degree
        rank = binomial(fmodule._rank, degree)
        self._zero_element = 0  # provisory (to avoid infinite recursion in what
        # follows)
        if degree == 1:  # case of the dual
            if name is None and fmodule._name is not None:
                name = fmodule._name + '*'
            if latex_name is None and fmodule._latex_name is not None:
                latex_name = fmodule._latex_name + r'^*'
        else:
            if name is None and fmodule._name is not None:
                name = r'/\^{}('.format(degree) + fmodule._name + '*)'
            if latex_name is None and fmodule._latex_name is not None:
                latex_name = r'\Lambda^{' + str(degree) + r'}\left(' + \
                             fmodule._latex_name + r'^*\right)'
        FiniteRankFreeModule.__init__(
            self,
            fmodule._ring,
            rank,
            name=name,
            latex_name=latex_name,
            start_index=fmodule._sindex,
            output_formatter=fmodule._output_formatter)
        # Unique representation:
        if self._degree in self._fmodule._dual_exterior_powers:
            raise ValueError("the {}th exterior power of ".format(degree) +
                             "the dual of {}".format(self._fmodule) +
                             " has already been created")
        else:
            self._fmodule._dual_exterior_powers[self._degree] = self
        # Zero element
        self._zero_element = self._element_constructor_(name='zero',
                                                        latex_name='0')
        for basis in self._fmodule._known_bases:
            self._zero_element._components[basis] = \
                                            self._zero_element._new_comp(basis)
Ejemplo n.º 17
0
def greedy_coefficient(self,d_vector,p,q):
    b = abs(self._B0[0,1])
    c = abs(self._B0[1,0])
    a1 = d_vector[0]
    a2 = d_vector[1]
    p = Integer(p)
    q = Integer(q)
    if p == 0 and q == 0:
        return 1
    sum1 = 0
    for k in range(1,p+1):
        bin = 0
        if a2-c*q+k-1 >= k:
            bin = binomial(a2-c*q+k-1,k)
        sum1 += (-1)**(k-1)*self.greedy_coefficient(d_vector,p-k,q)*bin
    sum2 = 0
    for l in range(1,q+1):
        bin = 0
        if a1-b*p+l-1 >= l:
            bin = binomial(a1-b*p+l-1,l)
        sum2 += (-1)**(l-1)*self.greedy_coefficient(d_vector,p,q-l)*bin
    #print "sum1=",sum1,"sum2=",sum2
    return max(sum1,sum2)
Ejemplo n.º 18
0
    def __init__(self, fmodule, degree, name=None, latex_name=None):
        r"""
        TESTS::

            sage: from sage.tensor.modules.ext_pow_free_module import ExtPowerDualFreeModule
            sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
            sage: e = M.basis('e')
            sage: A = ExtPowerDualFreeModule(M, 2) ; A
            2nd exterior power of the dual of the Rank-3 free module M over
             the Integer Ring
            sage: TestSuite(A).run()

        """
        from sage.functions.other import binomial
        self._fmodule = fmodule
        self._degree = degree
        rank = binomial(fmodule._rank, degree)
        self._zero_element = 0 # provisory (to avoid infinite recursion in what
                               # follows)
        if degree == 1:  # case of the dual
            if name is None and fmodule._name is not None:
                name = fmodule._name + '*'
            if latex_name is None and fmodule._latex_name is not None:
                latex_name = fmodule._latex_name + r'^*'
        else:
            if name is None and fmodule._name is not None:
                name = '/\^{}('.format(degree) + fmodule._name + '*)'
            if latex_name is None and fmodule._latex_name is not None:
                latex_name = r'\Lambda^{' + str(degree) + r'}\left(' + \
                             fmodule._latex_name + r'^*\right)'
        FiniteRankFreeModule.__init__(self, fmodule._ring, rank, name=name,
                                      latex_name=latex_name,
                                      start_index=fmodule._sindex,
                                    output_formatter=fmodule._output_formatter)
        # Unique representation:
        if self._degree in self._fmodule._dual_exterior_powers:
            raise ValueError("the {}th exterior power of ".format(degree) +
                             "the dual of {}".format(self._fmodule) +
                             " has already been created")
        else:
            self._fmodule._dual_exterior_powers[self._degree] = self
        # Zero element
        self._zero_element = self._element_constructor_(name='zero',
                                                        latex_name='0')
        for basis in self._fmodule._known_bases:
            self._zero_element._components[basis] = \
                                            self._zero_element._new_comp(basis)
Ejemplo n.º 19
0
def _real_or_imaginary_part_of_power_of_complex_number(n, start):
    """
    Let z = x + y * I.
    If start = 0, return Re(z^n). If start = 1, return Im(z^n).
    The result is a sage symbolic expression in x and y with rational
    coefficients.
    """

    # By binomial theorem, we have
    #
    #               n       n        n       n    n-i    i
    #   (x + y * I)   = sum       (     ) * I  * x    * y
    #                     i = 0      i
    #
    # The real/imaginary part consists of all even/odd terms in the sum:
    return sum([
        binomial(n, i) * (-1) ** (i/2) * var('x') ** (n - i) * var('y') ** i
        for i in range(start, n + 1, 2)])
Ejemplo n.º 20
0
    def probability_of_exactly_t_errors(self, t):
        r"""
        Returns the probability ``self`` has to return
        exactly ``t`` errors.

        INPUT:

        - ``t`` -- an integer

        EXAMPLES::

            sage: epsilon = 0.3
            sage: Chan = channels.QarySymmetricChannel(GF(59)^50, epsilon)
            sage: Chan.probability_of_exactly_t_errors(15)
            0.122346861835401
        """
        n = self.input_space().dimension()
        epsilon = self.error_probability()
        return binomial(n, t) * epsilon**t * (1-epsilon)**(n-t)
Ejemplo n.º 21
0
    def __init__(self, base_field, order, num_of_var):
        r"""
        TESTS:

        Note that the order given cannot be greater than (q-1). An error is raised if that happens::

            sage: from sage.coding.reed_muller_code import QAryReedMullerCode
            sage: C = QAryReedMullerCode(GF(3), 4, 4)
            Traceback (most recent call last):
            ...
            ValueError: The order must be less than 3

        The order and the number of variable must be integers::

            sage: C = QAryReedMullerCode(GF(3),1.1,4)
            Traceback (most recent call last):
            ...
            ValueError: The order of the code must be an integer

        The base_field parameter must be a finite field::

            sage: C = QAryReedMullerCode(QQ,1,4)
            Traceback (most recent call last):
            ...
            ValueError: the input `base_field` must be a FiniteField
        """
        # input sanitization
        if not (base_field in FiniteFields):
            raise ValueError("the input `base_field` must be a FiniteField")
        if not (isinstance(order, (Integer, int))):
            raise ValueError("The order of the code must be an integer")
        if not (isinstance(num_of_var, (Integer, int))):
            raise ValueError("The number of variables must be an integer")
        q = base_field.cardinality()
        if (order >= q):
            raise ValueError("The order must be less than %s" % q)

        super(QAryReedMullerCode,
              self).__init__(base_field, q**num_of_var, "EvaluationVector",
                             "Syndrome")
        self._order = order
        self._num_of_var = num_of_var
        self._dimension = binomial(num_of_var + order, order)
Ejemplo n.º 22
0
    def probability_of_exactly_t_errors(self, t):
        r"""
        Returns the probability ``self`` has to return
        exactly ``t`` errors.

        INPUT:

        - ``t`` -- an integer

        EXAMPLES::

            sage: epsilon = 0.3
            sage: Chan = channels.QarySymmetricChannel(GF(59)^50, epsilon)
            sage: Chan.probability_of_exactly_t_errors(15)
            0.122346861835401
        """
        n = self.input_space().dimension()
        epsilon = self.error_probability()
        return binomial(n, t) * epsilon**t * (1-epsilon)**(n-t)
Ejemplo n.º 23
0
    def dimension(self):
        r"""
        Return the dimension of ``self``.

        The dimension of the Schur algebra `S_R(n, r)` is

        .. MATH::

            \dim S_R(n,r) = \binom{n^2+r-1}{r}.

        EXAMPLES::

            sage: S = SchurAlgebra(QQ, 4, 2)
            sage: S.dimension()
            136
            sage: S = SchurAlgebra(QQ, 2, 4)
            sage: S.dimension()
            35
        """
        return binomial(self._n ** 2 + self._r - 1, self._r)
Ejemplo n.º 24
0
    def dimension(self):
        r"""
        Return the dimension of ``self``.

        The dimension of the Schur algebra `S_R(n, r)` is

        .. MATH::

            \dim S_R(n,r) = \binom{n^2+r-1}{r}.

        EXAMPLES::

            sage: S = SchurAlgebra(QQ, 4, 2)
            sage: S.dimension()
            136
            sage: S = SchurAlgebra(QQ, 2, 4)
            sage: S.dimension()
            35
        """
        return binomial(self._n**2 + self._r - 1, self._r)
Ejemplo n.º 25
0
    def __init__(self, base_field, order, num_of_var):
        r"""
        TESTS:

        Note that the order given cannot be greater than (q-1). An error is raised if that happens::

            sage: from sage.coding.reed_muller_code import QAryReedMullerCode
            sage: C = QAryReedMullerCode(GF(3), 4, 4)
            Traceback (most recent call last):
            ...
            ValueError: The order must be less than 3

        The order and the number of variable must be integers::

            sage: C = QAryReedMullerCode(GF(3),1.1,4)
            Traceback (most recent call last):
            ...
            ValueError: The order of the code must be an integer

        The base_field parameter must be a finite field::

            sage: C = QAryReedMullerCode(QQ,1,4)
            Traceback (most recent call last):
            ...
            ValueError: the input `base_field` must be a FiniteField
        """
        # input sanitization
        if not(base_field in FiniteFields):
            raise ValueError("the input `base_field` must be a FiniteField")
        if not(isinstance(order, (Integer, int))):
            raise ValueError("The order of the code must be an integer")
        if not(isinstance(num_of_var, (Integer, int))):
            raise ValueError("The number of variables must be an integer")
        q = base_field.cardinality()
        if (order >= q):
            raise ValueError("The order must be less than %s" % q)

        super(QAryReedMullerCode,self).__init__(base_field, q**num_of_var, "EvaluationVector", "Syndrome")
        self._order = order
        self._num_of_var = num_of_var
        self._dimension = binomial(num_of_var + order, order)
Ejemplo n.º 26
0
 def roth_rec(Q, lam, k):
     r"""
     Recursion of the root finding:
     Q is the remaining poly, lam is the power of x whose coefficient we are
     to determine now, and k is the remaining precision to handle (if ``precision`` is given)
     """
     if precision and k <= 0:
         solutions.append((Rx(g[:lam]), lam))
         return
     (T, strip) = _strip_x_pows(Q)
     if precision:
         k = k - strip
     Ty = Rx([p[0] for p in T])
     if Ty.is_zero() or (precision and k <= 0):
         if precision:
             solutions.append((Rx(g[:lam]), lam))
         else:
             solutions.append(Rx(g[:lam]))
         return
     roots = Ty.roots(multiplicities=False)
     for gamma in roots:
         g[lam] = gamma
         if lam < maxd:
             # Construct T(y=x*y + gamma)
             ell = len(T) - 1
             yc = [[
                 binomial(s, t) * x**t * gamma**(s - t)
                 for t in range(s + 1)
             ] for s in range(ell + 1)]
             Tg = []
             for t in range(ell + 1):
                 Tg.append(sum(yc[s][t] * T[s] for s in range(t, ell + 1)))
             roth_rec(Tg, lam + 1, k)
         else:
             if precision:
                 solutions.append((Rx(g[:lam + 1]), lam + 1))
             elif sum(Q[t] * gamma**t for t in range(len(Q))).is_zero():
                 solutions.append(Rx(g[:lam + 1]))
     return
Ejemplo n.º 27
0
    def eval_formula(self, n, x):
        """
        Evaluate ``chebyshev_U`` using an explicit formula.
        See [ASHandbook]_ 227 (p. 782) for details on the recurions.
        See also [EffCheby]_ for the recursion formulas.

        INPUT:

        - ``n`` -- an integer

        - ``x`` -- a value to evaluate the polynomial at (this can be
          any ring element)

        EXAMPLES::

            sage: chebyshev_U.eval_formula(10, x)
            1024*x^10 - 2304*x^8 + 1792*x^6 - 560*x^4 + 60*x^2 - 1
            sage: chebyshev_U.eval_formula(-2, x)
            -1
            sage: chebyshev_U.eval_formula(-1, x)
            0
            sage: chebyshev_U.eval_formula(0, x)
            1
            sage: chebyshev_U.eval_formula(1, x)
            2*x
            sage: chebyshev_U.eval_formula(2,0.1) == chebyshev_U._evalf_(2,0.1)
            True
        """
        if n < -1:
            return -self.eval_formula(-n - 2, x)

        res = parent(x).zero()
        for j in xrange(0, n // 2 + 1):
            f = binomial(n - j, j)
            res += (-1)**j * (2 * x)**(n - 2 * j) * f
        return res
Ejemplo n.º 28
0
 def roth_rec(Q, lam, k):
     r"""
     Recursion of the root finding:
     Q is the remaining poly, lam is the power of x whose coefficient we are
     to determine now, and k is the remaining precision to handle (if ``precision`` is given)
     """
     if precision and k <= 0:
         solutions.append((Rx(g[:lam]), lam))
         return
     (T, strip) = _strip_x_pows(Q)
     if precision:
         k = k - strip
     Ty = Rx([ p[0] for p in T ])
     if Ty.is_zero() or (precision and k <= 0):
         if precision:
             solutions.append((Rx(g[:lam]), lam))
         else:
             solutions.append(Rx(g[:lam]))
         return
     roots = Ty.roots(multiplicities=False)
     for gamma in roots:
         g[lam] = gamma
         if lam<maxd:
             # Construct T(y=x*y + gamma)
             ell = len(T)-1
             yc = [[binomial(s, t) * x**t * gamma**(s-t) for t in range(s+1)] for s in range(ell+1)]
             Tg = []
             for t in range(ell+1):
                 Tg.append(sum(yc[s][t] * T[s] for s in range(t, ell+1)))
             roth_rec(Tg , lam+1, k)
         else:
             if precision:
                 solutions.append((Rx(g[:lam+1]), lam+1))
             elif sum( Q[t] * gamma**t for t in range(len(Q)) ).is_zero():
                 solutions.append(Rx(g[:lam+1]))
     return
Ejemplo n.º 29
0
    def eval_formula(self, n, x):
        """
        Evaluate ``chebyshev_U`` using an explicit formula.
        See [ASHandbook]_ 227 (p. 782) for details on the recurions.
        See also [EffCheby]_ for the recursion formulas.

        INPUT:

        - ``n`` -- an integer

        - ``x`` -- a value to evaluate the polynomial at (this can be
          any ring element)

        EXAMPLES::

            sage: chebyshev_U.eval_formula(10, x)
            1024*x^10 - 2304*x^8 + 1792*x^6 - 560*x^4 + 60*x^2 - 1
            sage: chebyshev_U.eval_formula(-2, x)
            -1
            sage: chebyshev_U.eval_formula(-1, x)
            0
            sage: chebyshev_U.eval_formula(0, x)
            1
            sage: chebyshev_U.eval_formula(1, x)
            2*x
            sage: chebyshev_U.eval_formula(2,0.1) == chebyshev_U._evalf_(2,0.1)
            True
        """
        if n < -1:
            return -self.eval_formula(-n - 2, x)

        res = parent(x).zero()
        for j in xrange(0, n // 2 + 1):
            f = binomial(n - j, j)
            res += (-1) ** j * (2 * x) ** (n - 2 * j) * f
        return res
Ejemplo n.º 30
0
def number_of_partial_injection(n, algorithm='binomial'):
    r"""
    Return the number of partial injections on an set of `n` elements
    defined on a subset of `k` elements for each `k` in `0, 1, ..., n`.

    INPUT:

    - ``n`` -- integer
    - ``algorithm`` -- string (default: ``'binomial'``), ``'binomial'``
      or ``'recursive'``. When n>50, the binomial coefficient approach is
      faster (linear time vs quadratic time).

    OUTPUT:

        list

    .. NOTE::

        The recursive code of this function was originally written by
        Vincent Delecroix (Nov 30, 2017) the day after a discussion with
        Pascal Weil and me at LaBRI.

    EXAMPLES::

        sage: from slabbe import number_of_partial_injection
        sage: number_of_partial_injection(0)
        [1]
        sage: number_of_partial_injection(1)
        [1, 1]
        sage: number_of_partial_injection(2)
        [1, 4, 2]
        sage: number_of_partial_injection(3)
        [1, 9, 18, 6]
        sage: number_of_partial_injection(4)
        [1, 16, 72, 96, 24]
        sage: number_of_partial_injection(5)
        [1, 25, 200, 600, 600, 120]
        sage: number_of_partial_injection(6)
        [1, 36, 450, 2400, 5400, 4320, 720]
        sage: number_of_partial_injection(7)
        [1, 49, 882, 7350, 29400, 52920, 35280, 5040]
        sage: number_of_partial_injection(8)
        [1, 64, 1568, 18816, 117600, 376320, 564480, 322560, 40320]

    TESTS::

        sage: number_of_partial_injection(8, algorithm='recursive')
        [1, 64, 1568, 18816, 117600, 376320, 564480, 322560, 40320]

    REFERENCE:

        https://oeis.org/A144084
    """
    if algorithm == 'binomial':
        return [binomial(n,k)**2*factorial(k) for k in range(n+1)]
    elif algorithm == 'recursive':
        L = [ZZ(1)]
        for t in range(1, n+1):
            L.append(t * L[-1])
            for k in range(t-1, 0, -1):
                L[k] = (t * L[k]) // (t-k) + t * L[k-1]
        return L
def _compute_sw_spherical_harm(s,
                               l,
                               m,
                               theta,
                               phi,
                               condon_shortley=True,
                               numerical=None):
    r"""
    Compute the spin-weighted spherical harmonic of spin weight ``s`` and
    indices ``(l,m)`` as a callable symbolic expression in (theta,phi)

    INPUT:

    - ``s`` -- integer; the spin weight
    - ``l`` -- non-negative integer; the harmonic degree
    - ``m`` -- integer within the range ``[-l, l]``; the azimuthal number
    - ``theta`` -- colatitude angle
    - ``phi`` -- azimuthal angle
    - ``condon_shortley`` -- (default: ``True``) determines whether the
      Condon-Shortley phase of `(-1)^m` is taken into account (see below)
    - ``numerical`` -- (default: ``None``) determines whether a symbolic or
      a numerical computation of a given type is performed; allowed values are

      - ``None``: a symbolic computation is performed
      - ``RDF``: Sage's machine double precision floating-point numbers
        (``RealDoubleField``)
      - ``RealField(n)``, where ``n`` is a number of bits: Sage's
        floating-point numbers with an arbitrary precision; note that ``RR`` is
        a shortcut for ``RealField(53)``.
      - ``float``: Python's floating-point numbers


    OUTPUT:

    - `{}_s Y_l^m(\theta,\phi)` either

      - as a symbolic expression if ``numerical`` is ``None``
      - or a pair of floating-point numbers, each of them being of the type
        corresponding to ``numerical`` and representing respectively the
        real and imaginary parts of `{}_s Y_l^m(\theta,\phi)`

    ALGORITHM:

    The spin-weighted spherical harmonic is evaluated according to Eq. (3.1)
    of J. N. Golberg et al., J. Math. Phys. **8**, 2155 (1967)
    [:doi:`10.1063/1.1705135`], with an extra `(-1)^m` factor (the so-called
    *Condon-Shortley phase*) if ``condon_shortley`` is ``True``, the actual
    formula being then the one given in
    :wikipedia:`Spin-weighted_spherical_harmonics#Calculating`

    TESTS::

        sage: from kerrgeodesic_gw.spin_weighted_spherical_harm import _compute_sw_spherical_harm
        sage: theta, phi = var("theta phi")
        sage: _compute_sw_spherical_harm(-2, 2, 1, theta, phi)
        1/4*(sqrt(5)*cos(theta) + sqrt(5))*e^(I*phi)*sin(theta)/sqrt(pi)

    """
    if abs(s) > l:
        return ZZ(0)
    if abs(theta) < 1.e-6:  # TODO: fix the treatment of small theta values
        if theta < 0:  #       possibly with exact formula for theta=0
            theta = -1.e-6  #
        else:  #
            theta = 1.e-6  #
    cott2 = cos(theta / 2) / sin(theta / 2)
    res = 0
    for r in range(l - s + 1):
        res += (-1)**(l - r - s) * (binomial(l - s, r) * binomial(
            l + s, r + s - m) * cott2**(2 * r + s - m))
    res *= sin(theta / 2)**(2 * l)
    ff = factorial(l + m) * factorial(l - m) * (2 * l + 1) / (
        factorial(l + s) * factorial(l - s))
    if numerical:
        pre = sqrt(numerical(ff) / numerical(pi)) / 2
    else:
        pre = sqrt(ff) / (2 * sqrt(pi))
    res *= pre
    if condon_shortley:
        res *= (-1)**m
    if numerical:
        return (numerical(res * cos(m * phi)), numerical(res * sin(m * phi)))
    # Symbolic case:
    res = res.simplify_full()
    res = res.reduce_trig()  # get rid of cos(theta/2) and sin(theta/2)
    res = res.simplify_trig()  # further trigonometric simplifications
    res *= exp(I * m * phi)
    return res
    def SingularityAnalysis(var,
                            zeta=1,
                            alpha=0,
                            beta=0,
                            delta=0,
                            precision=None,
                            normalized=True):
        r"""
        Return the asymptotic expansion of the coefficients of
        an power series with specified pole and logarithmic singularity.

        More precisely, this extracts the `n`-th coefficient

        .. MATH::

            [z^n] \left(\frac{1}{1-z/\zeta}\right)^\alpha
            \left(\frac{1}{z/\zeta} \log \frac{1}{1-z/\zeta}\right)^\beta
            \left(\frac{1}{z/\zeta} \log
            \left(\frac{1}{z/\zeta} \log \frac{1}{1-z/\zeta}\right)\right)^\delta

        (if ``normalized=True``, the default) or

        .. MATH::

            [z^n] \left(\frac{1}{1-z/\zeta}\right)^\alpha
            \left(\log \frac{1}{1-z/\zeta}\right)^\beta
            \left(\log
            \left(\frac{1}{z/\zeta} \log \frac{1}{1-z/\zeta}\right)\right)^\delta

        (if ``normalized=False``).

        INPUT:

        - ``var`` -- a string for the variable name.

        - ``zeta`` -- (default: `1`) the location of the singularity.

        - ``alpha`` -- (default: `0`) the pole order of the singularty.

        - ``beta`` -- (default: `0`) the order of the logarithmic singularity.

        - ``delta`` -- (default: `0`) the order of the log-log singularity.
          Not yet implemented for ``delta != 0``.

        - ``precision`` -- (default: ``None``) an integer. If ``None``, then
          the default precision of the asymptotic ring is used.

        - ``normalized`` -- (default: ``True``) a boolean, see above.

        OUTPUT:

        An asymptotic expansion.

        EXAMPLES::

            sage: asymptotic_expansions.SingularityAnalysis('n', alpha=1)
            1
            sage: asymptotic_expansions.SingularityAnalysis('n', alpha=2)
            n + 1
            sage: asymptotic_expansions.SingularityAnalysis('n', alpha=3)
            1/2*n^2 + 3/2*n + 1
            sage: _.parent()
            Asymptotic Ring <n^ZZ> over Rational Field

        ::

            sage: asymptotic_expansions.SingularityAnalysis('n', alpha=-3/2,
            ....:     precision=3)
            3/4/sqrt(pi)*n^(-5/2)
            + 45/32/sqrt(pi)*n^(-7/2)
            + 1155/512/sqrt(pi)*n^(-9/2)
            + O(n^(-11/2))
            sage: asymptotic_expansions.SingularityAnalysis('n', alpha=-1/2,
            ....:     precision=3)
            -1/2/sqrt(pi)*n^(-3/2)
            - 3/16/sqrt(pi)*n^(-5/2)
            - 25/256/sqrt(pi)*n^(-7/2)
            + O(n^(-9/2))
            sage: asymptotic_expansions.SingularityAnalysis('n', alpha=1/2,
            ....:     precision=4)
            1/sqrt(pi)*n^(-1/2)
            - 1/8/sqrt(pi)*n^(-3/2)
            + 1/128/sqrt(pi)*n^(-5/2)
            + 5/1024/sqrt(pi)*n^(-7/2)
            + O(n^(-9/2))
            sage: _.parent()
            Asymptotic Ring <n^QQ> over Symbolic Constants Subring

        ::

            sage: S = SR.subring(rejecting_variables=('n',))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=S.var('a'),
            ....:     precision=4).map_coefficients(lambda c: c.factor())
            1/gamma(a)*n^(a - 1)
            + (1/2*(a - 1)*a/gamma(a))*n^(a - 2)
            + (1/24*(3*a - 1)*(a - 1)*(a - 2)*a/gamma(a))*n^(a - 3)
            + (1/48*(a - 1)^2*(a - 2)*(a - 3)*a^2/gamma(a))*n^(a - 4)
            + O(n^(a - 5))
            sage: _.parent()
            Asymptotic Ring <n^(Symbolic Subring rejecting the variable n)>
            over Symbolic Subring rejecting the variable n

        ::

            sage: ae = asymptotic_expansions.SingularityAnalysis('n',
            ....:          alpha=1/2, beta=1, precision=4); ae
            1/sqrt(pi)*n^(-1/2)*log(n) + ((euler_gamma + 2*log(2))/sqrt(pi))*n^(-1/2)
            - 5/8/sqrt(pi)*n^(-3/2)*log(n) + (1/8*(3*euler_gamma + 6*log(2) - 8)/sqrt(pi)
            - (euler_gamma + 2*log(2) - 2)/sqrt(pi))*n^(-3/2) + O(n^(-5/2)*log(n))
            sage: n = ae.parent().gen()
            sage: ae.subs(n=n-1).map_coefficients(lambda x: x.canonicalize_radical())
            1/sqrt(pi)*n^(-1/2)*log(n)
            + ((euler_gamma + 2*log(2))/sqrt(pi))*n^(-1/2)
            - 1/8/sqrt(pi)*n^(-3/2)*log(n)
            + (-1/8*(euler_gamma + 2*log(2))/sqrt(pi))*n^(-3/2)
            + O(n^(-5/2)*log(n))

        ::

            sage: asymptotic_expansions.SingularityAnalysis('n',
            ....:     alpha=1, beta=1/2, precision=4)
            log(n)^(1/2) + 1/2*euler_gamma*log(n)^(-1/2)
            + (-1/8*euler_gamma^2 + 1/48*pi^2)*log(n)^(-3/2)
            + (1/16*euler_gamma^3 - 1/32*euler_gamma*pi^2 + 1/8*zeta(3))*log(n)^(-5/2)
            + O(log(n)^(-7/2))

        ::

            sage: ae = asymptotic_expansions.SingularityAnalysis('n',
            ....:     alpha=0, beta=2, precision=14)
            sage: n = ae.parent().gen()
            sage: ae.subs(n=n-2)
            2*n^(-1)*log(n) + 2*euler_gamma*n^(-1) - n^(-2) - 1/6*n^(-3) + O(n^(-5))

        ::

            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=-1/2, beta=1, precision=2, normalized=False)
            -1/2/sqrt(pi)*n^(-3/2)*log(n)
            + (-1/2*(euler_gamma + 2*log(2) - 2)/sqrt(pi))*n^(-3/2)
            + O(n^(-5/2)*log(n))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1/2, alpha=0, beta=1, precision=3, normalized=False)
            2^n*n^(-1) + O(2^n*n^(-2))


        ALGORITHM:

        See [FS2009]_ together with the
        `errata list <http://algo.inria.fr/flajolet/Publications/AnaCombi/errata.pdf>`_.

        REFERENCES:

        .. [FS2009] Philippe Flajolet and Robert Sedgewick,
           `Analytic combinatorics <http://algo.inria.fr/flajolet/Publications/AnaCombi/book.pdf>`_.
           Cambridge University Press, Cambridge, 2009.

        TESTS::

            sage: ex = asymptotic_expansions.SingularityAnalysis('n', alpha=-1/2,
            ....:     precision=4)
            sage: n = ex.parent().gen()
            sage: coefficients = ((1-x)^(1/2)).series(
            ....:     x, 21).truncate().coefficients(x, sparse=False)
            sage: ex.compare_with_values(n,    # rel tol 1e-6
            ....:     lambda k: coefficients[k], [5, 10, 20])
            [(5, 0.015778873294?), (10, 0.01498952777?), (20, 0.0146264622?)]
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=3, precision=2)
            1/2*n^2 + 3/2*n + O(1)
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=3, precision=3)
            1/2*n^2 + 3/2*n + 1
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=3, precision=4)
            1/2*n^2 + 3/2*n + 1

        ::

            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=0)
            Traceback (most recent call last):
            ...
            NotImplementedOZero: The error term in the result is O(0)
            which means 0 for sufficiently large n.
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=-1)
            Traceback (most recent call last):
            ...
            NotImplementedOZero: The error term in the result is O(0)
            which means 0 for sufficiently large n.

        ::

            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'm', alpha=-1/2, precision=3)
            -1/2/sqrt(pi)*m^(-3/2)
            - 3/16/sqrt(pi)*m^(-5/2)
            - 25/256/sqrt(pi)*m^(-7/2)
            + O(m^(-9/2))
            sage: _.parent()
            Asymptotic Ring <m^QQ> over Symbolic Constants Subring

        Location of the singularity::

            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=1, zeta=2, precision=3)
            (1/2)^n
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=1, zeta=1/2, precision=3)
            2^n
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=1, zeta=CyclotomicField(3).gen(),
            ....:      precision=3)
            (-zeta3 - 1)^n
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=4, zeta=2, precision=3)
            1/6*(1/2)^n*n^3 + (1/2)^n*n^2 + 11/6*(1/2)^n*n + O((1/2)^n)
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=-1, zeta=2, precision=3)
            Traceback (most recent call last):
            ...
            NotImplementedOZero: The error term in the result is O(0)
            which means 0 for sufficiently large n.
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=1/2, zeta=2, precision=3)
            1/sqrt(pi)*(1/2)^n*n^(-1/2) - 1/8/sqrt(pi)*(1/2)^n*n^(-3/2)
            + 1/128/sqrt(pi)*(1/2)^n*n^(-5/2) + O((1/2)^n*n^(-7/2))

        The following tests correspond to Table VI.5 in [FS2009]_. ::

            sage: A.<n> = AsymptoticRing('n^QQ * log(n)^QQ', QQ)
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=-1/2, beta=1, precision=2,
            ....:     normalized=False) * (- sqrt(pi*n^3))
            1/2*log(n) + 1/2*euler_gamma + log(2) - 1 + O(n^(-1)*log(n))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=0, beta=1, precision=3,
            ....:     normalized=False)
            n^(-1) + O(n^(-2))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=0, beta=2,  precision=14,
            ....:     normalized=False) * n
            2*log(n) + 2*euler_gamma - n^(-1) - 1/6*n^(-2) +  O(n^(-4))
            sage: (asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=1/2, beta=1, precision=4,
            ....:     normalized=False) * sqrt(pi*n)).\
            ....:     map_coefficients(lambda x: x.expand())
            log(n) + euler_gamma + 2*log(2) - 1/8*n^(-1)*log(n) +
            (-1/8*euler_gamma - 1/4*log(2))*n^(-1) + O(n^(-2)*log(n))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=1, beta=1, precision=13,
            ....:     normalized=False)
            log(n) + euler_gamma + 1/2*n^(-1) - 1/12*n^(-2) + 1/120*n^(-4)
            + O(n^(-6))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=1, beta=2, precision=4,
            ....:     normalized=False)
            log(n)^2 + 2*euler_gamma*log(n) + euler_gamma^2 - 1/6*pi^2
            + O(n^(-1)*log(n))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=3/2, beta=1, precision=3,
            ....:     normalized=False) * sqrt(pi/n)
            2*log(n) + 2*euler_gamma + 4*log(2) - 4 + 3/4*n^(-1)*log(n)
            + O(n^(-1))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=2, beta=1, precision=5,
            ....:     normalized=False)
            n*log(n) + (euler_gamma - 1)*n + log(n) + euler_gamma + 1/2
            + O(n^(-1))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=2, beta=2, precision=4,
            ....:     normalized=False) / n
            log(n)^2 + (2*euler_gamma - 2)*log(n)
            - 2*euler_gamma + euler_gamma^2 - 1/6*pi^2 + 2
            + n^(-1)*log(n)^2 + O(n^(-1)*log(n))

        Be aware that the last result does *not* coincide with [FS2009]_,
        they do have a different error term.

        Checking parameters::

            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, 1, 1/2, precision=0, normalized=False)
            Traceback (most recent call last):
            ...
            ValueError: beta and delta must be integers
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, 1, 1, 1/2, normalized=False)
            Traceback (most recent call last):
            ...
            ValueError: beta and delta must be integers

        ::

            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=0, beta=0, delta=1, precision=3)
            Traceback (most recent call last):
            ...
            NotImplementedError: not implemented for delta!=0
        """
        from itertools import islice, count
        from asymptotic_ring import AsymptoticRing
        from growth_group import ExponentialGrowthGroup, \
                MonomialGrowthGroup
        from sage.arith.all import falling_factorial
        from sage.categories.cartesian_product import cartesian_product
        from sage.functions.other import binomial, gamma
        from sage.calculus.calculus import limit
        from sage.misc.cachefunc import cached_function
        from sage.arith.srange import srange
        from sage.rings.rational_field import QQ
        from sage.rings.integer_ring import ZZ
        from sage.symbolic.ring import SR

        SCR = SR.subring(no_variables=True)
        s = SR('s')
        iga = 1 / gamma(alpha)
        if iga.parent() is SR:
            try:
                iga = SCR(iga)
            except TypeError:
                pass

        coefficient_ring = iga.parent()
        if beta != 0:
            coefficient_ring = SCR

        @cached_function
        def inverse_gamma_derivative(shift, r):
            """
            Return value of `r`-th derivative of 1/Gamma
            at alpha-shift.
            """
            if r == 0:
                result = iga * falling_factorial(alpha - 1, shift)
            else:
                result = limit((1 / gamma(s)).diff(s, r), s=alpha - shift)

            try:
                return coefficient_ring(result)
            except TypeError:
                return result

        if isinstance(alpha, int):
            alpha = ZZ(alpha)
        if isinstance(beta, int):
            beta = ZZ(beta)
        if isinstance(delta, int):
            delta = ZZ(delta)

        if precision is None:
            precision = AsymptoticRing.__default_prec__

        if not normalized and not (beta in ZZ and delta in ZZ):
            raise ValueError("beta and delta must be integers")
        if delta != 0:
            raise NotImplementedError("not implemented for delta!=0")

        groups = []
        if zeta != 1:
            groups.append(ExponentialGrowthGroup((1 / zeta).parent(), var))

        groups.append(MonomialGrowthGroup(alpha.parent(), var))
        if beta != 0:
            groups.append(
                MonomialGrowthGroup(beta.parent(), 'log({})'.format(var)))

        group = cartesian_product(groups)
        A = AsymptoticRing(growth_group=group,
                           coefficient_ring=coefficient_ring,
                           default_prec=precision)
        n = A.gen()

        if zeta == 1:
            exponential_factor = 1
        else:
            exponential_factor = n.rpow(1 / zeta)

        if beta in ZZ and beta >= 0:
            it = ((k, r) for k in count() for r in srange(beta + 1))
            k_max = precision
        else:
            it = ((0, r) for r in count())
            k_max = 0

        if beta != 0:
            log_n = n.log()
        else:
            # avoid construction of log(n)
            # because it does not exist in growth group.
            log_n = 1

        it = reversed(list(islice(it, precision + 1)))
        if normalized:
            beta_denominator = beta
        else:
            beta_denominator = 0
        L = _sa_coefficients_lambda_(max(1, k_max), beta=beta_denominator)
        (k, r) = next(it)
        result = (n**(-k) * log_n**(-r)).O()

        if alpha in ZZ and beta == 0:
            if alpha > 0 and alpha <= precision:
                result = A(0)
            elif alpha <= 0 and precision > 0:
                from misc import NotImplementedOZero
                raise NotImplementedOZero(A)

        for (k, r) in it:
            result += binomial(beta, r) * \
                sum(L[(k, ell)] * (-1)**ell *
                    inverse_gamma_derivative(ell, r)
                    for ell in srange(k, 2*k+1)
                    if (k, ell) in L) * \
                n**(-k) * log_n**(-r)

        result *= exponential_factor * n**(alpha - 1) * log_n**beta

        return result
Ejemplo n.º 33
0
        def _test_jacobi(self, **options):
            """
            Test the Jacobi axiom of this super Lie conformal algebra.

            INPUT:

            - ``options`` -- any keyword arguments acceptde by :meth:`_tester`

            EXAMPLES:

            By default, this method tests only the elements returned by
            ``self.some_elements()``::

                sage: V = lie_conformal_algebras.Affine(QQ, 'B2')
                sage: V._test_jacobi()      # long time (6 seconds)

            It works for super Lie conformal algebras too::

                sage: V = lie_conformal_algebras.NeveuSchwarz(QQ)
                sage: V._test_jacobi()

            We can use specific elements by passing the ``elements``
            keyword argument::

                sage: V = lie_conformal_algebras.Affine(QQ, 'A1', names=('e', 'h', 'f'))
                sage: V.inject_variables()
                Defining e, h, f, K
                sage: V._test_jacobi(elements=(e, 2*f+h, 3*h))

            TESTS::

                sage: wrongdict = {('a', 'a'): {0: {('b', 0): 1}}, ('b', 'a'): {0: {('a', 0): 1}}}
                sage: V = LieConformalAlgebra(QQ, wrongdict, names=('a', 'b'), parity=(1, 0))
                sage: V._test_jacobi()
                Traceback (most recent call last):
                ...
                AssertionError: {(0, 0): -3*a} != {}
                - {(0, 0): -3*a}
                + {}
            """
            tester = self._tester(**options)
            S = tester.some_elements()
            # Try our best to avoid non-homogeneous elements
            elements = []
            for s in S:
                try:
                    s.is_even_odd()
                except ValueError:
                    try:
                        elements.extend([s.even_component(), s.odd_component()])
                    except (AttributeError, ValueError):
                        pass
                    continue
                elements.append(s)
            S = elements
            from sage.misc.misc import some_tuples
            from sage.functions.other import binomial
            pz = tester._instance.zero()
            for x,y,z in some_tuples(S, 3, tester._max_runs):
                if x.is_zero() or y.is_zero():
                    sgn = 1
                elif x.is_even_odd() * y.is_even_odd():
                    sgn = -1
                else:
                    sgn = 1
                brxy = x.bracket(y)
                brxz = x.bracket(z)
                bryz = y.bracket(z)
                br1 = {k: x.bracket(v) for k,v in bryz.items()}
                br2 = {k: v.bracket(z) for k,v in brxy.items()}
                br3 = {k: y.bracket(v) for k,v in brxz.items()}
                jac1 = {(j,k): v for k in br1 for j,v in br1[k].items()}
                jac3 = {(k,j): v for k in br3 for j,v in br3[k].items()}
                jac2 = {}
                for k,br in br2.items():
                    for j,v in br.items():
                        for r in range(j+1):
                            jac2[(k+r, j-r)] = (jac2.get((k+r, j-r), pz)
                                                + binomial(k+r, r)*v)
                for k,v in jac2.items():
                    jac1[k] = jac1.get(k, pz) - v
                for k,v in jac3.items():
                    jac1[k] = jac1.get(k, pz) - sgn*v
                jacobiator = {k: v for k,v in jac1.items() if v}
                tester.assertDictEqual(jacobiator, {})
Ejemplo n.º 34
0
    def _frob_sparse(self, i, j, N0):
        r"""
        Compute `Frob(x^i y^(-j) dx ) / dx` for y^r = f(x) with N0 terms

        INPUT:

        -   ``i`` - The power of x in the expression `Frob(x^i dx/y^j) / dx`

        -   ``j`` - The (negative) power of y in the expression
                    `Frob(x^i dx/y^j) / dx`

        OUTPUT:

        ``frobij`` - a Matrix of size  (d * (N0 - 1) + ) x (N0)
                     that represents the Frobenius expansion of
                     x^i dx/y^j modulo p^(N0 + 1)

                    the entry (l, s) corresponds to the coefficient associated
                    to the monomial x**(p * (i + 1 + l) -1) * y**(p * -(j + r*s))
                    (l, s) --> (p * (i + 1 + l) -1, p * -(j + r*s))

        ALGORITHM:

        Compute:

        Frob(x^i dx/y^j) / dx = p * x ** (p * (i+1) - 1) * y ** (-j*p) * Sigma

        where:

        .. MATH::

            Sigma = \sum_{k = 0} ^{N0-1}
                            \sum_{s = 0} ^k
                                (-1) ** (k-s) * binomial(k, s)
                                * binomial(-j/r, k)
                                * self._frobpow[s]
                                * self._y ** (-self._r * self._p * s)
                    = \sum_{s = 0} ^{N0 - 1}
                        \sum_{k = s} ^N0
                            (-1) ** (k-s) * binomial(k, s)
                            * binomial(-j/self._r, k)
                            * self._frobpow[s]
                            * self._y ** (-self._r*self._p*s)
                    = \sum_{s = 0} ^{N0-1}
                            D_{j, s}
                            * self._frobpow[s]
                            * self._y ** (-self._r * self._p * s)
                    = \sum_{s = 0} ^N0
                        \sum_{l = 0} ^(d*s)
                            D_{j, s} * self._frobpow[s][l]
                            * x ** (self._p ** l)
                            * y ** (-self._r * self._p ** s)

        and:

        .. MATH::

            D_{j, s} = \sum_{k = s} ^N0 (-1) ** (k-s) * binomial(k, s) * binomial(-j/self._r, k) )

        TESTS::

            sage: p = 499
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: C = CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1)
            sage: C._init_frob()
            sage: C._frob_sparse(2, 0, 1)
            [499]
            sage: C._frob_sparse(2, 0, 2)
            [499   0]
            [  0   0]
            [  0   0]
            [  0   0]
            [  0   0]
            sage: C._frob_sparse(2, 1, 1)
            [499]
            sage: C._frob_sparse(2, 1, 2)
            [ 82834998  41417000]
            [        0 124251000]
            [        0 124250002]
            [        0  41416501]
            [        0  41417000]
            sage: C._frob_sparse(2, 2, 1)
            [499]
        """
        def _extend_frobpow(power):
            if power < len(self._frobpow_list):
                pass
            else:
                frobpow = self._Zqx(self._frobpow_list[-1])
                for k in range(len(self._frobpow_list), power + 1):
                    frobpow *= self._frobf
                self._frobpow_list.extend([frobpow.list()])
            assert power < len(self._frobpow_list)

        _extend_frobpow(N0)
        r = self._r
        Dj = [
            self._Zq(
                sum([(-1)**(k - l) * binomial(k, l) * binomial(-ZZ(j) / r, k)
                     for k in range(l, N0)])) for l in range(N0)
        ]
        frobij = matrix(self._Zq, self._d * (N0 - 1) + 1, N0)
        for s in range(N0):
            for l in range(self._d * s + 1):
                frobij[l, s] = self._p * Dj[s] * self._frobpow_list[s][l]
        return frobij
Ejemplo n.º 35
0
 def _N0_RH():
     return ceil(
         log(2 * binomial(2 * self._genus, self._genus), self._p) +
         self._genus * self._n / ZZ(2))
Ejemplo n.º 36
0
    def frobenius_polynomial(self):
        r"""
        Return the characteristic polynomial of Frobenius.

        EXAMPLES:

        Hyperelliptic curves::

            sage: p = 11
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: f = x^7 + 4*x^2 + 10*x + 4
            sage: CyclicCover(2, f).frobenius_polynomial() == \
            ....: HyperellipticCurve(f).frobenius_polynomial()
            True
            sage: f = 2*x^5 + 4*x^3 + x^2 + 2*x + 1
            sage: CyclicCover(2, f).frobenius_polynomial() == \
            ....: HyperellipticCurve(f).frobenius_polynomial()
            True
            sage: f = 2*x^6 + 4*x^4 + x^3 + 2*x^2 + x
            sage: CyclicCover(2, f).frobenius_polynomial() == \
            ....: HyperellipticCurve(f).frobenius_polynomial()
            True
            sage: p = 1117
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: f = x^9 + 4*x^2 + 10*x + 4
            sage: CyclicCover(2, f).frobenius_polynomial() == \
            ....: HyperellipticCurve(f).frobenius_polynomial() # long time
            True
            sage: f = 2*x^5 + 4*x^3 + x^2 + 2*x + 1
            sage: CyclicCover(2, f).frobenius_polynomial() == \
            ....: HyperellipticCurve(f).frobenius_polynomial()
            True

        Superelliptic curves::

            sage: p = 11
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1).frobenius_polynomial()
            x^6 + 21*x^4 + 231*x^2 + 1331
            sage: CyclicCover(4, x^3 + x + 1).frobenius_polynomial()
            x^6 + 2*x^5 + 11*x^4 + 121*x^2 + 242*x + 1331
            sage: p = 4999
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: CyclicCover(4, x^3  - 1).frobenius_polynomial() == \
            ....: CyclicCover(3, x^4  + 1).frobenius_polynomial()
            True
            sage: CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1).frobenius_polynomial()
            x^6 + 180*x^5 + 20988*x^4 + 1854349*x^3 + 104919012*x^2 + 4498200180*x + 124925014999
            sage: CyclicCover(4,x^5 + x + 1).frobenius_polynomial()
            x^12 - 64*x^11 + 5018*x^10 - 488640*x^9 + 28119583*x^8 - 641791616*x^7 + 124245485932*x^6 - 3208316288384*x^5 + 702708407289583*x^4 - 61043359329111360*x^3 + 3133741752599645018*x^2 - 199800079984001599936*x + 15606259372500374970001

            sage: CyclicCover(11, PolynomialRing(GF(1129), 'x')([-1] + [0]*(5-1) + [1])).frobenius_polynomial() # long time
            x^40 + 7337188909826596*x^30 + 20187877911930897108199045855206*x^20 + 24687045654725446027864774006541463602997309796*x^10 + 11320844849639649951608809973589776933203136765026963553258401

            sage: CyclicCover(3, PolynomialRing(GF(1009^2), 'x')([-1] + [0]*(5-1) + [1])).frobenius_polynomial() # long time
            x^8 + 532*x^7 - 2877542*x^6 - 242628176*x^5 + 4390163797795*x^4 - 247015136050256*x^3 - 2982540407204025062*x^2 + 561382189105547134612*x + 1074309286591662654798721


        A non-monic example checking that :trac:`29015` is fixed::

            sage: a = 3
            sage: K.<s>=GF(83^3);
            sage: R.<x>= PolynomialRing(K)
            sage: h = s*x^4 +x*3+ 8;
            sage: C = CyclicCover(a,h)
            sage: C.frobenius_polynomial()
            x^6 + 1563486*x^4 + 893980969482*x^2 + 186940255267540403

        Non-superelliptic curves::

            sage: p = 13
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: C = CyclicCover(4, x^4 + 1)
            sage: C.frobenius_polynomial()
            x^6 - 6*x^5 + 3*x^4 + 60*x^3 + 39*x^2 - 1014*x + 2197
            sage: R.<t> = PowerSeriesRing(Integers())
            sage: C.projective_closure().zeta_series(2,t)
            1 + 8*t + 102*t^2 + O(t^3)
            sage: C.frobenius_polynomial().reverse()(t)/((1-t)*(1-p*t)) + O(t^5)
            1 + 8*t + 102*t^2 + 1384*t^3 + 18089*t^4 + O(t^5)

            sage: x = PolynomialRing(GF(11),"x").gen()
            sage: CyclicCover(4, x^6 - 11*x^3 + 70*x^2 - x + 961).frobenius_polynomial() # long time
            x^14 + 14*x^12 + 287*x^10 + 3025*x^8 + 33275*x^6 + 381997*x^4 + 2254714*x^2 + 19487171
            sage: x = PolynomialRing(GF(4999),"x").gen()
            sage: CyclicCover(4, x^6 - 11*x^3 + 70*x^2 - x + 961).frobenius_polynomial() # long time
            x^14 - 4*x^13 - 2822*x^12 - 30032*x^11 + 37164411*x^10 - 152369520*x^9 + 54217349361*x^8 - 1021791160888*x^7 + 271032529455639*x^6 - 3807714457169520*x^5 + 4642764601604000589*x^4 - 18754988504199390032*x^3 - 8809934776794570547178*x^2 - 62425037490001499880004*x + 78015690603129374475034999

            sage: p = 11
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: CyclicCover(3, 5*x^3 - 5*x + 13).frobenius_polynomial()
            x^2 + 11
            sage: CyclicCover(3, x^6 + x^4 - x^3 + 2*x^2 - x - 1).frobenius_polynomial()
            x^8 + 32*x^6 + 462*x^4 + 3872*x^2 + 14641
            sage: p = 4999
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: CyclicCover(3, 5*x^3 - 5*x + 13).frobenius_polynomial()
            x^2 - 47*x + 4999
            sage: CyclicCover(3, x^6 + x^4 - x^3 + 2*x^2 - x - 1).frobenius_polynomial()
            x^8 + 122*x^7 + 4594*x^6 - 639110*x^5 - 82959649*x^4 - 3194910890*x^3 + 114804064594*x^2 + 15240851829878*x + 624500149980001

            sage: p = 11
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: CyclicCover(5, x^5 + x).frobenius_polynomial() # long time
            x^12 + 4*x^11 + 22*x^10 + 108*x^9 + 503*x^8 + 1848*x^7 + 5588*x^6 + 20328*x^5 + 60863*x^4 + 143748*x^3 + 322102*x^2 + 644204*x + 1771561
            sage: CyclicCover(5, 2*x^5 + x).frobenius_polynomial() # long time
            x^12 - 9*x^11 + 42*x^10 - 108*x^9 - 47*x^8 + 1782*x^7 - 8327*x^6 + 19602*x^5 - 5687*x^4 - 143748*x^3 + 614922*x^2 - 1449459*x + 1771561
            sage: p = 49999
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: CyclicCover(5, x^5 + x ).frobenius_polynomial() # long time
            x^12 + 299994*x^10 + 37498500015*x^8 + 2499850002999980*x^6 + 93742500224997000015*x^4 + 1874812507499850001499994*x^2 + 15623125093747500037499700001
            sage: CyclicCover(5, 2*x^5 + x).frobenius_polynomial() # long time
            x^12 + 299994*x^10 + 37498500015*x^8 + 2499850002999980*x^6 + 93742500224997000015*x^4 + 1874812507499850001499994*x^2 + 15623125093747500037499700001


        TESTS::

            sage: for _ in range(5): # long time
            ....:     fail = False
            ....:     p = random_prime(500, lbound=5)
            ....:     for i in range(1, 4):
            ....:         F = GF(p**i)
            ....:         Fx = PolynomialRing(F, 'x')
            ....:         b = F.random_element()
            ....:         while b == 0:
            ....:            b = F.random_element()
            ....:         E = EllipticCurve(F, [0, b])
            ....:         C1 = CyclicCover(3, Fx([-b, 0, 1]))
            ....:         C2 = CyclicCover(2, Fx([b, 0, 0, 1]))
            ....:         frob = [elt.frobenius_polynomial() for elt in [E, C1, C2]]
            ....:         if len(set(frob)) != 1:
            ....:             E
            ....:             C1
            ....:             C2
            ....:             frob
            ....:             fail = True
            ....:             break
            ....:     if fail:
            ....:       break
            ....: else:
            ....:     True
            True


        """
        self._init_frob()
        F = self.frobenius_matrix(self._N0)

        def _denominator():
            R = PolynomialRing(ZZ, "T")
            T = R.gen()
            denom = R(1)
            lc = self._f.list()[-1]
            if lc == 1:  # MONIC
                for i in range(2, self._delta + 1):
                    if self._delta % i == 0:
                        phi = euler_phi(i)
                        G = IntegerModRing(i)
                        ki = G(self._q).multiplicative_order()
                        denom = denom * (T**ki - 1)**(phi // ki)
                return denom
            else:  # Non-monic
                x = PolynomialRing(self._Fq, "x").gen()
                f = x**self._delta - lc
                L = f.splitting_field("a")
                roots = [r for r, _ in f.change_ring(L).roots()]
                roots_dict = dict([(r, i) for i, r in enumerate(roots)])
                rootsfrob = [
                    L.frobenius_endomorphism(self._Fq.degree())(r)
                    for r in roots
                ]
                m = zero_matrix(len(roots))
                for i, r in enumerate(roots):
                    m[i, roots_dict[rootsfrob[i]]] = 1
            return R(R(m.characteristic_polynomial()) // (T - 1))

        denom = _denominator()
        R = PolynomialRing(ZZ, "x")

        if self._nodenominators:
            min_val = 0
        else:
            # are there any denominators in F?
            min_val = min(
                self._Qq(elt).valuation() for row in F.rows() for elt in row)

        if min_val >= 0:
            prec = _N0_nodenominators(self._p, self._genus, self._n)
            charpoly_prec = [
                prec + i for i in reversed(range(1, self._genus + 1))
            ] + [prec] * (self._genus + 1)
            cp = charpoly_frobenius(F, charpoly_prec, self._p, 1, self._n,
                                    denom.list())
            return R(cp)
        else:
            cp = F.charpoly().reverse()
            denom = denom.reverse()
            PS = PowerSeriesRing(self._Zp, "T")
            cp = PS(cp) / PS(denom)
            cp = cp.padded_list(self._genus + 1)
            cpZZ = [None for _ in range(2 * self._genus + 1)]
            cpZZ[0] = 1
            cpZZ[-1] = self._p**self._genus
            for i in range(1, self._genus + 1):
                cmod = cp[i]
                bound = binomial(2 * self._genus,
                                 i) * self._p**(i * self._n * 0.5)
                localmod = self._p**(ceil(log(bound, self._p)))
                c = cmod.lift() % localmod
                if c > bound:
                    c = -(-cmod.lift() % localmod)
                cpZZ[i] = c
                if i != self._genus + 1:
                    cpZZ[2 * self._genus - i] = c * self._p**(self._genus - i)
            cpZZ.reverse()
            return R(cpZZ)
Ejemplo n.º 37
0
    def BinomialRandomUniform(self, n, k, p):
        r"""
        Return a random `k`-uniform hypergraph on `n` points, in which each
        edge is inserted independently with probability `p`.

        - ``n`` -- number of nodes of the graph

        - ``k`` -- uniformity

        - ``p`` -- probability of an edge

        EXAMPLES::

            sage: hypergraphs.BinomialRandomUniform(50, 3, 1).num_blocks()
            19600
            sage: hypergraphs.BinomialRandomUniform(50, 3, 0).num_blocks()
            0

        TESTS::

            sage: hypergraphs.BinomialRandomUniform(50, 3, -0.1)
            Traceback (most recent call last):
            ...
            ValueError: edge probability should be in [0,1]
            sage: hypergraphs.BinomialRandomUniform(50, 3, 1.1)
            Traceback (most recent call last):
            ...
            ValueError: edge probability should be in [0,1]
            sage: hypergraphs.BinomialRandomUniform(-50, 3, 0.17)
            Traceback (most recent call last):
            ...
            ValueError: number of vertices should be non-negative
            sage: hypergraphs.BinomialRandomUniform(50.9, 3, 0.17)
            Traceback (most recent call last):
            ...
            ValueError: number of vertices should be an integer
            sage: hypergraphs.BinomialRandomUniform(50, -3, 0.17)
            Traceback (most recent call last):
            ...
            ValueError: the uniformity should be non-negative
            sage: hypergraphs.BinomialRandomUniform(50, I, 0.17)
            Traceback (most recent call last):
            ...
            ValueError: the uniformity should be an integer
        """
        from sage.rings.integer import Integer
        if n < 0:
            raise ValueError("number of vertices should be non-negative")
        try:
            nverts = Integer(n)
        except TypeError:
            raise ValueError("number of vertices should be an integer")
        if k < 0:
            raise ValueError("the uniformity should be non-negative")
        try:
            uniformity = Integer(k)
        except TypeError:
            raise ValueError("the uniformity should be an integer")
        if not 0 <= p <= 1:
            raise ValueError("edge probability should be in [0,1]")

        import numpy.random as nrn
        from sage.functions.other import binomial
        m = nrn.binomial(binomial(nverts, uniformity), p)
        return hypergraphs.UniformRandomUniform(n, k, m)
Ejemplo n.º 38
0
        def principal_specialization(self, n=infinity, q=None):
            r"""
            Return the principal specialization of a symmetric function.

            The *principal specialization* of order `n` at `q`
            is the ring homomorphism `ps_{n,q}` from the ring of
            symmetric functions to another commutative ring `R`
            given by `x_i \mapsto q^{i-1}` for `i \in \{1,\dots,n\}`
            and `x_i \mapsto 0` for `i > n`.
            Here, `q` is a given element of `R`, and we assume that
            the variables of our symmetric functions are
            `x_1, x_2, x_3, \ldots`.
            (To be more precise, `ps_{n,q}` is a `K`-algebra
            homomorphism, where `K` is the base ring.)
            See Section 7.8 of [EnumComb2]_.

            The *stable principal specialization* at `q` is the ring
            homomorphism `ps_q` from the ring of symmetric functions
            to another commutative ring `R` given by
            `x_i \mapsto q^{i-1}` for all `i`.
            This is well-defined only if the resulting infinite sums
            converge; thus, in particular, setting `q = 1` in the
            stable principal specialization is an invalid operation.

            INPUT:

            - ``n`` (default: ``infinity``) -- a nonnegative integer or
              ``infinity``, specifying whether to compute the principal
              specialization of order ``n`` or the stable principal
              specialization.

            - ``q`` (default: ``None``) -- the value to use for `q`; the
              default is to create a ring of polynomials in ``q``
              (or a field of rational functions in ``q``) over the
              given coefficient ring.

            We use the formulas from Proposition 7.8.3 of [EnumComb2]_
            (using Gaussian binomial coefficients `\binom{u}{v}_q`):

            .. MATH::

                ps_{n,q}(h_\lambda) = \prod_i \binom{n+\lambda_i-1}{\lambda_i}_q,

                ps_{n,1}(h_\lambda) = \prod_i \binom{n+\lambda_i-1}{\lambda_i},

                ps_q(h_\lambda) = 1 / \prod_i \prod_{j=1}^{\lambda_i} (1-q^j).

            EXAMPLES::

                sage: h = SymmetricFunctions(QQ).h()
                sage: x = h[2,1]
                sage: x.principal_specialization(3)
                q^6 + 2*q^5 + 4*q^4 + 4*q^3 + 4*q^2 + 2*q + 1
                sage: x = 3*h[2] + 2*h[1] + 1
                sage: x.principal_specialization(3, q=var("q"))
                2*(q^3 - 1)/(q - 1) + 3*(q^4 - 1)*(q^3 - 1)/((q^2 - 1)*(q - 1)) + 1

            TESTS::

                sage: x = h.zero()
                sage: s = x.principal_specialization(3); s
                0

            """
            from sage.combinat.q_analogues import q_binomial

            def get_variable(ring, name):
                try:
                    ring(name)
                except TypeError:
                    from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
                    return PolynomialRing(ring, name).gen()
                else:
                    raise ValueError(
                        "the variable %s is in the base ring, pass it explicitly"
                        % name)

            if q is None:
                q = get_variable(self.base_ring(), 'q')

            if q == 1:
                if n == infinity:
                    raise ValueError(
                        "the stable principal specialization at q=1 is not defined"
                    )
                f = lambda partition: prod(
                    binomial(n + part - 1, part) for part in partition)
            elif n == infinity:
                f = lambda partition: prod(1 / prod(
                    (1 - q**i) for i in range(1, part + 1))
                                           for part in partition)
            else:
                f = lambda partition: prod(
                    q_binomial(n + part - 1, part, q=q) for part in partition)

            return self.parent()._apply_module_morphism(self, f, q.parent())
    def _standardize_s_coeff(s_coeff, index_set, ce, parity=None):
        """
        Convert an input dictionary to structure constants of this
        Lie conformal algebra.

        INPUT:

        - ``s_coeff`` -- a dictionary as in
          :class:`LieConformalAlgebraWithStructureCoefficients<sage.\
          algebras.lie_conformal_algebras.lie_conformal_algebra_with_\
          structure_coefficients.LieConformalAlgebraWithStructure\
          Coefficients>`.
        - ``index_set` -- A finite enumerated set indexing the
          generators (not counting the central elements).
        - ``ce`` -- a tuple of ``str``; a list of names for the central
          generators of this Lie conformal algebra
        - ``parity`` -- a tuple of `0` or `1` (Default: tuple of `0`);
          this tuple specifies the parity of each non-central generator.

        OUTPUT:

        A finite Family representing ``s_coeff`` in the input.
        It contains superfluous information that can be obtained by
        skew-symmetry but that improves speed in computing OPE for
        vertex algebras.

        EXAMPLES::

            sage: virdict =  {('L','L'):{0:{('L',1):1}, 1:{('L',0): 2},3:{('C', 0):1/2}}}
            sage: Vir = lie_conformal_algebras.Virasoro(QQ)
            sage: Vir._standardize_s_coeff(virdict, Family(('L',)), ('C',))
            Finite family {('L', 'L'): ((0, ((('L', 1), 1),)),               (1, ((('L', 0), 2),)),               (3, ((('C', 0), 1/2),)))}
        """
        if parity is None:
            parity = (0, ) * index_set.cardinality()
        index_to_parity = {i: p for (i, p) in zip(index_set, parity)}
        sc = {}
        #mypair has a pair of generators
        for mypair in s_coeff.keys():
            #e.g.  v = { 0: { (L,2):3, (G,3):1}, 1:{(L,1),2} }
            v = s_coeff[mypair]
            key = tuple(mypair)
            vals = {}
            for l in v.keys():
                lth_product = {k: y for k, y in v[l].items() if y}
                if lth_product:
                    vals[l] = lth_product

            myvals = tuple([(k, tuple(v.items())) for k, v in vals.items()
                            if v])

            if key in sc.keys() and sorted(sc[key]) != sorted(myvals):
                raise ValueError("two distinct values given for one "\
                                 "and the same bracket, skew-symmetry"\
                                 "is not satisfied?")
            if myvals:
                sc[key] = myvals

            #We now add the skew-symmetric part to optimize
            #brackets computations later
            key = (mypair[1], mypair[0])
            if index_to_parity[mypair[0]] * index_to_parity[mypair[1]]:
                parsgn = -1
            else:
                parsgn = 1
            maxpole = max(v.keys())
            vals = {}
            for k in range(maxpole + 1):
                kth_product = {}
                for j in range(maxpole + 1 - k):
                    if k + j in v.keys():
                        for i in v[k + j]:
                            if (i[0] not in ce) or (i[0] in ce
                                                    and i[1] + j == 0):
                                kth_product[(i[0],i[1]+j)] = \
                                        kth_product.get((i[0], i[1]+j), 0)
                                kth_product[(i[0],i[1]+j)] += parsgn*\
                                v[k+j][i]*(-1)**(k+j+1)*binomial(i[1]+j,j)
                kth_product = {k: v for k, v in kth_product.items() if v}
                if kth_product:
                    vals[k] = kth_product

            myvals = tuple([(k, tuple(v.items())) for k, v in vals.items()
                            if v])

            if key in sc.keys() and sorted(sc[key]) != sorted(myvals):
                raise ValueError("two distinct values given for one "\
                                 "and the same bracket. "\
                                 "Skew-symmetry is not satisfied?")
            if myvals:
                sc[key] = myvals
        return Family(sc)
Ejemplo n.º 40
0
        def principal_specialization(self, n=infinity, q=None):
            r"""
            Return the principal specialization of a symmetric function.

            The *principal specialization* of order `n` at `q`
            is the ring homomorphism `ps_{n,q}` from the ring of
            symmetric functions to another commutative ring `R`
            given by `x_i \mapsto q^{i-1}` for `i \in \{1,\dots,n\}`
            and `x_i \mapsto 0` for `i > n`.
            Here, `q` is a given element of `R`, and we assume that
            the variables of our symmetric functions are
            `x_1, x_2, x_3, \ldots`.
            (To be more precise, `ps_{n,q}` is a `K`-algebra
            homomorphism, where `K` is the base ring.)
            See Section 7.8 of [EnumComb2]_.

            The *stable principal specialization* at `q` is the ring
            homomorphism `ps_q` from the ring of symmetric functions
            to another commutative ring `R` given by
            `x_i \mapsto q^{i-1}` for all `i`.
            This is well-defined only if the resulting infinite sums
            converge; thus, in particular, setting `q = 1` in the
            stable principal specialization is an invalid operation.

            INPUT:

            - ``n`` (default: ``infinity``) -- a nonnegative integer or
              ``infinity``, specifying whether to compute the principal
              specialization of order ``n`` or the stable principal
              specialization.

            - ``q`` (default: ``None``) -- the value to use for `q`; the
              default is to create a ring of polynomials in ``q``
              (or a field of rational functions in ``q``) over the
              given coefficient ring.

            For ``q=1`` and finite ``n`` we use the formula from
            Proposition 7.8.3 of [EnumComb2]_:

            .. MATH::

                ps_{n,1}(m_\lambda) = \binom{n}{\ell(\lambda)}
                                      \binom{\ell(\lambda)}{m_1(\lambda), m_2(\lambda),\dots},

            where `\ell(\lambda)` denotes the length of `\lambda`.

            In all other cases, we convert to complete homogeneous
            symmetric functions.

            EXAMPLES::

                sage: m = SymmetricFunctions(QQ).m()
                sage: x = m[3,1]
                sage: x.principal_specialization(3)
                q^7 + q^6 + q^5 + q^3 + q^2 + q

                sage: x = 5*m[2] + 3*m[1] + 1
                sage: x.principal_specialization(3, q=var("q"))
                -10*(q^3 - 1)*q/(q - 1) + 5*(q^3 - 1)^2/(q - 1)^2 + 3*(q^3 - 1)/(q - 1) + 1

            TESTS::

                sage: m.zero().principal_specialization(3)
                0

            """
            if q == 1:
                if n == infinity:
                    raise ValueError(
                        "the stable principal specialization at q=1 is not defined"
                    )
                f = lambda partition: binomial(n, len(
                    partition)) * multinomial(partition.to_exp())
                return self.parent()._apply_module_morphism(
                    self, f, q.parent())

            # heuristically, it seems fastest to fall back to the
            # elementary basis - using the powersum basis would
            # introduce singularities, because it is not a Z-basis
            return self.parent().realization_of().elementary()(
                self).principal_specialization(n=n, q=q)
Ejemplo n.º 41
0
    def BinomialRandomUniform(self, n, k, p):
        r"""
        Return a random `k`-uniform hypergraph on `n` points, in which each
        edge is inserted independently with probability `p`.

        - ``n`` -- number of nodes of the graph

        - ``k`` -- uniformity

        - ``p`` -- probability of an edge

        EXAMPLES::

            sage: hypergraphs.BinomialRandomUniform(50, 3, 1).num_blocks()
            19600
            sage: hypergraphs.BinomialRandomUniform(50, 3, 0).num_blocks()
            0

        TESTS::

            sage: hypergraphs.BinomialRandomUniform(50, 3, -0.1)
            Traceback (most recent call last):
            ...
            ValueError: edge probability should be in [0,1]
            sage: hypergraphs.BinomialRandomUniform(50, 3, 1.1)
            Traceback (most recent call last):
            ...
            ValueError: edge probability should be in [0,1]
            sage: hypergraphs.BinomialRandomUniform(-50, 3, 0.17)
            Traceback (most recent call last):
            ...
            ValueError: number of vertices should be non-negative
            sage: hypergraphs.BinomialRandomUniform(50.9, 3, 0.17)
            Traceback (most recent call last):
            ...
            ValueError: number of vertices should be an integer
            sage: hypergraphs.BinomialRandomUniform(50, -3, 0.17)
            Traceback (most recent call last):
            ...
            ValueError: the uniformity should be non-negative
            sage: hypergraphs.BinomialRandomUniform(50, I, 0.17)
            Traceback (most recent call last):
            ...
            ValueError: the uniformity should be an integer
        """
        from sage.rings.integer import Integer
        if n < 0:
            raise ValueError("number of vertices should be non-negative")
        try:
            nverts = Integer(n)
        except TypeError:
            raise ValueError("number of vertices should be an integer")
        if k < 0:
            raise ValueError("the uniformity should be non-negative")
        try:
            uniformity = Integer(k)
        except TypeError:
            raise ValueError("the uniformity should be an integer")
        if not 0 <= p <= 1:
            raise ValueError("edge probability should be in [0,1]")

        import numpy.random as nrn
        from sage.functions.other import binomial
        m = nrn.binomial(binomial(nverts, uniformity), p)
        return hypergraphs.UniformRandomUniform(n, k, m)
def fiej(i, j, d):  # fiejcoeff_on_highest_weight
    """
    INPUT:

    - `i`, `j`, `d` -- nonnegative integers

    OUTPUT: a nonnegative integer

    Let $f = x\partial_y and e = y\partial_x$, and `p` be a highest
    weight polynomial of weight `d`.  Then `c=fiej(i,j,d)` is such
    that `f^i e^j p = c e^{j-i} p`. `c` is given by the formula::

    .. MATH:: \prod_{k = j-i+1}^j (kd - 2 \binom{k}{2})

    EXAMPLES::

        sage: R = QQ['x,y']
        sage: R.inject_variables()
        Defining x, y
        sage: def f(p): return x*diff(p,y)
        sage: def e(p): return y*diff(p,x)

        sage: fiej(0,0,3)
        1

        sage: fiej(0,1,3)
        1
        sage: f(e(x^3)) / x^3
        3
        sage: fiej(1,1,3)
        3
        sage: f(f(e(x^3)))
        0
        sage: fiej(2,1,3)
        0

        sage: fiej(0,2,3)
        1
        sage: f(e(e(x^3))) / e(x^3)
        4
        sage: fiej(1,2,3)
        4
        sage: f(f(e(e(x^3)))) / x^3
        12
        sage: fiej(2,2,3)
        12


        sage: fiej(0,3,3)
        1
        sage: f(e(e(e(x^3)))) / e(e(x^3))
        3
        sage: fiej(1,3,3)
        3
        sage: f(f(e(e(e(x^3))))) / e(x^3)
        12
        sage: f(f(f(e(e(e(x^3)))))) / x^3
        36
        sage: fiej(3,3,3)
        36
        sage: fiej(4,3,3)
        0

        sage: f(f(f(e(e(e(x^9)))))) / x^9
        3024
        sage: fiej(3,3,9)
        3024
    """
    return binomial(j, i) * binomial(d - j + i, i) * factorial(i)**2
Ejemplo n.º 43
0
    def SingularityAnalysis(var, zeta=1, alpha=0, beta=0, delta=0,
                            precision=None, normalized=True):
        r"""
        Return the asymptotic expansion of the coefficients of
        an power series with specified pole and logarithmic singularity.

        More precisely, this extracts the `n`-th coefficient

        .. MATH::

            [z^n] \left(\frac{1}{1-z/\zeta}\right)^\alpha
            \left(\frac{1}{z/\zeta} \log \frac{1}{1-z/\zeta}\right)^\beta
            \left(\frac{1}{z/\zeta} \log
            \left(\frac{1}{z/\zeta} \log \frac{1}{1-z/\zeta}\right)\right)^\delta

        (if ``normalized=True``, the default) or

        .. MATH::

            [z^n] \left(\frac{1}{1-z/\zeta}\right)^\alpha
            \left(\log \frac{1}{1-z/\zeta}\right)^\beta
            \left(\log
            \left(\frac{1}{z/\zeta} \log \frac{1}{1-z/\zeta}\right)\right)^\delta

        (if ``normalized=False``).

        INPUT:

        - ``var`` -- a string for the variable name.

        - ``zeta`` -- (default: `1`) the location of the singularity.

        - ``alpha`` -- (default: `0`) the pole order of the singularty.

        - ``beta`` -- (default: `0`) the order of the logarithmic singularity.

        - ``delta`` -- (default: `0`) the order of the log-log singularity.
          Not yet implemented for ``delta != 0``.

        - ``precision`` -- (default: ``None``) an integer. If ``None``, then
          the default precision of the asymptotic ring is used.

        - ``normalized`` -- (default: ``True``) a boolean, see above.

        OUTPUT:

        An asymptotic expansion.

        EXAMPLES::

            sage: asymptotic_expansions.SingularityAnalysis('n', alpha=1)
            1
            sage: asymptotic_expansions.SingularityAnalysis('n', alpha=2)
            n + 1
            sage: asymptotic_expansions.SingularityAnalysis('n', alpha=3)
            1/2*n^2 + 3/2*n + 1
            sage: _.parent()
            Asymptotic Ring <n^ZZ> over Rational Field

        ::

            sage: asymptotic_expansions.SingularityAnalysis('n', alpha=-3/2,
            ....:     precision=3)
            3/4/sqrt(pi)*n^(-5/2)
            + 45/32/sqrt(pi)*n^(-7/2)
            + 1155/512/sqrt(pi)*n^(-9/2)
            + O(n^(-11/2))
            sage: asymptotic_expansions.SingularityAnalysis('n', alpha=-1/2,
            ....:     precision=3)
            -1/2/sqrt(pi)*n^(-3/2)
            - 3/16/sqrt(pi)*n^(-5/2)
            - 25/256/sqrt(pi)*n^(-7/2)
            + O(n^(-9/2))
            sage: asymptotic_expansions.SingularityAnalysis('n', alpha=1/2,
            ....:     precision=4)
            1/sqrt(pi)*n^(-1/2)
            - 1/8/sqrt(pi)*n^(-3/2)
            + 1/128/sqrt(pi)*n^(-5/2)
            + 5/1024/sqrt(pi)*n^(-7/2)
            + O(n^(-9/2))
            sage: _.parent()
            Asymptotic Ring <n^QQ> over Symbolic Constants Subring

        ::

            sage: S = SR.subring(rejecting_variables=('n',))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=S.var('a'),
            ....:     precision=4).map_coefficients(lambda c: c.factor())
            1/gamma(a)*n^(a - 1)
            + (1/2*(a - 1)*a/gamma(a))*n^(a - 2)
            + (1/24*(3*a - 1)*(a - 1)*(a - 2)*a/gamma(a))*n^(a - 3)
            + (1/48*(a - 1)^2*(a - 2)*(a - 3)*a^2/gamma(a))*n^(a - 4)
            + O(n^(a - 5))
            sage: _.parent()
            Asymptotic Ring <n^(Symbolic Subring rejecting the variable n)>
            over Symbolic Subring rejecting the variable n

        ::

            sage: ae = asymptotic_expansions.SingularityAnalysis('n',
            ....:          alpha=1/2, beta=1, precision=4); ae
            1/sqrt(pi)*n^(-1/2)*log(n) + ((euler_gamma + 2*log(2))/sqrt(pi))*n^(-1/2)
            - 5/8/sqrt(pi)*n^(-3/2)*log(n) + (1/8*(3*euler_gamma + 6*log(2) - 8)/sqrt(pi)
            - (euler_gamma + 2*log(2) - 2)/sqrt(pi))*n^(-3/2) + O(n^(-5/2)*log(n))
            sage: n = ae.parent().gen()
            sage: ae.subs(n=n-1).map_coefficients(lambda x: x.canonicalize_radical())
            1/sqrt(pi)*n^(-1/2)*log(n)
            + ((euler_gamma + 2*log(2))/sqrt(pi))*n^(-1/2)
            - 1/8/sqrt(pi)*n^(-3/2)*log(n)
            + (-1/8*(euler_gamma + 2*log(2))/sqrt(pi))*n^(-3/2)
            + O(n^(-5/2)*log(n))

        ::

            sage: asymptotic_expansions.SingularityAnalysis('n',
            ....:     alpha=1, beta=1/2, precision=4)
            log(n)^(1/2) + 1/2*euler_gamma*log(n)^(-1/2)
            + (-1/8*euler_gamma^2 + 1/48*pi^2)*log(n)^(-3/2)
            + (1/16*euler_gamma^3 - 1/32*euler_gamma*pi^2 + 1/8*zeta(3))*log(n)^(-5/2)
            + O(log(n)^(-7/2))

        ::

            sage: ae = asymptotic_expansions.SingularityAnalysis('n',
            ....:     alpha=0, beta=2, precision=14)
            sage: n = ae.parent().gen()
            sage: ae.subs(n=n-2)
            2*n^(-1)*log(n) + 2*euler_gamma*n^(-1) - n^(-2) - 1/6*n^(-3) + O(n^(-5))

        ::

            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=-1/2, beta=1, precision=2, normalized=False)
            -1/2/sqrt(pi)*n^(-3/2)*log(n)
            + (-1/2*(euler_gamma + 2*log(2) - 2)/sqrt(pi))*n^(-3/2)
            + O(n^(-5/2)*log(n))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1/2, alpha=0, beta=1, precision=3, normalized=False)
            2^n*n^(-1) + O(2^n*n^(-2))


        ALGORITHM:

        See [FS2009]_ together with the
        `errata list <http://algo.inria.fr/flajolet/Publications/AnaCombi/errata.pdf>`_.

        REFERENCES:

        .. [FS2009] Philippe Flajolet and Robert Sedgewick,
           `Analytic combinatorics <http://algo.inria.fr/flajolet/Publications/AnaCombi/book.pdf>`_.
           Cambridge University Press, Cambridge, 2009.

        TESTS::

            sage: ex = asymptotic_expansions.SingularityAnalysis('n', alpha=-1/2,
            ....:     precision=4)
            sage: n = ex.parent().gen()
            sage: coefficients = ((1-x)^(1/2)).series(
            ....:     x, 21).truncate().coefficients(x, sparse=False)
            sage: ex.compare_with_values(n,    # rel tol 1e-6
            ....:     lambda k: coefficients[k], [5, 10, 20])
            [(5, 0.015778873294?), (10, 0.01498952777?), (20, 0.0146264622?)]
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=3, precision=2)
            1/2*n^2 + 3/2*n + O(1)
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=3, precision=3)
            1/2*n^2 + 3/2*n + 1
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=3, precision=4)
            1/2*n^2 + 3/2*n + 1

        ::

            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=0)
            Traceback (most recent call last):
            ...
            NotImplementedOZero: The error term in the result is O(0)
            which means 0 for sufficiently large n.
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=-1)
            Traceback (most recent call last):
            ...
            NotImplementedOZero: The error term in the result is O(0)
            which means 0 for sufficiently large n.

        ::

            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'm', alpha=-1/2, precision=3)
            -1/2/sqrt(pi)*m^(-3/2)
            - 3/16/sqrt(pi)*m^(-5/2)
            - 25/256/sqrt(pi)*m^(-7/2)
            + O(m^(-9/2))
            sage: _.parent()
            Asymptotic Ring <m^QQ> over Symbolic Constants Subring

        Location of the singularity::

            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=1, zeta=2, precision=3)
            (1/2)^n
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=1, zeta=1/2, precision=3)
            2^n
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=1, zeta=CyclotomicField(3).gen(),
            ....:      precision=3)
            (-zeta3 - 1)^n
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=4, zeta=2, precision=3)
            1/6*(1/2)^n*n^3 + (1/2)^n*n^2 + 11/6*(1/2)^n*n + O((1/2)^n)
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=-1, zeta=2, precision=3)
            Traceback (most recent call last):
            ...
            NotImplementedOZero: The error term in the result is O(0)
            which means 0 for sufficiently large n.
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=1/2, zeta=2, precision=3)
            1/sqrt(pi)*(1/2)^n*n^(-1/2) - 1/8/sqrt(pi)*(1/2)^n*n^(-3/2)
            + 1/128/sqrt(pi)*(1/2)^n*n^(-5/2) + O((1/2)^n*n^(-7/2))

        The following tests correspond to Table VI.5 in [FS2009]_. ::

            sage: A.<n> = AsymptoticRing('n^QQ * log(n)^QQ', QQ)
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=-1/2, beta=1, precision=2,
            ....:     normalized=False) * (- sqrt(pi*n^3))
            1/2*log(n) + 1/2*euler_gamma + log(2) - 1 + O(n^(-1)*log(n))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=0, beta=1, precision=3,
            ....:     normalized=False)
            n^(-1) + O(n^(-2))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=0, beta=2,  precision=14,
            ....:     normalized=False) * n
            2*log(n) + 2*euler_gamma - n^(-1) - 1/6*n^(-2) +  O(n^(-4))
            sage: (asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=1/2, beta=1, precision=4,
            ....:     normalized=False) * sqrt(pi*n)).\
            ....:     map_coefficients(lambda x: x.expand())
            log(n) + euler_gamma + 2*log(2) - 1/8*n^(-1)*log(n) +
            (-1/8*euler_gamma - 1/4*log(2))*n^(-1) + O(n^(-2)*log(n))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=1, beta=1, precision=13,
            ....:     normalized=False)
            log(n) + euler_gamma + 1/2*n^(-1) - 1/12*n^(-2) + 1/120*n^(-4)
            + O(n^(-6))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=1, beta=2, precision=4,
            ....:     normalized=False)
            log(n)^2 + 2*euler_gamma*log(n) + euler_gamma^2 - 1/6*pi^2
            + O(n^(-1)*log(n))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=3/2, beta=1, precision=3,
            ....:     normalized=False) * sqrt(pi/n)
            2*log(n) + 2*euler_gamma + 4*log(2) - 4 + 3/4*n^(-1)*log(n)
            + O(n^(-1))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=2, beta=1, precision=5,
            ....:     normalized=False)
            n*log(n) + (euler_gamma - 1)*n + log(n) + euler_gamma + 1/2
            + O(n^(-1))
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, alpha=2, beta=2, precision=4,
            ....:     normalized=False) / n
            log(n)^2 + (2*euler_gamma - 2)*log(n)
            - 2*euler_gamma + euler_gamma^2 - 1/6*pi^2 + 2
            + n^(-1)*log(n)^2 + O(n^(-1)*log(n))

        Be aware that the last result does *not* coincide with [FS2009]_,
        they do have a different error term.

        Checking parameters::

            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, 1, 1/2, precision=0, normalized=False)
            Traceback (most recent call last):
            ...
            ValueError: beta and delta must be integers
            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', 1, 1, 1, 1/2, normalized=False)
            Traceback (most recent call last):
            ...
            ValueError: beta and delta must be integers

        ::

            sage: asymptotic_expansions.SingularityAnalysis(
            ....:     'n', alpha=0, beta=0, delta=1, precision=3)
            Traceback (most recent call last):
            ...
            NotImplementedError: not implemented for delta!=0
        """
        from itertools import islice, count
        from asymptotic_ring import AsymptoticRing
        from growth_group import ExponentialGrowthGroup, \
                MonomialGrowthGroup
        from sage.arith.all import falling_factorial
        from sage.categories.cartesian_product import cartesian_product
        from sage.functions.other import binomial, gamma
        from sage.calculus.calculus import limit
        from sage.misc.cachefunc import cached_function
        from sage.arith.srange import srange
        from sage.rings.rational_field import QQ
        from sage.rings.integer_ring import ZZ
        from sage.symbolic.ring import SR

        SCR = SR.subring(no_variables=True)
        s = SR('s')
        iga = 1/gamma(alpha)
        if iga.parent() is SR:
            try:
                iga = SCR(iga)
            except TypeError:
                pass

        coefficient_ring = iga.parent()
        if beta != 0:
            coefficient_ring = SCR

        @cached_function
        def inverse_gamma_derivative(shift, r):
            """
            Return value of `r`-th derivative of 1/Gamma
            at alpha-shift.
            """
            if r == 0:
                result = iga*falling_factorial(alpha-1, shift)
            else:
                result = limit((1/gamma(s)).diff(s, r), s=alpha-shift)

            try:
                return coefficient_ring(result)
            except TypeError:
                return result

        if isinstance(alpha, int):
            alpha = ZZ(alpha)
        if isinstance(beta, int):
            beta = ZZ(beta)
        if isinstance(delta, int):
            delta = ZZ(delta)

        if precision is None:
            precision = AsymptoticRing.__default_prec__


        if not normalized and not (beta in ZZ and delta in ZZ):
            raise ValueError("beta and delta must be integers")
        if delta != 0:
            raise NotImplementedError("not implemented for delta!=0")

        groups = []
        if zeta != 1:
            groups.append(ExponentialGrowthGroup((1/zeta).parent(), var))

        groups.append(MonomialGrowthGroup(alpha.parent(), var))
        if beta != 0:
            groups.append(MonomialGrowthGroup(beta.parent(), 'log({})'.format(var)))

        group = cartesian_product(groups)
        A = AsymptoticRing(growth_group=group, coefficient_ring=coefficient_ring,
                           default_prec=precision)
        n = A.gen()

        if zeta == 1:
            exponential_factor = 1
        else:
            exponential_factor = n.rpow(1/zeta)

        if beta in ZZ and beta >= 0:
            it = ((k, r)
                  for k in count()
                  for r in srange(beta+1))
            k_max = precision
        else:
            it = ((0, r)
                  for r in count())
            k_max = 0

        if beta != 0:
            log_n = n.log()
        else:
            # avoid construction of log(n)
            # because it does not exist in growth group.
            log_n = 1

        it = reversed(list(islice(it, precision+1)))
        if normalized:
            beta_denominator = beta
        else:
            beta_denominator = 0
        L = _sa_coefficients_lambda_(max(1, k_max), beta=beta_denominator)
        (k, r) = next(it)
        result = (n**(-k) * log_n**(-r)).O()

        if alpha in ZZ and beta == 0:
            if alpha > 0 and alpha <= precision:
                result = A(0)
            elif alpha <= 0 and precision > 0:
                from misc import NotImplementedOZero
                raise NotImplementedOZero(A)

        for (k, r) in it:
            result += binomial(beta, r) * \
                sum(L[(k, ell)] * (-1)**ell *
                    inverse_gamma_derivative(ell, r)
                    for ell in srange(k, 2*k+1)
                    if (k, ell) in L) * \
                n**(-k) * log_n**(-r)

        result *= exponential_factor * n**(alpha-1) * log_n**beta

        return result