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
>>> from sage.all import *
>>> from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius
>>> z5, = GF(Integer(17)**Integer(5)).gens()
>>> E = EllipticCurve([z5,Integer(1)])
>>> 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
>>> from sage.all import *
>>> z5, = GF(Integer(7)**Integer(5)).gens()
>>> E = EllipticCurve([z5,Integer(1)])
>>> pi = EllipticCurveHom_frobenius(E, Integer(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
>>> from sage.all import *
>>> z5, = GF(Integer(7)**Integer(5)).gens()
>>> E = EllipticCurve([z5,Integer(1)])
>>> pi = EllipticCurveHom_frobenius(E,Integer(5))
>>> pi.degree()
16807
>>> pi.rational_maps()
(x^16807, y^16807)
>>> pi.formal()                   # known bug
...
>>> pi.is_normalized()            # known bug
...
>>> pi.is_separable()
False
>>> pi.is_injective()
True
>>> 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
>>> from sage.all import *
>>> E = EllipticCurve([GF(Integer(17)**Integer(6)).gen(), Integer(0)])
>>> pi = EllipticCurveHom_frobenius(E)
>>> 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
>>> pihat.is_separable()
True
>>> pihat * pi == EllipticCurveHom_scalar(E,Integer(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))
>>> from sage.all import *
>>> E = EllipticCurve([Integer(0), GF(Integer(17)**Integer(6)).gen()])
>>> E.is_supersingular()
True
>>> pi1 = EllipticCurveHom_frobenius(E)
>>> 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
>>> pi6 = EllipticCurveHom_frobenius(E,Integer(6))
>>> 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
>>> 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)[source]¶
- 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 - >>> from sage.all import * >>> from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius >>> E = EllipticCurve(j=GF(Integer(11)**Integer(2)).gen()) >>> 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 >>> EllipticCurveHom_frobenius(E, Integer(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 - dual()[source]¶
- Compute the dual of this Frobenius isogeny. - This method returns an - EllipticCurveHomobject.- 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 - >>> from sage.all import * >>> from sage.schemes.elliptic_curves.hom_scalar import EllipticCurveHom_scalar >>> from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius >>> E = EllipticCurve(GF(Integer(31)), [Integer(0),Integer(1)]) >>> f = EllipticCurveHom_frobenius(E) >>> f.dual() * f == EllipticCurveHom_scalar(f.domain(), Integer(31)) True >>> f * f.dual() == EllipticCurveHom_scalar(f.codomain(), Integer(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 - >>> from sage.all import * >>> E = EllipticCurve(GF(Integer(31)), [Integer(1),Integer(0)]) >>> f = EllipticCurveHom_frobenius(E) >>> f.dual() * f == EllipticCurveHom_scalar(f.domain(), Integer(31)) True >>> f * f.dual() == EllipticCurveHom_scalar(f.codomain(), Integer(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().
 - inseparable_degree()[source]¶
- Return the inseparable degree of this Frobenius isogeny. - Since this class implements only purely inseparable isogenies, the inseparable degree equals the degree. - 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.inseparable_degree() 14641 sage: pi.inseparable_degree() == pi.degree() True - >>> from sage.all import * >>> from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius >>> E = EllipticCurve(GF(Integer(11)), [Integer(1),Integer(1)]) >>> pi = EllipticCurveHom_frobenius(E, Integer(4)) >>> pi.inseparable_degree() 14641 >>> pi.inseparable_degree() == pi.degree() True 
 - kernel_polynomial()[source]¶
- 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 - >>> from sage.all import * >>> from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius >>> E = EllipticCurve(GF(Integer(11)), [Integer(1),Integer(1)]) >>> pi = EllipticCurveHom_frobenius(E, Integer(5)) >>> pi.kernel_polynomial() 1 
 - rational_maps()[source]¶
- 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) - >>> from sage.all import * >>> from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius >>> E = EllipticCurve(GF(Integer(11)), [Integer(1),Integer(1)]) >>> pi = EllipticCurveHom_frobenius(E, Integer(4)) >>> pi.rational_maps() (x^14641, y^14641) 
 - scaling_factor()[source]¶
- 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 - >>> from sage.all import * >>> from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius >>> E = EllipticCurve(GF(Integer(11)), [Integer(1),Integer(1)]) >>> pi = EllipticCurveHom_frobenius(E) >>> pi.formal() t^11 + O(t^33) >>> pi.scaling_factor() 0 >>> pi = EllipticCurveHom_frobenius(E, Integer(3)) >>> pi.formal() t^1331 + O(t^1353) >>> pi.scaling_factor() 0 >>> pi = EllipticCurveHom_frobenius(E, Integer(0)) >>> pi == E.scalar_multiplication(Integer(1)) True >>> pi.scaling_factor() 1 - The scaling factor lives in the base ring: - sage: pi.scaling_factor().parent() Finite Field of size 11 - >>> from sage.all import * >>> pi.scaling_factor().parent() Finite Field of size 11 - ALGORITHM: Inseparable isogenies of degree \(>1\) have scaling factor \(0\). 
 - x_rational_map()[source]¶
- 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 - >>> from sage.all import * >>> from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius >>> E = EllipticCurve(GF(Integer(11)), [Integer(1),Integer(1)]) >>> pi = EllipticCurveHom_frobenius(E, Integer(4)) >>> pi.x_rational_map() x^14641