Created
July 21, 2025 06:33
-
-
Save amadhurkant/5301c47eef51e679b1ac396b7a3d81e2 to your computer and use it in GitHub Desktop.
Isogeny of elliptic curve demonstration using sagemath.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
# ~~~ Construction of an Isogeny Between Elliptic Curves ~~~ | |
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
# Field and Curve Definitions | |
p = 97 | |
F = GF(p) | |
E1 = EllipticCurve(F, [1, 24]) | |
E2 = EllipticCurve(F, [42, 46]) | |
# Initial Data | |
print(f"E1: {E1}, j(E1) = {E1.j_invariant()}, |E1(F_p)| = {E1.order()}") | |
print(f"E2: {E2}, j(E2) = {E2.j_invariant()}, |E2(F_p)| = {E2.order()}") | |
print("-" * 70) | |
# Determine the degree via modular polynomials | |
print("Determining the degree of the isogeny φ: E1 → E2") | |
degree = None | |
j1, j2 = E1.j_invariant(), E2.j_invariant() | |
# Test small prime degrees | |
for l in [3, 5, 7, 11, 13]: | |
Phi_l = classical_modular_polynomial(l) | |
result = Phi_l(j1, j2) % p | |
print(f" Testing Φ_{l}(j1, j2) mod {p}: Result = {result}") | |
if result == 0: | |
degree = l | |
break | |
if degree is None: | |
raise ValueError("No isogeny of small prime degree found between the curves.") | |
else: | |
print(f"The modular polynomial condition holds for l = {degree}. This is the degree.") | |
print("-" * 70) | |
# Kernel Construction | |
print(f"Kernel of the {degree}-isogeny:") | |
order = E1.order() | |
if order % degree == 0: | |
print(f"Since deg(φ) divides |E1(F_p)|, the kernel is a rational subgroup.") | |
cofactor = order // degree | |
P_gen = E1.gen(0) | |
kernel_generator = cofactor * P_gen | |
print(f"The kernel G = <P>, where P = {kernel_generator.xy()}, has order {kernel_generator.order()}.") | |
else: | |
raise ValueError("The kernel is not rational; a different construction method is needed.") | |
print("-" * 70) | |
# Isogeny Construction and Explicit Formulas | |
print("Isogeny Construction (via Vélu's formulas):") | |
# Construct the isogeny from the specified kernel | |
phi = E1.isogeny(kernel_generator) | |
print(f"The isogeny constructed from G has codomain: {phi.codomain()}") | |
print("\nThe rational maps defining φ are:") | |
Rx, Ry = phi.rational_maps() | |
print(f"φ_x(x) = {Rx}") | |
print(f"\nφ_y(x, y) = {Ry}") | |
print("-" * 70) | |
# Verification of the Map | |
print("Verification:") | |
# Use a generator of the full group as a test point | |
P_test = E1.gen(0) | |
Q_image = phi(P_test) | |
print(f"The map φ sends the point P = {P_test.xy()} on E1") | |
print(f"to its image Q = {Q_image.xy()}.") | |
is_on_target = Q_image in E2 | |
print(f"Check: Is Q in E2? --> {is_on_target}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment