Hyperelliptic curves over a general ring#

EXAMPLES:

sage: P.<x> = GF(5)[]
sage: f = x^5 - 3*x^4 - 2*x^3 + 6*x^2 + 3*x - 1
sage: C = HyperellipticCurve(f); C
Hyperelliptic Curve over Finite Field of size 5
 defined by y^2 = x^5 + 2*x^4 + 3*x^3 + x^2 + 3*x + 4
P.<x> = GF(5)[]
f = x^5 - 3*x^4 - 2*x^3 + 6*x^2 + 3*x - 1
C = HyperellipticCurve(f); C
sage: P.<x> = QQ[]
sage: f = 4*x^5 - 30*x^3 + 45*x - 22
sage: C = HyperellipticCurve(f); C
Hyperelliptic Curve over Rational Field defined by y^2 = 4*x^5 - 30*x^3 + 45*x - 22
sage: C.genus()
2

sage: D = C.affine_patch(0)
sage: D.defining_polynomials()[0].parent()
Multivariate Polynomial Ring in x1, x2 over Rational Field
P.<x> = QQ[]
f = 4*x^5 - 30*x^3 + 45*x - 22
C = HyperellipticCurve(f); C
C.genus()
D = C.affine_patch(0)
D.defining_polynomials()[0].parent()
class sage.schemes.hyperelliptic_curves.hyperelliptic_generic.HyperellipticCurve_generic(PP, f, h=None, names=None, genus=None)#

Bases: ProjectivePlaneCurve

base_extend(R)#

Returns this HyperellipticCurve over a new base ring R.

EXAMPLES:

sage: # needs sage.rings.padics
sage: R.<x> = QQ[]
sage: H = HyperellipticCurve(x^5 - 10*x + 9)
sage: K = Qp(3, 5)
sage: L.<a> = K.extension(x^30 - 3)
sage: HK = H.change_ring(K)
sage: HL = HK.change_ring(L); HL
Hyperelliptic Curve
 over 3-adic Eisenstein Extension Field in a defined by x^30 - 3
 defined by (1 + O(a^150))*y^2 = (1 + O(a^150))*x^5
  + (2 + 2*a^30 + a^60 + 2*a^90 + 2*a^120 + O(a^150))*x + a^60 + O(a^210)

sage: R.<x> = FiniteField(7)[]
sage: H = HyperellipticCurve(x^8 + x + 5)
sage: H.base_extend(FiniteField(7^2, 'a'))                                  # needs sage.rings.finite_rings
Hyperelliptic Curve over Finite Field in a of size 7^2
 defined by y^2 = x^8 + x + 5
# needs sage.rings.padics
R.<x> = QQ[]
H = HyperellipticCurve(x^5 - 10*x + 9)
K = Qp(3, 5)
L.<a> = K.extension(x^30 - 3)
HK = H.change_ring(K)
HL = HK.change_ring(L); HL
R.<x> = FiniteField(7)[]
H = HyperellipticCurve(x^8 + x + 5)
H.base_extend(FiniteField(7^2, 'a'))                                  # needs sage.rings.finite_rings
change_ring(R)#

Returns this HyperellipticCurve over a new base ring R.

EXAMPLES:

sage: # needs sage.rings.padics
sage: R.<x> = QQ[]
sage: H = HyperellipticCurve(x^5 - 10*x + 9)
sage: K = Qp(3, 5)
sage: L.<a> = K.extension(x^30 - 3)
sage: HK = H.change_ring(K)
sage: HL = HK.change_ring(L); HL
Hyperelliptic Curve
 over 3-adic Eisenstein Extension Field in a defined by x^30 - 3
 defined by (1 + O(a^150))*y^2 = (1 + O(a^150))*x^5
  + (2 + 2*a^30 + a^60 + 2*a^90 + 2*a^120 + O(a^150))*x + a^60 + O(a^210)

sage: R.<x> = FiniteField(7)[]
sage: H = HyperellipticCurve(x^8 + x + 5)
sage: H.base_extend(FiniteField(7^2, 'a'))                                  # needs sage.rings.finite_rings
Hyperelliptic Curve over Finite Field in a of size 7^2
 defined by y^2 = x^8 + x + 5
# needs sage.rings.padics
R.<x> = QQ[]
H = HyperellipticCurve(x^5 - 10*x + 9)
K = Qp(3, 5)
L.<a> = K.extension(x^30 - 3)
HK = H.change_ring(K)
HL = HK.change_ring(L); HL
R.<x> = FiniteField(7)[]
H = HyperellipticCurve(x^8 + x + 5)
H.base_extend(FiniteField(7^2, 'a'))                                  # needs sage.rings.finite_rings
genus()#
has_odd_degree_model()#

Return True if an odd degree model of self exists over the field of definition; False otherwise.

Use odd_degree_model to calculate an odd degree model.

EXAMPLES:

sage: x = QQ['x'].0
sage: HyperellipticCurve(x^5 + x).has_odd_degree_model()
True
sage: HyperellipticCurve(x^6 + x).has_odd_degree_model()
True
sage: HyperellipticCurve(x^6 + x + 1).has_odd_degree_model()
False
x = QQ['x'].0
HyperellipticCurve(x^5 + x).has_odd_degree_model()
HyperellipticCurve(x^6 + x).has_odd_degree_model()
HyperellipticCurve(x^6 + x + 1).has_odd_degree_model()
hyperelliptic_polynomials(K=None, var='x')#

EXAMPLES:

sage: R.<x> = QQ[]; C = HyperellipticCurve(x^3 + x - 1, x^3/5); C
Hyperelliptic Curve over Rational Field defined by y^2 + 1/5*x^3*y = x^3 + x - 1
sage: C.hyperelliptic_polynomials()
(x^3 + x - 1, 1/5*x^3)
R.<x> = QQ[]; C = HyperellipticCurve(x^3 + x - 1, x^3/5); C
C.hyperelliptic_polynomials()
invariant_differential()#

Returns dx/2y, as an element of the Monsky-Washnitzer cohomology of self

EXAMPLES:

sage: R.<x> = QQ['x']
sage: C = HyperellipticCurve(x^5 - 4*x + 4)
sage: C.invariant_differential()
1 dx/2y
R.<x> = QQ['x']
C = HyperellipticCurve(x^5 - 4*x + 4)
C.invariant_differential()
is_singular()#

Returns False, because hyperelliptic curves are smooth projective curves, as checked on construction.

EXAMPLES:

sage: R.<x> = QQ[]
sage: H = HyperellipticCurve(x^5 + 1)
sage: H.is_singular()
False
R.<x> = QQ[]
H = HyperellipticCurve(x^5 + 1)
H.is_singular()

A hyperelliptic curve with genus at least 2 always has a singularity at infinity when viewed as a plane projective curve. This can be seen in the following example.:

sage: R.<x> = QQ[]
sage: H = HyperellipticCurve(x^5 + 2)
sage: from sage.misc.verbose import set_verbose
sage: set_verbose(-1)
sage: H.is_singular()
False
sage: from sage.schemes.curves.projective_curve import ProjectivePlaneCurve
sage: ProjectivePlaneCurve.is_singular(H)
True
R.<x> = QQ[]
H = HyperellipticCurve(x^5 + 2)
from sage.misc.verbose import set_verbose
set_verbose(-1)
H.is_singular()
from sage.schemes.curves.projective_curve import ProjectivePlaneCurve
ProjectivePlaneCurve.is_singular(H)
is_smooth()#

Returns True, because hyperelliptic curves are smooth projective curves, as checked on construction.

EXAMPLES:

sage: R.<x> = GF(13)[]
sage: H = HyperellipticCurve(x^8 + 1)
sage: H.is_smooth()
True
R.<x> = GF(13)[]
H = HyperellipticCurve(x^8 + 1)
H.is_smooth()

A hyperelliptic curve with genus at least 2 always has a singularity at infinity when viewed as a plane projective curve. This can be seen in the following example.:

sage: # needs sage.rings.finite_rings
sage: R.<x> = GF(27, 'a')[]
sage: H = HyperellipticCurve(x^10 + 2)
sage: from sage.misc.verbose import set_verbose
sage: set_verbose(-1)
sage: H.is_smooth()
True
sage: from sage.schemes.curves.projective_curve import ProjectivePlaneCurve
sage: ProjectivePlaneCurve.is_smooth(H)
False
# needs sage.rings.finite_rings
R.<x> = GF(27, 'a')[]
H = HyperellipticCurve(x^10 + 2)
from sage.misc.verbose import set_verbose
set_verbose(-1)
H.is_smooth()
from sage.schemes.curves.projective_curve import ProjectivePlaneCurve
ProjectivePlaneCurve.is_smooth(H)
jacobian()#
lift_x(x, all=False)#
local_coord(P, prec=20, name='t')#

Calls the appropriate local_coordinates function

INPUT:

  • P – a point on self

  • prec – desired precision of the local coordinates

  • name – generator of the power series ring (default: t)

OUTPUT:

(x(t),y(t)) such that y(t)2=f(x(t)), where t is the local parameter at P

EXAMPLES:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^5 - 23*x^3 + 18*x^2 + 40*x)
sage: H.local_coord(H(1 ,6), prec=5)
(1 + t + O(t^5), 6 + t - 7/2*t^2 - 1/2*t^3 - 25/48*t^4 + O(t^5))
sage: H.local_coord(H(4, 0), prec=7)
(4 + 1/360*t^2 - 191/23328000*t^4 + 7579/188956800000*t^6 + O(t^7), t + O(t^7))
sage: H.local_coord(H(0, 1, 0), prec=5)
(t^-2 + 23*t^2 - 18*t^4 - 569*t^6 + O(t^7),
 t^-5 + 46*t^-1 - 36*t - 609*t^3 + 1656*t^5 + O(t^6))
R.<x> = QQ['x']
H = HyperellipticCurve(x^5 - 23*x^3 + 18*x^2 + 40*x)
H.local_coord(H(1 ,6), prec=5)
H.local_coord(H(4, 0), prec=7)
H.local_coord(H(0, 1, 0), prec=5)

AUTHOR:

  • Jennifer Balakrishnan (2007-12)

local_coordinates_at_infinity(prec=20, name='t')#

For the genus g hyperelliptic curve y2=f(x), return (x(t),y(t)) such that (y(t))2=f(x(t)), where t=xg/y is the local parameter at infinity

INPUT:

  • prec – desired precision of the local coordinates

  • name – generator of the power series ring (default: t)

OUTPUT:

(x(t),y(t)) such that y(t)2=f(x(t)) and t=xg/y is the local parameter at infinity

EXAMPLES:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^5 - 5*x^2 + 1)
sage: x, y = H.local_coordinates_at_infinity(10)
sage: x
t^-2 + 5*t^4 - t^8 - 50*t^10 + O(t^12)
sage: y
t^-5 + 10*t - 2*t^5 - 75*t^7 + 50*t^11 + O(t^12)
R.<x> = QQ['x']
H = HyperellipticCurve(x^5 - 5*x^2 + 1)
x, y = H.local_coordinates_at_infinity(10)
x
y
sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^3 - x + 1)
sage: x, y = H.local_coordinates_at_infinity(10)
sage: x
t^-2 + t^2 - t^4 - t^6 + 3*t^8 + O(t^12)
sage: y
t^-3 + t - t^3 - t^5 + 3*t^7 - 10*t^11 + O(t^12)
R.<x> = QQ['x']
H = HyperellipticCurve(x^3 - x + 1)
x, y = H.local_coordinates_at_infinity(10)
x
y

AUTHOR:

  • Jennifer Balakrishnan (2007-12)

local_coordinates_at_nonweierstrass(P, prec=20, name='t')#

For a non-Weierstrass point P=(a,b) on the hyperelliptic curve y2=f(x), return (x(t),y(t)) such that (y(t))2=f(x(t)), where t=xa is the local parameter.

INPUT:

  • P = (a, b) – a non-Weierstrass point on self

  • prec – desired precision of the local coordinates

  • name – gen of the power series ring (default: t)

OUTPUT:

(x(t),y(t)) such that y(t)2=f(x(t)) and t=xa is the local parameter at P

EXAMPLES:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^5 - 23*x^3 + 18*x^2 + 40*x)
sage: P = H(1, 6)
sage: x, y = H.local_coordinates_at_nonweierstrass(P, prec=5)
sage: x
1 + t + O(t^5)
sage: y
6 + t - 7/2*t^2 - 1/2*t^3 - 25/48*t^4 + O(t^5)
sage: Q = H(-2, 12)
sage: x, y = H.local_coordinates_at_nonweierstrass(Q, prec=5)
sage: x
-2 + t + O(t^5)
sage: y
12 - 19/2*t - 19/32*t^2 + 61/256*t^3 - 5965/24576*t^4 + O(t^5)
R.<x> = QQ['x']
H = HyperellipticCurve(x^5 - 23*x^3 + 18*x^2 + 40*x)
P = H(1, 6)
x, y = H.local_coordinates_at_nonweierstrass(P, prec=5)
x
y
Q = H(-2, 12)
x, y = H.local_coordinates_at_nonweierstrass(Q, prec=5)
x
y

AUTHOR:

  • Jennifer Balakrishnan (2007-12)

local_coordinates_at_weierstrass(P, prec=20, name='t')#

For a finite Weierstrass point on the hyperelliptic curve y2=f(x), returns (x(t),y(t)) such that (y(t))2=f(x(t)), where t=y is the local parameter.

INPUT:

  • P – a finite Weierstrass point on self

  • prec – desired precision of the local coordinates

  • name – gen of the power series ring (default: t)

OUTPUT:

(x(t),y(t)) such that y(t)2=f(x(t)) and t=y is the local parameter at P

EXAMPLES:

sage: R.<x> = QQ['x']
sage: H = HyperellipticCurve(x^5 - 23*x^3 + 18*x^2 + 40*x)
sage: A = H(4, 0)
sage: x, y = H.local_coordinates_at_weierstrass(A, prec=7)
sage: x
4 + 1/360*t^2 - 191/23328000*t^4 + 7579/188956800000*t^6 + O(t^7)
sage: y
t + O(t^7)
sage: B = H(-5, 0)
sage: x, y = H.local_coordinates_at_weierstrass(B, prec=5)
sage: x
-5 + 1/1260*t^2 + 887/2000376000*t^4 + O(t^5)
sage: y
t + O(t^5)
R.<x> = QQ['x']
H = HyperellipticCurve(x^5 - 23*x^3 + 18*x^2 + 40*x)
A = H(4, 0)
x, y = H.local_coordinates_at_weierstrass(A, prec=7)
x
y
B = H(-5, 0)
x, y = H.local_coordinates_at_weierstrass(B, prec=5)
x
y
AUTHOR:
  • Jennifer Balakrishnan (2007-12)

    • Francis Clarke (2012-08-26)

monsky_washnitzer_gens()#
odd_degree_model()#

Return an odd degree model of self, or raise ValueError if one does not exist over the field of definition.

EXAMPLES:

sage: x = QQ['x'].gen()
sage: H = HyperellipticCurve((x^2 + 2)*(x^2 + 3)*(x^2 + 5)); H
Hyperelliptic Curve over Rational Field defined by y^2 = x^6 + 10*x^4 + 31*x^2 + 30
sage: H.odd_degree_model()
Traceback (most recent call last):
...
ValueError: No odd degree model exists over field of definition

sage: K2 = QuadraticField(-2, 'a')                                          # needs sage.rings.number_field
sage: Hp2 = H.change_ring(K2).odd_degree_model(); Hp2                       # needs sage.rings.number_field
Hyperelliptic Curve over Number Field in a
 with defining polynomial x^2 + 2 with a = 1.414213562373095?*I
 defined by y^2 = 6*a*x^5 - 29*x^4 - 20*x^2 + 6*a*x + 1

sage: K3 = QuadraticField(-3, 'b')                                          # needs sage.rings.number_field
sage: Hp3 = H.change_ring(QuadraticField(-3, 'b')).odd_degree_model(); Hp3  # needs sage.rings.number_field
Hyperelliptic Curve over Number Field in b
 with defining polynomial x^2 + 3 with b = 1.732050807568878?*I
 defined by y^2 = -4*b*x^5 - 14*x^4 - 20*b*x^3 - 35*x^2 + 6*b*x + 1

Of course, ``Hp2`` and ``Hp3`` are isomorphic over the composite
extension.  One consequence of this is that odd degree models
reduced over "different" fields should have the same number of
points on their reductions.  43 and 67 split completely in the
compositum, so when we reduce we find:

sage: # needs sage.rings.number_field
sage: P2 = K2.factor(43)[0][0]
sage: P3 = K3.factor(43)[0][0]
sage: Hp2.change_ring(K2.residue_field(P2)).frobenius_polynomial()
x^4 - 16*x^3 + 134*x^2 - 688*x + 1849
sage: Hp3.change_ring(K3.residue_field(P3)).frobenius_polynomial()
x^4 - 16*x^3 + 134*x^2 - 688*x + 1849

sage: H.change_ring(GF(43)).odd_degree_model().frobenius_polynomial()       # needs sage.rings.finite_rings
x^4 - 16*x^3 + 134*x^2 - 688*x + 1849

sage: # needs sage.rings.number_field
sage: P2 = K2.factor(67)[0][0]
sage: P3 = K3.factor(67)[0][0]
sage: Hp2.change_ring(K2.residue_field(P2)).frobenius_polynomial()
x^4 - 8*x^3 + 150*x^2 - 536*x + 4489
sage: Hp3.change_ring(K3.residue_field(P3)).frobenius_polynomial()
x^4 - 8*x^3 + 150*x^2 - 536*x + 4489

sage: H.change_ring(GF(67)).odd_degree_model().frobenius_polynomial()       # needs sage.rings.finite_rings
x^4 - 8*x^3 + 150*x^2 - 536*x + 4489
x = QQ['x'].gen()
H = HyperellipticCurve((x^2 + 2)*(x^2 + 3)*(x^2 + 5)); H
H.odd_degree_model()
K2 = QuadraticField(-2, 'a')                                          # needs sage.rings.number_field
Hp2 = H.change_ring(K2).odd_degree_model(); Hp2                       # needs sage.rings.number_field
K3 = QuadraticField(-3, 'b')                                          # needs sage.rings.number_field
Hp3 = H.change_ring(QuadraticField(-3, 'b')).odd_degree_model(); Hp3  # needs sage.rings.number_field
# needs sage.rings.number_field
P2 = K2.factor(43)[0][0]
P3 = K3.factor(43)[0][0]
Hp2.change_ring(K2.residue_field(P2)).frobenius_polynomial()
Hp3.change_ring(K3.residue_field(P3)).frobenius_polynomial()
H.change_ring(GF(43)).odd_degree_model().frobenius_polynomial()       # needs sage.rings.finite_rings
# needs sage.rings.number_field
P2 = K2.factor(67)[0][0]
P3 = K3.factor(67)[0][0]
Hp2.change_ring(K2.residue_field(P2)).frobenius_polynomial()
Hp3.change_ring(K3.residue_field(P3)).frobenius_polynomial()
H.change_ring(GF(67)).odd_degree_model().frobenius_polynomial()       # needs sage.rings.finite_rings
rational_points(**kwds)#

Find rational points on the hyperelliptic curve, all arguments are passed on to sage.schemes.generic.algebraic_scheme.rational_points().

EXAMPLES:

For the LMFDB genus 2 curve 932.a.3728.1:

sage: R.<x> = PolynomialRing(QQ)
sage: C = HyperellipticCurve(R([0, -1, 1, 0, 1, -2, 1]), R([1]))
sage: C.rational_points(bound=8)
[(-1 : -3 : 1),
(-1 : 2 : 1),
(0 : -1 : 1),
(0 : 0 : 1),
(0 : 1 : 0),
(1/2 : -5/8 : 1),
(1/2 : -3/8 : 1),
(1 : -1 : 1),
(1 : 0 : 1)]
R.<x> = PolynomialRing(QQ)
C = HyperellipticCurve(R([0, -1, 1, 0, 1, -2, 1]), R([1]))
C.rational_points(bound=8)

Check that github issue #29509 is fixed for the LMFDB genus 2 curve 169.a.169.1:

sage: C = HyperellipticCurve(R([0, 0, 0, 0, 1, 1]), R([1, 1, 0, 1]))
sage: C.rational_points(bound=10)
[(-1 : 0 : 1),
(-1 : 1 : 1),
(0 : -1 : 1),
(0 : 0 : 1),
(0 : 1 : 0)]
C = HyperellipticCurve(R([0, 0, 0, 0, 1, 1]), R([1, 1, 0, 1]))
C.rational_points(bound=10)

An example over a number field:

sage: R.<x> = PolynomialRing(QuadraticField(2))                             # needs sage.rings.number_field
sage: C = HyperellipticCurve(R([1, 0, 0, 0, 0, 1]))                         # needs sage.rings.number_field
sage: C.rational_points(bound=2)                                            # needs sage.rings.number_field
[(-1 : 0 : 1),
 (0 : -1 : 1),
 (0 : 1 : 0),
 (0 : 1 : 1),
 (1 : -a : 1),
 (1 : a : 1)]
R.<x> = PolynomialRing(QuadraticField(2))                             # needs sage.rings.number_field
C = HyperellipticCurve(R([1, 0, 0, 0, 0, 1]))                         # needs sage.rings.number_field
C.rational_points(bound=2)                                            # needs sage.rings.number_field
sage.schemes.hyperelliptic_curves.hyperelliptic_generic.is_HyperellipticCurve(C)#

EXAMPLES:

sage: from sage.schemes.hyperelliptic_curves.hyperelliptic_generic import is_HyperellipticCurve
sage: R.<x> = QQ[]; C = HyperellipticCurve(x^3 + x - 1); C
Hyperelliptic Curve over Rational Field defined by y^2 = x^3 + x - 1
sage: is_HyperellipticCurve(C)
True
from sage.schemes.hyperelliptic_curves.hyperelliptic_generic import is_HyperellipticCurve
R.<x> = QQ[]; C = HyperellipticCurve(x^3 + x - 1); C
is_HyperellipticCurve(C)