Testing whether elliptic curves over number fields are Q-curves#

AUTHORS:

  • John Cremona (February 2021)

The code here implements the algorithm of Cremona and Najman presented in [CrNa2020].

sage.schemes.elliptic_curves.Qcurves.Step4Test(E, B, oldB=0, verbose=False)[source]#

Apply local Q-curve test to E at all primes up to B.

INPUT:

  • E (elliptic curve): an elliptic curve defined over a number field

  • B (integer): upper bound on primes to test

  • oldB (integer, default 0): lower bound on primes to test

  • verbose (boolean, default False): verbosity flag

OUTPUT:

Either (False, p), if the local test at p proves that E is not a Q-curve, or (True, 0) if all local tests at primes between oldB and B fail to prove that E is not a Q-curve.

ALGORITHM (see [CrNa2020] for details):

This local test at p only applies if E has good reduction at all of the primes lying above p in the base field K of E. It tests whether (1) E is either ordinary at all Pp, or supersingular at all; (2) if ordinary at all, it tests that the squarefree part of aP24N(P) is the same for all Pp.

EXAMPLES:

A non-Q-curve over a quartic field (with LMFDB label ‘4.4.8112.1-12.1-a1’) fails this test at p=13:

sage: from sage.schemes.elliptic_curves.Qcurves import Step4Test
sage: R.<x> = PolynomialRing(QQ)
sage: K.<a> = NumberField(R([3, 0, -5, 0, 1]))                                  # needs sage.rings.number_field
sage: E = EllipticCurve([K([-3,-4,1,1]), K([4,-1,-1,0]), K([-2,0,1,0]),         # needs sage.rings.number_field
....:                    K([-621,778,138,-178]), K([9509,2046,-24728,10380])])
sage: Step4Test(E, 100, verbose=True)                                           # needs sage.rings.number_field
No: inconsistency at the 2 ordinary primes dividing 13
- Frobenius discriminants mod squares: [-3, -1]
(False, 13)
from sage.schemes.elliptic_curves.Qcurves import Step4Test
R.<x> = PolynomialRing(QQ)
K.<a> = NumberField(R([3, 0, -5, 0, 1]))                                  # needs sage.rings.number_field
E = EllipticCurve([K([-3,-4,1,1]), K([4,-1,-1,0]), K([-2,0,1,0]),         # needs sage.rings.number_field
                   K([-621,778,138,-178]), K([9509,2046,-24728,10380])])
Step4Test(E, 100, verbose=True)                                           # needs sage.rings.number_field
>>> from sage.all import *
>>> from sage.schemes.elliptic_curves.Qcurves import Step4Test
>>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1)
>>> K = NumberField(R([Integer(3), Integer(0), -Integer(5), Integer(0), Integer(1)]), names=('a',)); (a,) = K._first_ngens(1)# needs sage.rings.number_field
>>> E = EllipticCurve([K([-Integer(3),-Integer(4),Integer(1),Integer(1)]), K([Integer(4),-Integer(1),-Integer(1),Integer(0)]), K([-Integer(2),Integer(0),Integer(1),Integer(0)]),         # needs sage.rings.number_field
...                    K([-Integer(621),Integer(778),Integer(138),-Integer(178)]), K([Integer(9509),Integer(2046),-Integer(24728),Integer(10380)])])
>>> Step4Test(E, Integer(100), verbose=True)                                           # needs sage.rings.number_field
No: inconsistency at the 2 ordinary primes dividing 13
- Frobenius discriminants mod squares: [-3, -1]
(False, 13)

A Q-curve over a sextic field (with LMFDB label ‘6.6.1259712.1-64.1-a6’) passes this test for all p<100:

sage: from sage.schemes.elliptic_curves.Qcurves import Step4Test
sage: R.<x> = PolynomialRing(QQ)
sage: K.<a> = NumberField(R([-3, 0, 9, 0, -6, 0, 1]))                           # needs sage.rings.number_field
sage: E = EllipticCurve([K([1,-3,0,1,0,0]), K([5,-3,-6,1,1,0]),                 # needs sage.rings.number_field
....:                    K([1,-3,0,1,0,0]), K([-139,-129,331,277,-76,-63]),
....:                    K([2466,1898,-5916,-4582,1361,1055])])
sage: Step4Test(E, 100, verbose=True)                                           # needs sage.rings.number_field
(True, 0)
from sage.schemes.elliptic_curves.Qcurves import Step4Test
R.<x> = PolynomialRing(QQ)
K.<a> = NumberField(R([-3, 0, 9, 0, -6, 0, 1]))                           # needs sage.rings.number_field
E = EllipticCurve([K([1,-3,0,1,0,0]), K([5,-3,-6,1,1,0]),                 # needs sage.rings.number_field
                   K([1,-3,0,1,0,0]), K([-139,-129,331,277,-76,-63]),
                   K([2466,1898,-5916,-4582,1361,1055])])
Step4Test(E, 100, verbose=True)                                           # needs sage.rings.number_field
>>> from sage.all import *
>>> from sage.schemes.elliptic_curves.Qcurves import Step4Test
>>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1)
>>> K = NumberField(R([-Integer(3), Integer(0), Integer(9), Integer(0), -Integer(6), Integer(0), Integer(1)]), names=('a',)); (a,) = K._first_ngens(1)# needs sage.rings.number_field
>>> E = EllipticCurve([K([Integer(1),-Integer(3),Integer(0),Integer(1),Integer(0),Integer(0)]), K([Integer(5),-Integer(3),-Integer(6),Integer(1),Integer(1),Integer(0)]),                 # needs sage.rings.number_field
...                    K([Integer(1),-Integer(3),Integer(0),Integer(1),Integer(0),Integer(0)]), K([-Integer(139),-Integer(129),Integer(331),Integer(277),-Integer(76),-Integer(63)]),
...                    K([Integer(2466),Integer(1898),-Integer(5916),-Integer(4582),Integer(1361),Integer(1055)])])
>>> Step4Test(E, Integer(100), verbose=True)                                           # needs sage.rings.number_field
(True, 0)
sage.schemes.elliptic_curves.Qcurves.conjugacy_test(jlist, verbose=False)[source]#

Test whether a list of algebraic numbers contains a complete conjugacy class of 2-power degree.

INPUT:

  • jlist (list): a list of algebraic numbers in the same field

  • verbose (boolean, default False): verbosity flag

OUTPUT:

A possibly empty list of irreducible polynomials over Q of 2-power degree all of whose roots are in the list.

EXAMPLES:

sage: # needs sage.rings.number_field
sage: from sage.schemes.elliptic_curves.Qcurves import conjugacy_test
sage: conjugacy_test([3])
[x - 3]
sage: K.<a> = QuadraticField(2)
sage: conjugacy_test([K(3), a])
[x - 3]
sage: conjugacy_test([K(3), 3 + a])
[x - 3]
sage: conjugacy_test([3 + a])
[]
sage: conjugacy_test([3 + a, 3 - a])
[x^2 - 6*x + 7]
sage: x = polygen(QQ)
sage: f = x^3 - 3
sage: K.<a> = f.splitting_field()
sage: js = f.roots(K, multiplicities=False)
sage: conjugacy_test(js)
[]
sage: f = x^4 - 3
sage: K.<a> = NumberField(f)
sage: js = f.roots(K, multiplicities=False)
sage: conjugacy_test(js)
[]
sage: K.<a> = f.splitting_field()
sage: js = f.roots(K, multiplicities=False)
sage: conjugacy_test(js)
[x^4 - 3]
# needs sage.rings.number_field
from sage.schemes.elliptic_curves.Qcurves import conjugacy_test
conjugacy_test([3])
K.<a> = QuadraticField(2)
conjugacy_test([K(3), a])
conjugacy_test([K(3), 3 + a])
conjugacy_test([3 + a])
conjugacy_test([3 + a, 3 - a])
x = polygen(QQ)
f = x^3 - 3
K.<a> = f.splitting_field()
js = f.roots(K, multiplicities=False)
conjugacy_test(js)
f = x^4 - 3
K.<a> = NumberField(f)
js = f.roots(K, multiplicities=False)
conjugacy_test(js)
K.<a> = f.splitting_field()
js = f.roots(K, multiplicities=False)
conjugacy_test(js)
>>> from sage.all import *
>>> # needs sage.rings.number_field
>>> from sage.schemes.elliptic_curves.Qcurves import conjugacy_test
>>> conjugacy_test([Integer(3)])
[x - 3]
>>> K = QuadraticField(Integer(2), names=('a',)); (a,) = K._first_ngens(1)
>>> conjugacy_test([K(Integer(3)), a])
[x - 3]
>>> conjugacy_test([K(Integer(3)), Integer(3) + a])
[x - 3]
>>> conjugacy_test([Integer(3) + a])
[]
>>> conjugacy_test([Integer(3) + a, Integer(3) - a])
[x^2 - 6*x + 7]
>>> x = polygen(QQ)
>>> f = x**Integer(3) - Integer(3)
>>> K = f.splitting_field(names=('a',)); (a,) = K._first_ngens(1)
>>> js = f.roots(K, multiplicities=False)
>>> conjugacy_test(js)
[]
>>> f = x**Integer(4) - Integer(3)
>>> K = NumberField(f, names=('a',)); (a,) = K._first_ngens(1)
>>> js = f.roots(K, multiplicities=False)
>>> conjugacy_test(js)
[]
>>> K = f.splitting_field(names=('a',)); (a,) = K._first_ngens(1)
>>> js = f.roots(K, multiplicities=False)
>>> conjugacy_test(js)
[x^4 - 3]
sage.schemes.elliptic_curves.Qcurves.is_Q_curve(E, maxp=100, certificate=False, verbose=False)[source]#

Return whether E is a Q-curve, with optional certificate.

INPUT:

  • E (elliptic curve) – an elliptic curve over a number field.

  • maxp (int, default 100): bound on primes used for checking necessary local conditions. The result will not depend on this, but using a larger value may return False faster.

  • certificate (bool, default False): if True then a second value is returned giving a certificate for the Q-curve property.

OUTPUT:

If certificate is False: either True (if E is a Q-curve), or False.

If certificate is True: a tuple consisting of a boolean flag as before and a certificate, defined as follows:

  • when the flag is True, so E is a Q-curve:

    • either {‘CM’:D} where D is a negative discriminant, when E has potential CM with discriminant D;

    • otherwise {‘CM’: 0, ‘core_poly’: f, ‘rho’: ρ, ‘r’: r, ‘N’: N}, when E is a non-CM Q-curve, where the core polynomial f is an irreducible monic polynomial over QQ of degree 2ρ, all of whose roots are j-invariants of curves isogenous to E, the core level N is a square-free integer with r prime factors which is the LCM of the degrees of the isogenies between these conjugates. For example, if there exists a curve E isogenous to E with j(E)=jQ, then the certificate is {‘CM’:0, ‘r’:0, ‘rho’:0, ‘core_poly’: x-j, ‘N’:1}.

  • when the flag is False, so E is not a Q-curve, the certificate is a prime p such that the reductions of E at the primes dividing p are inconsistent with the property of being a Q-curve. See the ALGORITHM section for details.

ALGORITHM:

See [CrNa2020] for details.

1. If E has rational j-invariant, or has CM, then return True.

2. Replace E by a curve defined over K=Q(j(E)). Let N be the conductor norm.

3. For all primes pN check that the valuations of j at all Pp are either all negative or all non-negative; if not, return False.

4. For pmaxp, pN, check that either E is ordinary mod P for all Pp, or E is supersingular mod P for all Pp; if neither, return False. If all are ordinary, check that the integers aP(E)24N(P) have the same square-free part; if not, return False.

5. Compute the K-isogeny class of E using the “heuristic” option (which is faster, but not guaranteed to be complete). Check whether the set of j-invariants of curves in the class of 2-power degree contains a complete Galois orbit. If so, return True.

6. Otherwise repeat step 4 for more primes, and if still undecided, repeat Step 5 without the “heuristic” option, to get the complete K-isogeny class (which will probably be no bigger than before). Now return True if the set of j-invariants of curves in the class contains a complete Galois orbit, otherwise return False.

EXAMPLES:

A non-CM curve over Q and a CM curve over Q are both trivially Q-curves:

sage: from sage.schemes.elliptic_curves.Qcurves import is_Q_curve
sage: E = EllipticCurve([1,2,3,4,5])
sage: flag, cert = is_Q_curve(E, certificate=True)
sage: flag
True
sage: cert
{'CM': 0, 'N': 1, 'core_poly': x, 'r': 0, 'rho': 0}

sage: E = EllipticCurve(j=8000)
sage: flag, cert = is_Q_curve(E, certificate=True)
sage: flag
True
sage: cert
{'CM': -8}
from sage.schemes.elliptic_curves.Qcurves import is_Q_curve
E = EllipticCurve([1,2,3,4,5])
flag, cert = is_Q_curve(E, certificate=True)
flag
cert
E = EllipticCurve(j=8000)
flag, cert = is_Q_curve(E, certificate=True)
flag
cert
>>> from sage.all import *
>>> from sage.schemes.elliptic_curves.Qcurves import is_Q_curve
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)])
>>> flag, cert = is_Q_curve(E, certificate=True)
>>> flag
True
>>> cert
{'CM': 0, 'N': 1, 'core_poly': x, 'r': 0, 'rho': 0}

>>> E = EllipticCurve(j=Integer(8000))
>>> flag, cert = is_Q_curve(E, certificate=True)
>>> flag
True
>>> cert
{'CM': -8}

A non-Q-curve over a quartic field. The local data at bad primes above 3 is inconsistent:

sage: from sage.schemes.elliptic_curves.Qcurves import is_Q_curve
sage: R.<x> = PolynomialRing(QQ)
sage: K.<a> = NumberField(R([3, 0, -5, 0, 1]))                                  # needs sage.rings.number_field
sage: E = EllipticCurve([K([-3,-4,1,1]), K([4,-1,-1,0]), K([-2,0,1,0]),         # needs sage.rings.number_field
....:                    K([-621,778,138,-178]), K([9509,2046,-24728,10380])])
sage: is_Q_curve(E, certificate=True, verbose=True)                             # needs sage.rings.number_field
Checking whether Elliptic Curve defined by y^2 + (a^3+a^2-4*a-3)*x*y + (a^2-2)*y = x^3 + (-a^2-a+4)*x^2 + (-178*a^3+138*a^2+778*a-621)*x + (10380*a^3-24728*a^2+2046*a+9509) over Number Field in a with defining polynomial x^4 - 5*x^2 + 3 is a Q-curve
No: inconsistency at the 2 primes dividing 3
- potentially multiplicative: [True, False]
(False, 3)
from sage.schemes.elliptic_curves.Qcurves import is_Q_curve
R.<x> = PolynomialRing(QQ)
K.<a> = NumberField(R([3, 0, -5, 0, 1]))                                  # needs sage.rings.number_field
E = EllipticCurve([K([-3,-4,1,1]), K([4,-1,-1,0]), K([-2,0,1,0]),         # needs sage.rings.number_field
                   K([-621,778,138,-178]), K([9509,2046,-24728,10380])])
is_Q_curve(E, certificate=True, verbose=True)                             # needs sage.rings.number_field
>>> from sage.all import *
>>> from sage.schemes.elliptic_curves.Qcurves import is_Q_curve
>>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1)
>>> K = NumberField(R([Integer(3), Integer(0), -Integer(5), Integer(0), Integer(1)]), names=('a',)); (a,) = K._first_ngens(1)# needs sage.rings.number_field
>>> E = EllipticCurve([K([-Integer(3),-Integer(4),Integer(1),Integer(1)]), K([Integer(4),-Integer(1),-Integer(1),Integer(0)]), K([-Integer(2),Integer(0),Integer(1),Integer(0)]),         # needs sage.rings.number_field
...                    K([-Integer(621),Integer(778),Integer(138),-Integer(178)]), K([Integer(9509),Integer(2046),-Integer(24728),Integer(10380)])])
>>> is_Q_curve(E, certificate=True, verbose=True)                             # needs sage.rings.number_field
Checking whether Elliptic Curve defined by y^2 + (a^3+a^2-4*a-3)*x*y + (a^2-2)*y = x^3 + (-a^2-a+4)*x^2 + (-178*a^3+138*a^2+778*a-621)*x + (10380*a^3-24728*a^2+2046*a+9509) over Number Field in a with defining polynomial x^4 - 5*x^2 + 3 is a Q-curve
No: inconsistency at the 2 primes dividing 3
- potentially multiplicative: [True, False]
(False, 3)

A non-Q-curve over a quadratic field. The local data at bad primes is consistent, but the local test at good primes above 13 is not:

sage: K.<a> = NumberField(R([-10, 0, 1]))                                       # needs sage.rings.number_field
sage: E = EllipticCurve([K([0,1]), K([-1,-1]), K([0,0]),                        # needs sage.rings.number_field
....:                    K([-236,40]), K([-1840,464])])
sage: is_Q_curve(E, certificate=True, verbose=True)                             # needs sage.rings.number_field
Checking whether Elliptic Curve defined by y^2 + a*x*y = x^3 + (-a-1)*x^2 + (40*a-236)*x + (464*a-1840) over Number Field in a with defining polynomial x^2 - 10 is a Q-curve
Applying local tests at good primes above p<=100
No: inconsistency at the 2 ordinary primes dividing 13
- Frobenius discriminants mod squares: [-1, -3]
No: local test at p=13 failed
(False, 13)
K.<a> = NumberField(R([-10, 0, 1]))                                       # needs sage.rings.number_field
E = EllipticCurve([K([0,1]), K([-1,-1]), K([0,0]),                        # needs sage.rings.number_field
                   K([-236,40]), K([-1840,464])])
is_Q_curve(E, certificate=True, verbose=True)                             # needs sage.rings.number_field
>>> from sage.all import *
>>> K = NumberField(R([-Integer(10), Integer(0), Integer(1)]), names=('a',)); (a,) = K._first_ngens(1)# needs sage.rings.number_field
>>> E = EllipticCurve([K([Integer(0),Integer(1)]), K([-Integer(1),-Integer(1)]), K([Integer(0),Integer(0)]),                        # needs sage.rings.number_field
...                    K([-Integer(236),Integer(40)]), K([-Integer(1840),Integer(464)])])
>>> is_Q_curve(E, certificate=True, verbose=True)                             # needs sage.rings.number_field
Checking whether Elliptic Curve defined by y^2 + a*x*y = x^3 + (-a-1)*x^2 + (40*a-236)*x + (464*a-1840) over Number Field in a with defining polynomial x^2 - 10 is a Q-curve
Applying local tests at good primes above p<=100
No: inconsistency at the 2 ordinary primes dividing 13
- Frobenius discriminants mod squares: [-1, -3]
No: local test at p=13 failed
(False, 13)

A quadratic Q-curve with CM discriminant 15 (j-invariant not in Q):

sage: from sage.schemes.elliptic_curves.Qcurves import is_Q_curve
sage: R.<x> = PolynomialRing(QQ)
sage: K.<a> = NumberField(R([-1, -1, 1]))                                       # needs sage.rings.number_field
sage: E = EllipticCurve([K([1,0]), K([-1,0]), K([0,1]), K([0,-2]), K([0,1])])   # needs sage.rings.number_field
sage: is_Q_curve(E, certificate=True, verbose=True)                             # needs sage.rings.number_field
Checking whether Elliptic Curve defined by y^2 + x*y + a*y = x^3 + (-1)*x^2 + (-2*a)*x + a over Number Field in a with defining polynomial x^2 - x - 1 is a Q-curve
Yes: E is CM (discriminant -15)
(True, {'CM': -15})
from sage.schemes.elliptic_curves.Qcurves import is_Q_curve
R.<x> = PolynomialRing(QQ)
K.<a> = NumberField(R([-1, -1, 1]))                                       # needs sage.rings.number_field
E = EllipticCurve([K([1,0]), K([-1,0]), K([0,1]), K([0,-2]), K([0,1])])   # needs sage.rings.number_field
is_Q_curve(E, certificate=True, verbose=True)                             # needs sage.rings.number_field
>>> from sage.all import *
>>> from sage.schemes.elliptic_curves.Qcurves import is_Q_curve
>>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1)
>>> K = NumberField(R([-Integer(1), -Integer(1), Integer(1)]), names=('a',)); (a,) = K._first_ngens(1)# needs sage.rings.number_field
>>> E = EllipticCurve([K([Integer(1),Integer(0)]), K([-Integer(1),Integer(0)]), K([Integer(0),Integer(1)]), K([Integer(0),-Integer(2)]), K([Integer(0),Integer(1)])])   # needs sage.rings.number_field
>>> is_Q_curve(E, certificate=True, verbose=True)                             # needs sage.rings.number_field
Checking whether Elliptic Curve defined by y^2 + x*y + a*y = x^3 + (-1)*x^2 + (-2*a)*x + a over Number Field in a with defining polynomial x^2 - x - 1 is a Q-curve
Yes: E is CM (discriminant -15)
(True, {'CM': -15})

An example over Q(2,3). The j-invariant is in Q(6), so computations will be done over that field, and in fact there is an isogenous curve with rational j, so we have a so-called rational Q-curve:

sage: # needs sage.rings.number_field
sage: K.<a> = NumberField(R([1, 0, -4, 0, 1]))
sage: E = EllipticCurve([K([-2,-4,1,1]), K([0,1,0,0]), K([0,1,0,0]),
....:                    K([-4780,9170,1265,-2463]),
....:                    K([163923,-316598,-43876,84852])])
sage: flag, cert = is_Q_curve(E, certificate=True)
sage: flag
True
sage: cert
{'CM': 0, 'N': 1, 'core_degs': [1], 'core_poly': x - 85184/3, 'r': 0, 'rho': 0}
# needs sage.rings.number_field
K.<a> = NumberField(R([1, 0, -4, 0, 1]))
E = EllipticCurve([K([-2,-4,1,1]), K([0,1,0,0]), K([0,1,0,0]),
                   K([-4780,9170,1265,-2463]),
                   K([163923,-316598,-43876,84852])])
flag, cert = is_Q_curve(E, certificate=True)
flag
cert
>>> from sage.all import *
>>> # needs sage.rings.number_field
>>> K = NumberField(R([Integer(1), Integer(0), -Integer(4), Integer(0), Integer(1)]), names=('a',)); (a,) = K._first_ngens(1)
>>> E = EllipticCurve([K([-Integer(2),-Integer(4),Integer(1),Integer(1)]), K([Integer(0),Integer(1),Integer(0),Integer(0)]), K([Integer(0),Integer(1),Integer(0),Integer(0)]),
...                    K([-Integer(4780),Integer(9170),Integer(1265),-Integer(2463)]),
...                    K([Integer(163923),-Integer(316598),-Integer(43876),Integer(84852)])])
>>> flag, cert = is_Q_curve(E, certificate=True)
>>> flag
True
>>> cert
{'CM': 0, 'N': 1, 'core_degs': [1], 'core_poly': x - 85184/3, 'r': 0, 'rho': 0}

Over the same field, a so-called strict Q-curve which is not isogenous to one with rational j, but whose core field is quadratic. In fact the isogeny class over K consists of 6 curves, four with conjugate quartic j-invariants and 2 with quadratic conjugate j-invariants in Q(3) (but which are not base-changes from the quadratic subfield):

sage: # needs sage.rings.number_field
sage: E = EllipticCurve([K([0,-3,0,1]), K([1,4,0,-1]), K([0,0,0,0]),
....:                    K([-2,-16,0,4]), K([-19,-32,4,8])])
sage: flag, cert = is_Q_curve(E, certificate=True)
sage: flag
True
sage: cert
{'CM': 0,
 'N': 2,
 'core_degs': [1, 2],
 'core_poly': x^2 - 840064*x + 1593413632,
 'r': 1,
 'rho': 1}
# needs sage.rings.number_field
E = EllipticCurve([K([0,-3,0,1]), K([1,4,0,-1]), K([0,0,0,0]),
                   K([-2,-16,0,4]), K([-19,-32,4,8])])
flag, cert = is_Q_curve(E, certificate=True)
flag
cert
>>> from sage.all import *
>>> # needs sage.rings.number_field
>>> E = EllipticCurve([K([Integer(0),-Integer(3),Integer(0),Integer(1)]), K([Integer(1),Integer(4),Integer(0),-Integer(1)]), K([Integer(0),Integer(0),Integer(0),Integer(0)]),
...                    K([-Integer(2),-Integer(16),Integer(0),Integer(4)]), K([-Integer(19),-Integer(32),Integer(4),Integer(8)])])
>>> flag, cert = is_Q_curve(E, certificate=True)
>>> flag
True
>>> cert
{'CM': 0,
 'N': 2,
 'core_degs': [1, 2],
 'core_poly': x^2 - 840064*x + 1593413632,
 'r': 1,
 'rho': 1}