|
65 | 65 | from sage.combinat.integer_vector_weighted import WeightedIntegerVectors
|
66 | 66 | from sage.functions.generalized import sgn
|
67 | 67 | from sage.functions.log import log
|
68 |
| -from sage.functions.other import floor, ceil |
| 68 | +from sage.functions.other import floor, ceil, frac |
69 | 69 | from sage.misc.cachefunc import cached_method
|
70 | 70 | from sage.misc.functional import cyclotomic_polynomial
|
71 | 71 | from sage.misc.misc_c import prod
|
|
74 | 74 | from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
|
75 | 75 | from sage.rings.integer_ring import ZZ
|
76 | 76 | from sage.rings.padics.padic_generic_element import gauss_table
|
77 |
| -from sage.rings.polynomial.polynomial_ring import polygen |
| 77 | +from sage.rings.polynomial.polynomial_ring import polygen, polygens |
78 | 78 | from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
79 | 79 | from sage.rings.power_series_ring import PowerSeriesRing
|
80 | 80 | from sage.rings.rational_field import QQ
|
81 | 81 | from sage.schemes.generic.spec import Spec
|
82 | 82 | from sage.rings.finite_rings.finite_field_constructor import GF
|
83 | 83 | from sage.rings.universal_cyclotomic_field import UniversalCyclotomicField
|
84 | 84 |
|
| 85 | + |
85 | 86 | def characteristic_polynomial_from_traces(traces, d, q, i, sign):
|
86 | 87 | r"""
|
87 | 88 | Given a sequence of traces `t_1, \dots, t_k`, return the
|
@@ -899,6 +900,80 @@ def hodge_polygon_vertices(self):
|
899 | 900 | lst.append((lst[-1][0] + hn[i], lst[-1][1] + i * hn[i]))
|
900 | 901 | return lst
|
901 | 902 |
|
| 903 | + def E_polynomial(self, vars=None): |
| 904 | + """ |
| 905 | + Return the E-polynomial of ``self``. |
| 906 | +
|
| 907 | + This is a bivariate polynomial. |
| 908 | +
|
| 909 | + The algorithm is taken from [FRV2019]_. |
| 910 | +
|
| 911 | + INPUT: |
| 912 | +
|
| 913 | + - ``vars`` -- optional pair of variables (default `u,v`) |
| 914 | +
|
| 915 | + REFERENCES: |
| 916 | +
|
| 917 | + .. [FRV2019] Fernando Rodriguez Villegas, *Mixed Hodge numbers |
| 918 | + and factorial ratios*, :arxiv:`1907.02722` |
| 919 | +
|
| 920 | + EXAMPLES:: |
| 921 | +
|
| 922 | + sage: from sage.modular.hypergeometric_motive import HypergeometricData |
| 923 | + sage: H = HypergeometricData(gamma_list=[-30,-1,6,10,15]) |
| 924 | + sage: H.E_polynomial() |
| 925 | + 8*u*v + 7*u + 7*v + 8 |
| 926 | +
|
| 927 | + sage: p, q = polygens(QQ,'p,q') |
| 928 | + sage: H.E_polynomial((p, q)) |
| 929 | + 8*p*q + 7*p + 7*q + 8 |
| 930 | +
|
| 931 | + sage: H = HypergeometricData(gamma_list=(-11, -2, 1, 3, 4, 5)) |
| 932 | + sage: H.E_polynomial() |
| 933 | + 5*u^2*v + 5*u*v^2 + u*v + 1 |
| 934 | +
|
| 935 | + sage: H = HypergeometricData(gamma_list=(-63, -8, -2, 1, 4, 16, 21, 31)) |
| 936 | + sage: H.E_polynomial() |
| 937 | + 21*u^3*v^2 + 21*u^2*v^3 + u^3*v + 23*u^2*v^2 + u*v^3 + u^2*v + u*v^2 + 2*u*v + 1 |
| 938 | + """ |
| 939 | + gamma = self.gamma_list() |
| 940 | + ell = len(gamma) |
| 941 | + |
| 942 | + gamma_plus = [g for g in gamma if g > 0] |
| 943 | + gamma_minus = [g for g in gamma if g < 0] |
| 944 | + |
| 945 | + domain = set(d for g in gamma for d in divisors(g.abs())) |
| 946 | + |
| 947 | + m_plus = {d: len([1 for g in gamma_plus if not g % d]) |
| 948 | + for d in domain} |
| 949 | + |
| 950 | + m_minus = {d: len([1 for g in gamma_minus if not g % d]) |
| 951 | + for d in domain} |
| 952 | + |
| 953 | + if vars is None: |
| 954 | + u, v = polygens(ZZ, 'u,v') |
| 955 | + else: |
| 956 | + u, v = vars |
| 957 | + uqv = u / v |
| 958 | + uv = u * v |
| 959 | + |
| 960 | + A = u.parent() |
| 961 | + delta_sharp_N = {d: A.sum(uqv**sum(frac(j * gi / d) for gi in gamma) |
| 962 | + for j in d.coprime_integers(d)) |
| 963 | + for d in domain} |
| 964 | + |
| 965 | + loop = [(d, m_plus[d], m_minus[d]) for d in domain] |
| 966 | + |
| 967 | + delta_sharp = sum((uqv**m - uqv**p) // (uqv - 1) * v**(ell - 1) |
| 968 | + * delta_sharp_N[d] |
| 969 | + for d, p, m in loop if m > p) |
| 970 | + |
| 971 | + delta_zero = sum((uv**min(m, p) - 1) // (uv - 1) * v**(ell - m - p) |
| 972 | + * delta_sharp_N[d] |
| 973 | + for d, p, m in loop) |
| 974 | + |
| 975 | + return (delta_sharp + delta_zero - 1).numerator() // (u * v) |
| 976 | + |
902 | 977 | def M_value(self):
|
903 | 978 | """
|
904 | 979 | Return the `M` coefficient that appears in the trace formula.
|
|
0 commit comments