Exemplo n.º 1
0
    def _eval_(self, n, m, theta, phi, **kwargs):
        r"""
        TESTS::

            sage: x, y = var('x y')
            sage: spherical_harmonic(1, 2, x, y)
            0
            sage: spherical_harmonic(1, -2, x, y)
            0
            sage: spherical_harmonic(1/2, 2, x, y)
            spherical_harmonic(1/2, 2, x, y)
            sage: spherical_harmonic(3, 2, x, y)
            1/8*sqrt(30)*sqrt(7)*cos(x)*e^(2*I*y)*sin(x)^2/sqrt(pi)
            sage: spherical_harmonic(3, 2, 1, 2)
            1/8*sqrt(30)*sqrt(7)*cos(1)*e^(4*I)*sin(1)^2/sqrt(pi)
            sage: spherical_harmonic(3 + I, 2., 1, 2)
            -0.351154337307488 - 0.415562233975369*I

        Check that :trac:`20939` is fixed::

            sage: ex = spherical_harmonic(3,2,1,2*pi/3)
            sage: QQbar(ex * sqrt(pi)/cos(1)/sin(1)^2).minpoly()
            x^4 + 105/32*x^2 + 11025/1024
        """
        if n in ZZ and m in ZZ and n > -1:
            if abs(m) > n:
                return ZZ(0)
            if m == 0 and theta.is_zero():
                return sqrt((2*n+1)/4/pi)
            from sage.arith.misc import factorial
            from sage.functions.trig import cos
            from sage.functions.orthogonal_polys import gen_legendre_P
            return (sqrt(factorial(n-m) * (2*n+1) / (4*pi * factorial(n+m))) *
                    exp(I*m*phi) * gen_legendre_P(n, m, cos(theta)) *
                    (-1)**m).simplify_trig()
Exemplo n.º 2
0
    def _eval_(self, n, m, theta, phi, **kwargs):
        r"""
        TESTS::

            sage: x, y = var('x y')
            sage: spherical_harmonic(1, 2, x, y)
            0
            sage: spherical_harmonic(1, -2, x, y)
            0
            sage: spherical_harmonic(1/2, 2, x, y)
            spherical_harmonic(1/2, 2, x, y)
            sage: spherical_harmonic(3, 2, x, y)
            1/8*sqrt(30)*sqrt(7)*cos(x)*e^(2*I*y)*sin(x)^2/sqrt(pi)
            sage: spherical_harmonic(3, 2, 1, 2)
            1/8*sqrt(30)*sqrt(7)*cos(1)*e^(4*I)*sin(1)^2/sqrt(pi)
            sage: spherical_harmonic(3 + I, 2., 1, 2)
            -0.351154337307488 - 0.415562233975369*I

        Check that :trac:`20939` is fixed::

            sage: ex = spherical_harmonic(3,2,1,2*pi/3)
            sage: QQbar(ex * sqrt(pi)/cos(1)/sin(1)^2).minpoly()
            x^4 + 105/32*x^2 + 11025/1024
        """
        if n in ZZ and m in ZZ and n > -1:
            if abs(m) > n:
                return ZZ(0)
            if m == 0 and theta.is_zero():
                return sqrt((2*n+1)/4/pi)
            from sage.arith.misc import factorial
            from sage.functions.trig import cos
            from sage.functions.orthogonal_polys import gen_legendre_P
            return (sqrt(factorial(n-m) * (2*n+1) / (4*pi * factorial(n+m))) *
                    exp(I*m*phi) * gen_legendre_P(n, m, cos(theta)) *
                    (-1)**m).simplify_trig()
Exemplo n.º 3
0
 def f(partition):
     n = 0
     for part in partition:
         if part != 1:
             return 0
         n += 1
     return t**n / factorial(n)
Exemplo n.º 4
0
def minimal_strata_spin_diff(gmax, rational=False):
    r"""
    Return the differences of volumes between even and odd components in
    H(2g-2) for the genus `g` going from ``1`` up to ``gmax-1``.

    If there are no even/odd components, the corresponding total volume is 0.
    Formulas are from [CheMoeSauZag20]_.

    EXAMPLES::

        sage: from surface_dynamics.flat_surfaces.masur_veech_volumes import minimal_strata_spin_diff
        sage: minimal_strata_spin_diff(5)
        [-1/3*pi^2, -1/120*pi^4, -143/544320*pi^6, -15697/1959552000*pi^8]
        sage: minimal_strata_spin_diff(5, rational=True)
        [-2, -3/4, -143/576, -15697/207360]
    """
    n = 2 * gmax
    R = QQ['u']
    u = R.gen()
    # B(u) = formula (15) in [CMSZ20]
    B = (2 * (u/2)._sinh_series(n).shift(-1)).inverse_series_trunc(n)
    # Pz and a in section 6.3 of [CMSZ20]
    Pz = (sum(-bernoulli(2*j) * u**(2*j) / (2*j) / 2**j for j in range(1, n // 2)))._exp_series(n)
    a = ((u*Pz.inverse_series_trunc(n)).revert_series(n).shift(-1) ).inverse_series_trunc(n)
    # theorem 6.11 in [CMSZ20], normalized volume v(2g-2)=(2g-1)*Vol(2g-2), note the missing factor 2
    if rational:
        return [2* (-2) * a[2*g] * 2 * g / (2*g - 1) / bernoulli(2*g) for g in range(1, gmax)]
    else:
        return [2* (-1)**(g) * (2*pi)**(2*g) * a[2 * g] /(2*g - 1) / factorial(2*g - 1) for g in range(1, gmax)]
Exemplo n.º 5
0
            def is_symmetric(self):
                r"""
                Determine if a `NCSym^*` function, expressed in the
                `\mathbf{w}` basis, is symmetric.

                A function `f` in the `\mathbf{w}` basis is a symmetric
                function if it is in the image of `\chi^*`. That is to say we
                have

                .. MATH::

                    f = \sum_{\lambda} c_{\lambda} \prod_i m_i(\lambda)!
                    \sum_{\lambda(A) = \lambda} \mathbf{w}_A

                where the second sum is over all set partitions `A` whose
                shape `\lambda(A)` is equal to `\lambda` and `m_i(\mu)` is
                the multiplicity of `i` in the partition `\mu`.

                OUTPUT:

                - ``True`` if `\lambda(A)=\lambda(B)` implies the coefficients of
                  `\mathbf{w}_A` and `\mathbf{w}_B` are equal, ``False`` otherwise

                EXAMPLES::

                    sage: w = SymmetricFunctionsNonCommutingVariables(QQ).dual().w()
                    sage: elt = w.sum_of_partitions([2,1,1])
                    sage: elt.is_symmetric()
                    True
                    sage: elt -= 3*w.sum_of_partitions([1,1])
                    sage: elt.is_symmetric()
                    True
                    sage: w = SymmetricFunctionsNonCommutingVariables(ZZ).dual().w()
                    sage: elt = w.sum_of_partitions([2,1,1]) / 2
                    sage: elt.is_symmetric()
                    False
                    sage: elt = w[[1,3],[2]]
                    sage: elt.is_symmetric()
                    False
                    sage: elt = w[[1],[2,3]] + w[[1,2],[3]] + 2*w[[1,3],[2]]
                    sage: elt.is_symmetric()
                    False
                """
                d = {}
                R = self.base_ring()
                for A, coeff in self:
                    la = A.shape()
                    exp = prod([factorial(_) for _ in la.to_exp()])
                    if la not in d:
                        if coeff / exp not in R:
                            return False
                        d[la] = [coeff, 1]
                    else:
                        if d[la][0] != coeff:
                            return False
                        d[la][1] += 1
                # Make sure we've seen each set partition of the shape
                return all(
                    d[la][1] == SetPartitions(la.size(), la).cardinality()
                    for la in d)
Exemplo n.º 6
0
        def sum_of_partitions(self, la):
            r"""
            Return the sum over all sets partitions whose shape is ``la``,
            scaled by `\prod_i m_i!` where `m_i` is the multiplicity
            of `i` in ``la``.

            INPUT:

            - ``la`` -- an integer partition

            OUTPUT:

            - an element of ``self``

            EXAMPLES::

                sage: w = SymmetricFunctionsNonCommutingVariables(QQ).dual().w()
                sage: w.sum_of_partitions([2,1,1])
                2*w{{1}, {2}, {3, 4}} + 2*w{{1}, {2, 3}, {4}} + 2*w{{1}, {2, 4}, {3}}
                 + 2*w{{1, 2}, {3}, {4}} + 2*w{{1, 3}, {2}, {4}} + 2*w{{1, 4}, {2}, {3}}
            """
            la = Partition(la)
            c = prod([factorial(_) for _ in la.to_exp()])
            P = SetPartitions()
            return self.sum_of_terms([(P(m), c)
                                      for m in SetPartitions(sum(la), la)],
                                     distinct=True)
Exemplo n.º 7
0
def minimal_strata_CMSZ(gmax, rational=False):
    r"""
    Return the volumes of `\cH(2g-2)` for the genus `g` going from ``1`` up to ``gmax-1``.

    The algorithm is the one from Sauvaget [Sau18]_ involving an implicit equation. As explained
    in [CheMoeSauZag20]_, one could go through Lagrange inversion. Note that they miss
    factor 2 in their theorem 4.1.

    EXAMPLES::

        sage: from surface_dynamics.flat_surfaces.masur_veech_volumes import minimal_strata_CMSZ
        sage: minimal_strata_CMSZ(6, True)
        [2, 3/4, 305/576, 87983/207360, 1019547/2867200]
        sage: minimal_strata_CMSZ(6, False)
        [1/3*pi^2,
         1/120*pi^4,
         61/108864*pi^6,
         12569/279936000*pi^8,
         12587/3311616000*pi^10]

        sage: from surface_dynamics import AbelianStratum
        sage: from surface_dynamics.flat_surfaces.masur_veech_volumes import masur_veech_volume
        sage: for rat in [True, False]:
        ....:     V0, V2, V4, V6 = minimal_strata_CMSZ(5, rational=rat)
        ....:     MV0 = masur_veech_volume(AbelianStratum(0), rat, 'table')
        ....:     assert V0 == MV0, (V0, MV0, rat)
        ....:     MV2 = masur_veech_volume(AbelianStratum(2), rat, 'table')
        ....:     assert V2 == MV2, (V2, MV2, rat)
        ....:     MV4 = masur_veech_volume(AbelianStratum(4), rat, 'table')
        ....:     assert V4 == MV4, (V4, MV4, rat)
        ....:     MV6 = masur_veech_volume(AbelianStratum(6), rat, 'table')
        ....:     assert V6 == MV6, (V6, MV6, rat)
    """
    n = 2 * gmax - 1
    R = QQ['u']
    u = R.gen()
    # B(u) = formula (15) in [CMSZ20]
    B = (2 * (u/2)._sinh_series(n+1).shift(-1)).inverse_series_trunc(n+1)
    Q = u * (sum(factorial(j-1) * B[j] * u**(j) for j in range(1,n)))._exp_series(n+1)
    # A = formula (14) in [CSMZ20]
    tA = Q.revert_series(n+1).shift(-1).inverse_series_trunc(n)
    # normalized values of volumes in [CMSZ20] are
    # v(m_1, ..., m_n) = (2m_1+1) (2m_2+1) ... (2m_n+1) Vol(m_1, m_2, ..., m_n)
    if rational:
        return [-4 * (2*g) / ZZ(2*g-1) / bernoulli(2*g) * tA[2*g] for g in range(1,gmax)]
    else:
        return [2 * (2*pi)**(2*g) * (-1)**g / ZZ(2*g-1) / factorial(2*g - 1) * tA[2*g] for g in range(1,gmax)]
Exemplo n.º 8
0
    def _gs_term(self, base_ring):
        """
        EXAMPLES::

            sage: F = species.CharacteristicSpecies(2)
            sage: F.generating_series().coefficients(5)
            [0, 0, 1/2, 0, 0]
            sage: F.generating_series().count(2)
            1
        """
        return base_ring(self._weight) / base_ring(factorial(self._n))
Exemplo n.º 9
0
 def coeff(p, q):
     ret = QQ.one()
     last = 0
     for val in p:
         count = 0
         s = 0
         while s != val:
             s += q[last + count]
             count += 1
         ret /= factorial(count)
         last += count
     return ret
Exemplo n.º 10
0
    def _gs_iterator(self, base_ring):
        r"""
        EXAMPLES::

            sage: P = species.PartitionSpecies()
            sage: g = P.generating_series()
            sage: g.coefficients(5)
            [1, 1, 1, 5/6, 5/8]
        """
        from sage.combinat.combinat import bell_number
        for n in _integers_from(0):
            yield self._weight * base_ring(bell_number(n) / factorial(n))
Exemplo n.º 11
0
def minimal_strata_hyp(g, rational=False):
    r"""
    Return the volume of the hyperelliptic component H^{hyp}(2g-2).

    The explicit formula appears in section 6.5 of [CheMoeSauZag20]_.

    EXAMPLES::

        sage: from surface_dynamics.flat_surfaces.masur_veech_volumes import minimal_strata_hyp
        sage: minimal_strata_hyp(2)
        1/120*pi^4
        sage: minimal_strata_hyp(4)
        1/580608*pi^8
        sage: minimal_strata_hyp(10)
        1/137733277917118464000*pi^20
        sage: minimal_strata_hyp(10, rational=True)
        668525/10499279483305984
    """
    if rational:
        return (-1)**(g+1) * 4 * factorial(2*g) / ( (2*g-1)*2*g*(2*g+1) * 2**(4*g-2) * bernoulli(2*g) * factorial(g-1)**2 )
    else:
        return 2*pi**(2*g) / ( (2*g-1)*2*g*(2*g+1) * 2**(2*g-2) * factorial(g-1)**2 )
Exemplo n.º 12
0
    def count(self, n):
        """
        Return the number of structures of size ``n``.

        EXAMPLES::

            sage: from sage.combinat.species.generating_series import ExponentialGeneratingSeriesRing
            sage: R = ExponentialGeneratingSeriesRing(QQ)
            sage: f = R([1])
            sage: [f.count(i) for i in range(7)]
            [1, 1, 2, 6, 24, 120, 720]
        """
        return factorial(n) * self.coefficient(n)
Exemplo n.º 13
0
    def _gs_iterator(self, base_ring):
        """
        The generating series for the species of subsets is
        `e^{2x}`.

        EXAMPLES::

            sage: S = species.SubsetSpecies()
            sage: S.generating_series().coefficients(5)
            [1, 2, 2, 4/3, 2/3]
        """
        for n in _integers_from(0):
            yield base_ring(2)**n / base_ring(factorial(n))
Exemplo n.º 14
0
    def _card(self, n):
        r"""
        Return the number of structures on an underlying set of size ``n`` for
        the species associated with ``self``.

        This is just ``n!`` times the coefficient of ``p[1]n`` in ``self``.

        EXAMPLES::

            sage: cis = species.PartitionSpecies().cycle_index_series()
            sage: cis._card(4)
            15
        """
        p = self.coefficient(n)
        return factorial(n) * p.coefficient([1] * n)
Exemplo n.º 15
0
    def _gs_iterator(self, base_ring):
        r"""
        The generating series for the species of sets is given by
        `e^x`.

        EXAMPLES::

            sage: S = species.SetSpecies()
            sage: g = S.generating_series()
            sage: g.coefficients(10)
            [1, 1, 1/2, 1/6, 1/24, 1/120, 1/720, 1/5040, 1/40320, 1/362880]
            sage: [g.count(i) for i in range(10)]
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        """
        for n in _integers_from(0):
            yield base_ring(self._weight / factorial(n))
Exemplo n.º 16
0
    def cardinality(self):
        r"""
        Count the number of linear extensions using a hook-length formula.

        EXAMPLES::

            sage: from sage.combinat.posets.poset_examples import Posets
            sage: P = Posets.YoungDiagramPoset(Partition([3,2]), dual=True)
            sage: P.linear_extensions().cardinality()
            5
        """
        num_elmts = self._poset.cardinality()

        if num_elmts == 0:
            return 1

        hook_product = self._poset.hook_product()
        return factorial(num_elmts) // hook_product
Exemplo n.º 17
0
    def write(self, g, n, s=None):
        r"""
        Print normalized values of the polynomials F_{g,n}
        """
        g = ZZ(g)
        n = ZZ(n)
        if n < 0:
            raise ValueError
        if s is None:
            s = range(3 * g - 3 + n + 1)
        elif isinstance(s, numbers.Integral):
            s = [s]

        for t in s:
            for p in Partitions(t + n, length=n):
                p = [i - 1 for i in p]
                c = prod(factorial(2 * i + 1) for i in p)
                f = self.F(g, n, p)
                if f:
                    print("{} {}".format([i for i in p], self.F(g, n, p) / c))
Exemplo n.º 18
0
    def _functorial_compose_gen(self, y, ao):
        """
        Returns a generator for the coefficients of the functorial
        composition of self with y.

        EXAMPLES::

            sage: E = species.SetSpecies()
            sage: E2 = E.restricted(min=2, max=3)
            sage: WP = species.SubsetSpecies()
            sage: P2 = E2*E
            sage: g1 = WP.generating_series()
            sage: g2 = P2.generating_series()
            sage: g = g1._functorial_compose_gen(g2, 0)
            sage: [next(g) for i in range(10)]
            [1, 1, 1, 4/3, 8/3, 128/15, 2048/45, 131072/315, 2097152/315, 536870912/2835]
        """
        n = 0
        while True:
            yield self.count(y.count(n)) / factorial(n)
            n += 1
Exemplo n.º 19
0
            def to_symmetric_function(self):
                r"""
                Take a function in the `\mathbf{w}` basis, and return its
                symmetric realization, when possible, expressed in the
                homogeneous basis of symmetric functions.

                OUTPUT:

                - If ``self`` is a symmetric function, then the expansion
                  in the homogeneous basis of the symmetric functions is returned.
                  Otherwise an error is raised.

                EXAMPLES::

                    sage: w = SymmetricFunctionsNonCommutingVariables(QQ).dual().w()
                    sage: elt = w[[1],[2,3]] + w[[1,2],[3]] + w[[1,3],[2]]
                    sage: elt.to_symmetric_function()
                    h[2, 1]
                    sage: elt = w.sum_of_partitions([2,1,1]) / 2
                    sage: elt.to_symmetric_function()
                    1/2*h[2, 1, 1]

                TESTS::

                    sage: w = SymmetricFunctionsNonCommutingVariables(QQ).dual().w()
                    sage: w(0).to_symmetric_function()
                    0
                    sage: w([]).to_symmetric_function()
                    h[]
                    sage: (2*w([])).to_symmetric_function()
                    2*h[]
                """
                if not self.is_symmetric():
                    raise ValueError("not a symmetric function")
                h = SymmetricFunctions(self.parent().base_ring()).homogeneous()
                d = {A.shape(): c for A, c in self}
                return h.sum_of_terms(
                    [(AA, cc / prod([factorial(_) for _ in AA.to_exp()]))
                     for AA, cc in d.items()],
                    distinct=True)
Exemplo n.º 20
0
def coeff_sp(J,I):
    r"""
    Returns the coefficient `sp_{J,I}` as defined in [NCSF]_.

    INPUT:

    - ``J`` -- a composition
    - ``I`` -- a composition refining ``J``

    OUTPUT:

    - integer

    EXAMPLES::

        sage: from sage.combinat.ncsf_qsym.combinatorics import coeff_sp
        sage: coeff_sp(Composition([1,1,1]), Composition([2,1]))
        2
        sage: coeff_sp(Composition([2,1]), Composition([3]))
        4
    """
    return prod(factorial(len(K))*prod(K) for K in J.refinement_splitting(I))
Exemplo n.º 21
0
        def idempotent(self, la):
            """
            Return the idempotent corresponding to the partition ``la``
            of `n`.

            EXAMPLES::

                sage: I = DescentAlgebra(QQ, 4).I()
                sage: E = I.idempotent([3,1]); E
                1/2*I[1, 3] + 1/2*I[3, 1]
                sage: E*E == E
                True
                sage: E2 = I.idempotent([2,1,1]); E2
                1/6*I[1, 1, 2] + 1/6*I[1, 2, 1] + 1/6*I[2, 1, 1]
                sage: E2*E2 == E2
                True
                sage: E*E2 == I.zero()
                True
            """
            from sage.combinat.permutation import Permutations
            k = len(la)
            C = Compositions(self.realization_of()._n)
            return self.sum_of_terms([(C(x), QQ((1, factorial(k))))
                                      for x in Permutations(la)])
Exemplo n.º 22
0
 def f(partition):
     n = partition.size()
     return (StandardTableaux(partition).cardinality() * t**n /
             factorial(n))
Exemplo n.º 23
0
    def cardinality(self):
        r"""
        Return the number of linear extensions by using the determinant
        formula for counting linear extensions of mobiles.

        EXAMPLES::

            sage: from sage.combinat.posets.mobile import MobilePoset
            sage: M = MobilePoset(DiGraph([[0,1,2,3,4,5,6,7,8], [(1,0),(3,0),(2,1),(2,3),(4,
            ....: 3), (5,4),(5,6),(7,4),(7,8)]]))
            sage: M.linear_extensions().cardinality()
            1098

            sage: M1 = posets.RibbonPoset(6, [1,3])
            sage: M1.linear_extensions().cardinality()
            61

            sage: P = posets.MobilePoset(posets.RibbonPoset(7, [1,3]), {1:
            ....: [posets.YoungDiagramPoset([3, 2], dual=True)], 3: [posets.DoubleTailedDiamond(6)]},
            ....: anchor=(4, 2, posets.ChainPoset(6)))
            sage: P.linear_extensions().cardinality()
            361628701868606400
        """
        import sage.combinat.posets.d_complete as dc
        # Find folds
        if self._poset._anchor:
            anchor_index = self._poset._ribbon.index(self._poset._anchor[0])
        else:
            anchor_index = len(self._poset._ribbon)

        folds_up = []
        folds_down = []

        for ind, r in enumerate(self._poset._ribbon[:-1]):
            if ind < anchor_index and self._poset.is_greater_than(r, self._poset._ribbon[ind + 1]):
                folds_up.append((self._poset._ribbon[ind + 1], r))
            elif ind >= anchor_index and self._poset.is_less_than(r, self._poset._ribbon[ind + 1]):
                folds_down.append((r, self._poset._ribbon[ind + 1]))

        if not folds_up and not folds_down:
            return dc.DCompletePoset(self._poset).linear_extensions().cardinality()

        # Get ordered connected components
        cr = self._poset.cover_relations()
        foldless_cr = [tuple(c) for c in cr if tuple(c) not in folds_up and tuple(c) not in folds_down]

        elmts = list(self._poset._elements)
        poset_components = DiGraph([elmts, foldless_cr])
        ordered_poset_components = [poset_components.connected_component_containing_vertex(f[1], sort=False)
                                    for f in folds_up]
        ordered_poset_components.extend(poset_components.connected_component_containing_vertex(f[0], sort=False)
                                        for f in folds_down)
        ordered_poset_components.append(poset_components.connected_component_containing_vertex(
            folds_down[-1][1] if folds_down else folds_up[-1][0], sort=False))

        # Return determinant

        # Consoludate the folds lists
        folds = folds_up
        folds.extend(folds_down)

        mat = []
        for i in range(len(folds) + 1):
            mat_poset = dc.DCompletePoset(self._poset.subposet(ordered_poset_components[i]))
            row = [0] * (i - 1 if i - 1 > 0 else 0) + [1] * (1 if i >= 1 else 0)
            row.append(1 / mat_poset.hook_product())
            for j, f in enumerate(folds[i:]):
                next_poset = self._poset.subposet(ordered_poset_components[j + i + 1])
                mat_poset = dc.DCompletePoset(next_poset.slant_sum(mat_poset, f[0], f[1]))
                row.append(1 / mat_poset.hook_product())

            mat.append(row)
        return matrix(QQ, mat).determinant() * factorial(self._poset.cardinality())