print("Exercise: simplify the coefficients of the curve y^2 = x^3 -108*x + 1512 so that they are smaller integers (in absolute value)")
print("Let's define E1 in short Weierstrass form with coefficients (a, b) = (-108, 1512)")
E1 = EllipticCurve([-108, 1512])
print("E1 is: {}".format(E1))
g = gcd(-108, 1512)
print("-108 = {}, 1512 = {}, gcd(-108, 1512) = {} = {}".format(factor(108), factor(1512), g, factor(g)))
a = E1.a4()
b = E1.a6()
u2 = 6 # u^2 = 6 because u = sqrt(6)
aa = a/u2**2
bb = b/u2**3
print("taking u = sqrt(6), a' = a/u^4 = a/6^2 = {}/{} = {}, b' = b/u^6 = b/6^3 = {}/{} = {}".format(a, u2**2, a/u2**2, b, u2**3, b/u2**3))
E2 = EllipticCurve([aa, bb])
print("E2 is {}".format(E2))
print("Do E1 and E2 have the same j-invariant?")
j1 = E1.j_invariant()
j2 = E2.j_invariant()
print("j(E1) = E1.j_invariant() = {}, j(E2) = E2.j_invariant() = {}".format(j1, j2))
print("Are the curves isomorphic? {}".format(E1.is_isomorphic(E2)))
E1.is_isomorphic(E2) # False over Q
print("The curves are not isomorphic over Q because sqrt(6) is not a rational number, it is algebraic, it requires a quadratic extension")
K. = QQ.extension(x**2-6)
print("A quadratic extension with sqrt(6) is K {}".format(K))
print("Change the field of definition of E1 and E2 to be K = Q(sqrt(6)) instead of Q")
E11 = E1.change_ring(K)
E22 = E2.change_ring(K)
E11.is_isomorphic(E22)
print("test again isomorphism: E11.is_isomorphic(E22) {}".format(E11.is_isomorphic(E22)))
print("compute the isomorphism: use E11.isomorphism_to(E22)")
E11.isomorphism_to(E22)
# it outputs the coefficients (u,r,s,t) of the map
# tricks:
# documentation: use the question mark then press enter
E11.isomorphism_to?
# To flush the top consule, use ctrl+u
# to get suggestions to complete a name or method, press the tabulation key (it's named completion)
# function field of E1
K0.= FunctionField(QQ)
K0Y. = K0[] # polynomial ring in Y
K. = K0.extension(Y**2 - x**3 -a*x-b)
# function field of E2
L0.~~= FunctionField(QQ)
L0T. = L0[] # polynomial ring in T
L. = L0.extension(T**2 - s**3 -aa*s-bb)
print("An example of a map between two curves that is not an isomorphism")
print("isomorphism means injective and surjective, the kernel is {O} the point at infinity")
print("endomorphism means from E to E (it stays on the same curve)")
print("an isogeny (chapter 12, will be covered in full details later) is another example of a morphism of curves")
print("is has a non-trivial kernel and maps points to a new curve (with a distinct j-invariant)")
E4 = EllipticCurve([-6, 4]) # see lecture 1 in the slides for a graph of this curve
E4.torsion_points() # the curve has a 2-torsion point (2,0)
I2 = E4.isogenies_prime_degree(2)[0] # [0] means the 1st item of the list in Python
E5 = I2.codomain() # the image curve under the isogeny
I2.rational_maps() # what is the expression of I2 from E4 to E5
E5.torsion_points() # does E5 has also 2-torsion points? yes
hatI2 = E5.isogenies_prime_degree(2)[0] # let's go back to E4
hatI2.rational_maps()
E4.j_invariant()
E5.j_invariant()
print("E4 is {}\nE5 is {}".format(E4, E5))
print("j(E4) = {} j(E5) = {}".format(E4.j_invariant(), E5.j_invariant()))
print("I2 E4 -> E5 has rational map {}".format(I2.rational_maps()))
print("hatI2 E5 -> E4 has rational map {}".format(hatI2.rational_maps()))
P2 = E4((2,0))
P = E4((0,2)) # a point on E4
Q = I2(P) # its image under I2 in E5
R = hatI2(Q) # its image when comming back to E4
R == 2*P
print("P = {} is on E4, I2(P) = {}= Q is on E5, hatI2(Q) = {} = R is on E4, and R == 2*P: {}".format(P, Q, R, R == 2*P))
print("an example of a GLV endomorphism on E/Fp")
## I'm doing this because I want a prime p so that a curve of j-invariant 1728 over Fp has order 2*r and r is prime again
p = 1009
ok = False
while not ok:
p = next_prime(p)
while not (p % 4) == 1:
p = next_prime(p)
print("p = {}".format(p))
Fp = GF(p)
a = Fp(2)
while a.is_square():
a = a+1
E = EllipticCurve([-a, 0])
r = E.order()
print("r = {}".format(r.factor()))
ok = (r // 2).is_prime()
if not ok: # try a twist
E = EllipticCurve([-a**3, 0])
r = E.order()
ok = (r // 2).is_prime()
a = a**3
print("r = {}".format(r.factor()))
r = r//2
r.is_prime()
t = E.trace_of_frobenius()
r == 21**2 + 10**2
Fr = GF(r)
Fr(-1).sqrt()
52**2
P = 2*E.random_element()
# clearing cofactor 2
while P == E(0):
P = 2*E.random_element()
print("P = {} on the curve has order r={}".format(P, r))
p == 30**2 + 11**2
eigenvalue_end = 52
sqrt_1_mod_p = (Fp(-1)).sqrt()
def phi(P, sqrt_1 = sqrt_1_mod_p):
x, y = P[0], P[1]
return P.curve()(-x, sqrt_1_mod_p*y)
phi(P)
phi(phi(P)) == -P
~~