Frobenius isogenies of elliptic curves#
Frobenius isogenies only exist in positive characteristic \(p\). They are given by \(\pi_n:(x,y)\mapsto (x^{p^n},y^{p^n})\).
This class implements \(\pi_n\) for \(n \geq 0\). Together with existing
tools for composing isogenies (see EllipticCurveHom_composite
),
we can therefore represent arbitrary inseparable isogenies in Sage.
EXAMPLES:
Constructing a Frobenius isogeny is straightforward:
sage: from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius
sage: z5, = GF(17^5).gens()
sage: E = EllipticCurve([z5,1])
sage: pi = EllipticCurveHom_frobenius(E); pi
Frobenius isogeny of degree 17:
From: Elliptic Curve defined by y^2 = x^3 + z5*x + 1
over Finite Field in z5 of size 17^5
To: Elliptic Curve defined by y^2 = x^3 + (9*z5^4+7*z5^3+10*z5^2+z5+14)*x + 1
over Finite Field in z5 of size 17^5
By passing \(n\), we can also construct higher-power Frobenius maps, such as the Frobenius endomorphism:
sage: z5, = GF(7^5).gens()
sage: E = EllipticCurve([z5,1])
sage: pi = EllipticCurveHom_frobenius(E, 5); pi
Frobenius endomorphism of degree 16807 = 7^5:
From: Elliptic Curve defined by y^2 = x^3 + z5*x + 1
over Finite Field in z5 of size 7^5
To: Elliptic Curve defined by y^2 = x^3 + z5*x + 1
over Finite Field in z5 of size 7^5
The usual EllipticCurveHom
methods are supported:
sage: z5, = GF(7^5).gens()
sage: E = EllipticCurve([z5,1])
sage: pi = EllipticCurveHom_frobenius(E,5)
sage: pi.degree()
16807
sage: pi.rational_maps()
(x^16807, y^16807)
sage: pi.formal() # known bug
...
sage: pi.is_normalized() # known bug
...
sage: pi.is_separable()
False
sage: pi.is_injective()
True
sage: pi.is_surjective()
True
Computing the dual of Frobenius is supported as well:
sage: E = EllipticCurve([GF(17^6).gen(), 0])
sage: pi = EllipticCurveHom_frobenius(E)
sage: pihat = pi.dual(); pihat
Isogeny of degree 17
from Elliptic Curve defined by y^2 = x^3 + (15*z6^5+5*z6^4+8*z6^3+12*z6^2+11*z6+7)*x
over Finite Field in z6 of size 17^6
to Elliptic Curve defined by y^2 = x^3 + z6*x
over Finite Field in z6 of size 17^6
sage: pihat.is_separable()
True
sage: pihat * pi == EllipticCurveHom_scalar(E,17) # known bug -- #6413
True
A supersingular example (with purely inseparable dual):
sage: E = EllipticCurve([0, GF(17^6).gen()])
sage: E.is_supersingular()
True
sage: pi1 = EllipticCurveHom_frobenius(E)
sage: pi1hat = pi1.dual(); pi1hat
Composite morphism of degree 17 = 17*1:
From: Elliptic Curve defined by y^2 = x^3 + (15*z6^5+5*z6^4+8*z6^3+12*z6^2+11*z6+7)
over Finite Field in z6 of size 17^6
To: Elliptic Curve defined by y^2 = x^3 + z6
over Finite Field in z6 of size 17^6
sage: pi6 = EllipticCurveHom_frobenius(E,6)
sage: pi6hat = pi6.dual(); pi6hat
Composite morphism of degree 24137569 = 24137569*1:
From: Elliptic Curve defined by y^2 = x^3 + z6
over Finite Field in z6 of size 17^6
To: Elliptic Curve defined by y^2 = x^3 + z6
over Finite Field in z6 of size 17^6
sage: pi6hat.factors()
(Frobenius endomorphism of degree 24137569 = 17^6:
From: Elliptic Curve defined by y^2 = x^3 + z6
over Finite Field in z6 of size 17^6
To: Elliptic Curve defined by y^2 = x^3 + z6
over Finite Field in z6 of size 17^6,
Elliptic-curve endomorphism of
Elliptic Curve defined by y^2 = x^3 + z6 over Finite Field in z6 of size 17^6
Via: (u,r,s,t) = (2*z6^5 + 10*z6^3 + z6^2 + 8, 0, 0, 0))
AUTHORS:
Lorenz Panny (2021): implement
EllipticCurveHom_frobenius
Mickaël Montessinos (2021): computing the dual of a Frobenius isogeny
- class sage.schemes.elliptic_curves.hom_frobenius.EllipticCurveHom_frobenius(E, power=1)#
Bases:
EllipticCurveHom
Construct a Frobenius isogeny on a given curve with a given power of the base-ring characteristic.
Writing \(n\) for the parameter
power
(default: \(1\)), the isogeny is defined by \((x,y) \to (x^{p^n}, y^{p^n})\) where \(p\) is the characteristic of the base ring.EXAMPLES:
sage: from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius sage: E = EllipticCurve(j=GF(11^2).gen()) sage: EllipticCurveHom_frobenius(E) Frobenius isogeny of degree 11: From: Elliptic Curve defined by y^2 = x^3 + (2*z2+6)*x + (8*z2+8) over Finite Field in z2 of size 11^2 To: Elliptic Curve defined by y^2 = x^3 + (9*z2+3)*x + (3*z2+7) over Finite Field in z2 of size 11^2 sage: EllipticCurveHom_frobenius(E, 2) Frobenius endomorphism of degree 121 = 11^2: From: Elliptic Curve defined by y^2 = x^3 + (2*z2+6)*x + (8*z2+8) over Finite Field in z2 of size 11^2 To: Elliptic Curve defined by y^2 = x^3 + (2*z2+6)*x + (8*z2+8) over Finite Field in z2 of size 11^2
- degree()#
Return the degree of this Frobenius isogeny.
EXAMPLES:
sage: from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius sage: E = EllipticCurve(GF(11), [1,1]) sage: pi = EllipticCurveHom_frobenius(E, 4) sage: pi.degree() 14641
- dual()#
Compute the dual of this Frobenius isogeny.
This method returns an
EllipticCurveHom
object.EXAMPLES:
An ordinary example:
sage: from sage.schemes.elliptic_curves.hom_scalar import EllipticCurveHom_scalar sage: from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius sage: E = EllipticCurve(GF(31), [0,1]) sage: f = EllipticCurveHom_frobenius(E) sage: f.dual() * f == EllipticCurveHom_scalar(f.domain(), 31) True sage: f * f.dual() == EllipticCurveHom_scalar(f.codomain(), 31) True
A supersingular example:
sage: E = EllipticCurve(GF(31), [1,0]) sage: f = EllipticCurveHom_frobenius(E) sage: f.dual() * f == EllipticCurveHom_scalar(f.domain(), 31) True sage: f * f.dual() == EllipticCurveHom_scalar(f.codomain(), 31) True
ALGORITHM:
For supersingular curves, the dual of Frobenius is again purely inseparable, so we start out with a Frobenius isogeny of equal degree in the opposite direction.
For ordinary curves, we immediately reduce to the case of prime degree. The kernel of the dual is the unique subgroup of size \(p\), which we compute from the \(p\)-division polynomial.
In both cases, we then search for the correct post-isomorphism using
find_post_isomorphism()
.
- is_injective()#
Determine whether or not this Frobenius isogeny has trivial kernel.
Since Frobenius isogenies are purely inseparable, this method always returns
True
.EXAMPLES:
sage: from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius sage: E = EllipticCurve(GF(11), [1,1]) sage: pi = EllipticCurveHom_frobenius(E, 5) sage: pi.is_injective() True
- is_separable()#
Determine whether or not this Frobenius isogeny is separable.
Since Frobenius isogenies are purely inseparable, this method returns
True
if and only if the degree is \(1\).EXAMPLES:
sage: from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius sage: E = EllipticCurve(GF(11), [1,1]) sage: pi = EllipticCurveHom_frobenius(E) sage: pi.degree() 11 sage: pi.is_separable() False sage: pi = EllipticCurveHom_frobenius(E, 0) sage: pi.degree() 1 sage: pi.is_separable() True
- kernel_polynomial()#
Return the kernel polynomial of this Frobenius isogeny as a polynomial in \(x\). This method always returns \(1\).
EXAMPLES:
sage: from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius sage: E = EllipticCurve(GF(11), [1,1]) sage: pi = EllipticCurveHom_frobenius(E, 5) sage: pi.kernel_polynomial() 1
- rational_maps()#
Return the explicit rational maps defining this Frobenius isogeny as (sparse) bivariate rational maps in \(x\) and \(y\).
EXAMPLES:
sage: from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius sage: E = EllipticCurve(GF(11), [1,1]) sage: pi = EllipticCurveHom_frobenius(E, 4) sage: pi.rational_maps() (x^14641, y^14641)
- scaling_factor()#
Return the Weierstrass scaling factor associated to this Frobenius morphism.
The scaling factor is the constant \(u\) (in the base field) such that \(\varphi^* \omega_2 = u \omega_1\), where \(\varphi: E_1\to E_2\) is this morphism and \(\omega_i\) are the standard Weierstrass differentials on \(E_i\) defined by \(\mathrm dx/(2y+a_1x+a_3)\).
EXAMPLES:
sage: from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius sage: E = EllipticCurve(GF(11), [1,1]) sage: pi = EllipticCurveHom_frobenius(E) sage: pi.formal() t^11 + O(t^33) sage: pi.scaling_factor() 0 sage: pi = EllipticCurveHom_frobenius(E, 3) sage: pi.formal() t^1331 + O(t^1353) sage: pi.scaling_factor() 0 sage: pi = EllipticCurveHom_frobenius(E, 0) sage: pi == E.scalar_multiplication(1) True sage: pi.scaling_factor() 1
The scaling factor lives in the base ring:
sage: pi.scaling_factor().parent() Finite Field of size 11
ALGORITHM: Inseparable isogenies of degree \(>1\) have scaling factor \(0\).
- x_rational_map()#
Return the \(x\)-coordinate rational map of this Frobenius isogeny as a (sparse) univariate rational map in \(x\).
EXAMPLES:
sage: from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius sage: E = EllipticCurve(GF(11), [1,1]) sage: pi = EllipticCurveHom_frobenius(E, 4) sage: pi.x_rational_map() x^14641