Let's investigate the conjecture on elliptic periods.
We want to find a counter-example, i.e., we want to find a curve over $\mathbb{F}_p$ such that a subgroup of order $ℓ$ is defined over an extension of degree $r|(ℓ-1)$, and such that the periods of that subgroup fall in a field smaller than $\mathbb{F}_{p^r}$.
To avoid pitfalls, we prefer having $r>2$, $ℓ≠p$, and maybe even $r≠p$. Since we have to mod-out the automorphisms of the curve, the smallest possible $ℓ$ to exhibit a counter-example is $13$, so that $(ℤ/13ℤ)^*/\{±1\}=\mathcal{C}_2\times\mathcal{C}_3$.
So, let's set $ℓ=13$, $r=3$. The elliptic period is defined as $x(P)+x([5]P)$ for $P$ a point of order 13 in a well chosen subgroup.
We look for a curve that has $13$-torsion points in an extension of degree $3$.
Here's an idea to generate tons of examples: take a curve over $ℚ$ with this property, and reduce modulo many primes. We are lucky: there are infinitely many such curves (http://arxiv.org/pdf/1211.2188.pdf, prop 31), and one such example is curve 147b1
in Cremona's database.
E = EllipticCurve('147b1')
E
Elliptic Curve defined by y^2 + y = x^3 + x^2 - 114*x + 473 over Rational Field
The curve is singular at $3$ and $7$
E.discriminant().factor()
-1 * 3 * 7^8
And certainly supersingular at $2$
E.j_invariant(), E.j_invariant().factor()
(-28672/3, -1 * 2^12 * 3^-1 * 7)
It's $13$-division polynomial factors as expected
[f[0].degree() for f in E.division_polynomial(13).factor()]
[3, 3, 78]
facts = E.division_polynomial(13).factor()[:2]
facts
[(x^3 - 48*x^2 + 425*x - 1009, 1), (x^3 + x^2 - 114*x - 127, 1)]
Let's look at multiplication by $5$. It's action on the abscissa is given by a rational fraction in $x$.
mul5 = E.multiplication_by_m(5, x_only=True)
mul5
(x^25 + 11400*x^23 - 952440*x^22 + 21459390*x^21 - 109428732*x^20 - 4950010695*x^19 + 144784682400*x^18 - 181243777785*x^17 - 76264253249145*x^16 + 1852228009144500*x^15 - 17751704371327800*x^14 - 13405942951098075*x^13 + 2174244297003851940*x^12 - 23804139576831231690*x^11 + 121433153419916125074*x^10 - 449464862928041129205*x^9 + 5800247633495175127650*x^8 - 83614774727436641897175*x^7 + 721566408459768769400580*x^6 - 4069574415747167715056277*x^5 + 16123970604415307494932945*x^4 - 46252779384036854092437225*x^3 + 94273994056986749224110510*x^2 - 123535079543891692412564130*x + 77552624336221526363279505)/(25*x^24 + 200*x^23 - 70120*x^22 + 1425070*x^21 + 48308554*x^20 - 2610219360*x^19 + 43594684875*x^18 - 67903799190*x^17 - 9897608934825*x^16 + 202483959479556*x^15 - 2037974926602780*x^14 + 6054274701348300*x^13 + 169194401041110165*x^12 - 3540471811324712460*x^11 + 39604874743194363378*x^10 - 306463233082971903660*x^9 + 1678785952137330965175*x^8 - 5689479606125098303260*x^7 + 3210444480296511269595*x^6 + 76839986296881639452124*x^5 - 379972558692366773002065*x^4 + 584163989209171893761550*x^3 + 1091490755999416581874005*x^2 - 5298108546577918019618340*x + 5764429991723000943803364)
As we expect, multiplication by $5$ sends the abscissas of one factor to the other. We can verify this with a resultant.
_.<x,y> = QQ[]
facts[0][0].resultant(mul5.denominator()*y - mul5.numerator()).univariate_polynomial().monic() == facts[1][0](y)
True
facts[1][0].resultant(mul5.denominator()*y - mul5.numerator()).univariate_polynomial().monic() == facts[0][0](y)
True
By the same resultant trick, we get the minimal polynomial of the elliptic period. Remember: the period is defined as $x(P)+x([5]P)$.
period = facts[0][0].resultant(mul5.denominator()*(y - x) - mul5.numerator()).univariate_polynomial()
period
1347137238494276547832006567721872890819326613454654477690085519113574118965817601*y^3 - 63315450209230997748104308682928025868508350832368760451434019398337983591393427247*y^2 + 375851289539903156845129832394402536538592125153848599275533859832687179191463110679*y + 5430310208370428764310818474486869622892705578835712199568734727546817273551210749631
Quite big coefficients, but let's look at the leading one
period.leading_coefficient().factor()
7^96
Ahah! Only the singular prime appears in it! Of course not a coincidence.
Let's simplify
period = period.monic()
period
y^3 - 47*y^2 + 279*y + 4031
Surprisingly short!
Just to be sure, let's check that this does not depend on the choice of the initial point.
facts[1][0].resultant(mul5.denominator()*(y - x) - mul5.numerator()).univariate_polynomial().monic() == period
True
So, now we look for a prime $p≠2,3,7$ such that the $13$-torsion points live in $\mathbb{F}_{p^3}$, but the period lives in $\mathbb{F}_p$.
We can read this directly on the polynomials.
def test(p):
R = PolynomialRing(GF(p), 'x')
return R(facts[0][0]).roots(), R(facts[1][0]).roots(), R(period).roots()
[(p,test(p)) for p in primes(100)]
[(2, ([], [], [(1, 3)])), (3, ([], [], [])), (5, ([], [], [])), (7, ([(2, 3)], [(2, 3)], [(4, 3)])), (11, ([], [], [])), (13, ([(10, 1), (8, 1), (4, 1)], [(12, 1), (7, 1), (6, 1)], [(4, 1), (3, 1), (1, 1)])), (17, ([], [], [])), (19, ([], [], [])), (23, ([], [], [])), (29, ([(27, 1), (15, 1), (6, 1)], [(23, 1), (22, 1), (12, 1)], [(0, 1), (27, 1), (20, 1)])), (31, ([], [], [])), (37, ([], [], [])), (41, ([(24, 1), (19, 1), (5, 1)], [(18, 1), (15, 1), (7, 1)], [(26, 1), (20, 1), (1, 1)])), (43, ([(31, 1), (10, 1), (7, 1)], [(21, 1), (15, 1), (6, 1)], [(28, 1), (16, 1), (3, 1)])), (47, ([], [], [])), (53, ([], [], [])), (59, ([], [], [])), (61, ([], [], [])), (67, ([], [], [])), (71, ([(69, 1), (35, 1), (15, 1)], [(30, 1), (29, 1), (11, 1)], [(64, 1), (28, 1), (26, 1)])), (73, ([], [], [])), (79, ([], [], [])), (83, ([(61, 1), (51, 1), (19, 1)], [(72, 1), (69, 1), (24, 1)], [(50, 1), (43, 1), (37, 1)])), (89, ([], [], [])), (97, ([(78, 1), (36, 1), (31, 1)], [(95, 1), (80, 1), (18, 1)], [(76, 1), (49, 1), (19, 1)]))]
Bad luck! Or maybe not.
One thing is obvious: if the first two split, the third splits as well. The opposite is less obvious. Let's work it out.
Call $P_1$ and $P_2$ the two factors of $φ_{13}$ of degree $3$. We want to prove that if $P_1$ (and $P_2$) is irreducible, then the minimal polynomial of the period is irreducible too. Let's suppose this is not the case and see what happens.
The first component of the multiplication-by-$5$ defines a rational mapping $I(x) = ψ_5(x)/φ_5^2(x)$. Since the only poles of $I(x)$ are in $E[5]$, its restriction to $V(P_1P_2)$ defines a polynomial mapping $i(x) = I(x) \bmod P_1P_2$, sending the roots of $P_1$ onto the roots of $P_2$ and vice-versa. This is obvious from the properties of the resultant, but let's double check.
A = QQ['x'].quo(facts[0][0]*facts[1][0])
facts[0][0].resultant(y - mul5(A.gen()).lift()) == facts[1][0](y)
True
facts[1][0].resultant(y - mul5(A.gen()).lift()) == facts[0][0](y)
True
The mapping $x + i(x)$ sends the roots of $P_1$ and the roots of $P_2$ onto the ellptic periods. If we suppose that $\mathrm{Res}_x(P_1(x), y - x - i(x)) = \mathrm{Res}_x(P_2(x), y - x - i(x))$ splits over $\mathbb{F}_p$, then by Galois invariance $x + i(x) = t \bmod P_1$ for a constant $t∈\mathbb{F}_p$, and since the periods do not depend on the initial choice of $P_1$ or $P_2$, we conclude that $i(x) = (t - x) \bmod P_1P_2$.
Hence, we can just compute $x + i(x) \bmod P_1P_2$ and see for what primes it is a constant.
x + mul5(A.gen()).lift()
12/16807*x^5 - 526/16807*x^4 + 1572/16807*x^3 + 58484/16807*x^2 - 308958/16807*x + 194559/16807
factor(16807)
7^5
gcd([526, 1572, 58484, 308958])
2
No suprise: $7$ is the only divisor in the denominators.
And bad news: the only prime that divides all coefficients is $2$, but we had ruled this one out before. So no reduction of $E$ is ever going to yield a counter-example.
Just for completeness, let's do the same check using norms instead of traces
period2 = facts[0][0].resultant(mul5.denominator()*y - x*mul5.numerator()).univariate_polynomial()
period2
1347137238494276547832006567721872890819326613454654477690085519113574118965817601*y^3 + 21554195815908424765312105083549966253109225815274471643041368305817185903453081616*y^2 - 5583883853558776290763667223207163132446108812769542810025404476725764723113313956145*y - 172626207152372079668836817607583957848260970227919788734640628675770728326636764844943
period2.leading_coefficient().factor()
7^96
period2 = period2.monic()
period2
y^3 + 16*y^2 - 4145*y - 128143
facts[1][0].resultant(mul5.denominator()*y - x*mul5.numerator()).univariate_polynomial().monic() == period2
True
((mul5)(A.gen()) * A.gen()).lift()
38/16807*x^5 - 1584/16807*x^4 + 1352/16807*x^3 + 194591/16807*x^2 - 538053/16807*x - 1537716/16807
gcd([1584, 1352, 194591, 538053])
1
At least now we have a criterion to do a brute-force search relatively fast: look for a curve $E/\mathbb{F}_p$ such that its $13$-division polynomial has two factors of degree $3$, and such that multiplication-by-$5$ modulo these two factors equals $t-x$ for some constant $t∈\mathbb{F}_p$.
This criterion easily extends to all primes $r,ℓ$ such that $4r=ℓ-1$ and where $i^2=-1\bmod ℓ$.
def test_p(ell, r, i, p):
count = 0
ex = []
for j in GF(p):
if j != 0 and j != 1728:
E = EllipticCurve(j=j)
phi = E.division_polynomial(ell)
x = phi.parent().gen()
f = gcd(phi, pow(x, p**r, phi) - x)
if f.degree() == 2*r:
count += 1
I = E.multiplication_by_m(i, x_only=True)
I = I.numerator().mod(f) * I.denominator().inverse_mod(f) % f
if (I + x).degree() <= 0:
ex.append(E)
return count, ex
def test_ell(ell, max_p=Infinity):
r = (ell - 1)//4
assert(is_prime(r))
i = Zmod(ell)(-1).sqrt()
i = min(i, -i).lift()
p = 3
ex = []
while p <= max_p:
t = test_p(ell, r, i, p)
print p, t, ex
if t[1]:
ex.append(t)
p = next_prime(p)
return ex
test_ell(13, 100)
3 (0, []) [] 5 (1, []) [] 7 (2, []) [] 11 (5, []) [] 13 (5, []) [] 17 (0, []) [] 19 (8, []) [] 23 (0, []) [] 29 (4, []) [] 31 (14, []) [] 37 (16, []) [] 41 (19, []) [] 43 (0, []) [] 47 (23, []) [] 53 (8, []) [] 59 (29, []) [] 61 (10, []) [] 67 (32, []) [] 71 (35, []) [] 73 (34, []) [] 79 (10, []) [] 83 (41, []) [] 89 (43, []) [] 97 (46, []) []
[]
test_ell(29, 100)
3 (0, []) [] 5 (0, []) [] 7 (0, []) [] 11 (4, []) [] 13 (0, []) [] 17 (9, []) [] 19 (3, []) [] 23 (0, []) [] 29 (15, []) [] 31 (12, []) [] 37 (21, []) [] 41 (15, []) [] 43 (16, []) [] 47 (22, []) [] 53 (4, []) [] 59 (2, []) [] 61 (31, []) [] 67 (0, []) [] 71 (0, []) [] 73 (31, []) [] 79 (40, []) [] 83 (2, []) [] 89 (47, []) [] 97 (51, []) []
[]
I'm testing $ℓ=13,29,53$. No luck so far (tested some thousands of primes).
The test is quite slow, mainly due to the factorization step in test_p
. Using modular polynomials à la SEA could speed it up a bit.
It was suggested that we use sage.schemes.elliptic_curves.isogeny_small_degree.isogenies_prime_degree_genus_0
for $ℓ=13,29$, but a quick profiling shows that this function is (significantly) slower than our naive factorization.
Finally, we can generalize the test we performed on 147b1
to other curves over $ℚ$ that have 13-torsion points in a cubic extension.
Table 1 in http://arxiv.org/pdf/1509.00528v2.pdf parameterizes these curves by
$$j(t) = \frac{(t^4 - t^3 + 5t^2 + t + 1)(t^8 - 5t^7 + 7t^6 - 5t^5 + 5t^3 + 7t^2 + 5t + 1)^3}{t^{13} (t^2 - 3t - 1)}.$$Below is a very fast test that runs through all this curves, and looks for prime factors common to all coefficients of $x+i(x)\bmod P_1P_2$, except the constant coefficient, and excluding singular primes and those that yield $j$-invariant $0$ and $1728$.
def test_X0(T=QQ, period=None):
_.<t> = QQ[]
j = (t^4 - t^3 + 5*t^2 + t + 1)*(t^8 - 5*t^7 + 7*t^6 - 5*t^5 + 5*t^3 + 7*t^2 + 5*t + 1)^3/(t^13 * (t^2 - 3*t - 1))
ex = []
if period is None:
period = lambda I: I + I.parent().gen()
for t in T:
if t != 0:
E = EllipticCurve(j=j(t)) # this is the slowest computation
I = period(E.multiplication_by_m(5, x_only=True))
for phi in E.isogenies_prime_degree(13):
f = phi.kernel_polynomial().factor()[0][0]
m = I.numerator().mod(f) * I.denominator().inverse_mod(f) % f
J = E.j_invariant()
badp = E.discriminant() * J.numerator() * (J-1728).numerator()
goodp = filter(lambda (p,m): not p.divides(badp), gcd(m[1:]).factor())
if goodp:
ex.append((t, J, goodp))
print t, J, ex
We can test the conjecture for traces and norms
from itertools import islice
test_X0(islice(QQ, 20))
1 -28672/3 [] -1 -28672/3 [] 1/2 -140246460241/73728 [] -1/2 152303/24576 [] 2 152303/24576 [] -2 -140246460241/73728 [] 1/3 -2017252899377152/27103491 [] -1/3 2072735744/1594323 [] 3 2072735744/1594323 [] -3 -2017252899377152/27103491 [] 2/3 -55698160846329217/300395962368 [] -2/3 -3924067587589/13060694016 [] 3/2 -3924067587589/13060694016 [] -3/2 -55698160846329217/300395962368 [] 1/4 -2354926657441487617/1811939328 [] -1/4 122607109504897/201326592 [] 4 122607109504897/201326592 [] -4 -2354926657441487617/1811939328 [] 3/4 -349809498592264034737/4600707831300096 []
test_X0(islice(QQ, 20), lambda I: I * I.parent().gen())
1 -28672/3 [] -1 -28672/3 [] 1/2 -140246460241/73728 [] -1/2 152303/24576 [] 2 152303/24576 [] -2 -140246460241/73728 [] 1/3 -2017252899377152/27103491 [] -1/3 2072735744/1594323 [] 3 2072735744/1594323 [] -3 -2017252899377152/27103491 [] 2/3 -55698160846329217/300395962368 [] -2/3 -3924067587589/13060694016 [] 3/2 -3924067587589/13060694016 [] -3/2 -55698160846329217/300395962368 [] 1/4 -2354926657441487617/1811939328 [] -1/4 122607109504897/201326592 [] 4 122607109504897/201326592 [] -4 -2354926657441487617/1811939328 [] 3/4 -349809498592264034737/4600707831300096 []
We're intensively testing the conjecture for many more $j$-invariants, and no counter-example has been found yet.
On the other hand, to vaguely support the conjecture, perturbing the period function just slightly quickly yields common factors:
test_X0(islice(QQ, 10), lambda I: I + I.parent().gen()^2)
1 -28672/3 [] -1 -28672/3 [] 1/2 -140246460241/73728 [] -1/2 152303/24576 [] 2 152303/24576 [] -2 -140246460241/73728 [] 1/3 -2017252899377152/27103491 [] -1/3 2072735744/1594323 [(-1/3, 2072735744/1594323, [(19, 1)])] 3 2072735744/1594323 [(-1/3, 2072735744/1594323, [(19, 1)]), (3, 2072735744/1594323, [(19, 1)])]
test_X0(range(11), lambda I: I + I.parent().gen()^3)
1 -28672/3 [] 2 152303/24576 [] 3 2072735744/1594323 [] 4 122607109504897/201326592 [] 5 533792153118969856/10986328125 [] 6 233420288435867735377/222031798272 [] 7 31497655516265535188992/2616003280989 [] 8 152136674190176801141317/1649267441664 [] 9 71737321403335622493417472/134718888901437 [] 10 1715948050978542408916511761/690000000000000 [(10, 1715948050978542408916511761/690000000000000, [(29, 1)])]
test_X0([48, 80], lambda I: I - I.parent().gen()^3)
48 84645560883547843260626938593288714317943248641/15502035539941028184195072 [(48, 84645560883547843260626938593288714317943248641/15502035539941028184195072, [(13, 1)])] 80 158059455224004445519963223677801007293951562732263681/33859460577361920000000000000 [(48, 84645560883547843260626938593288714317943248641/15502035539941028184195072, [(13, 1)]), (80, 158059455224004445519963223677801007293951562732263681/33859460577361920000000000000, [(23, 1)])]