Hyperelliptic curves (smooth model) over a field¶
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
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
# TODO: weighted projective space doesnt have affine_patch
# sage: D = C.affine_patch(0)
# sage: D.defining_polynomials()[0].parent()
# Multivariate Polynomial Ring in x1, x2 over Rational Field
AUTHORS:
David Kohel (2006): initial version
Sabrina Kunzweiler, Gareth Ma, Giacomo Pope (2024): adapt to smooth model
- class sage.schemes.hyperelliptic_curves.hyperelliptic_generic.HyperellipticCurve_generic(defining_polynomial, f, h, genus: Integer, names=['x', 'y'])[source]¶
Bases:
WeightedProjectiveCurve- affine_coordinates(P)[source]¶
Return the affine coordinates of a point
Pofself. That is for \(P = [X,Y,Z]\), the output is \(X/Z, Y/Z^{(g+1)}\).EXAMPLES:
sage: R.<x> = QQ[] sage: H = HyperellipticCurve(x^6 - 1) sage: P = H.point([2,0,2]) sage: H.affine_coordinates(P) (1, 0) sage: Q = H.point([1,1,0]) sage: H.affine_coordinates(Q) Traceback (most recent call last): ... ValueError: The point (1 : 1 : 0) is not an affine point of Hyperelliptic Curve over Rational Field defined by y^2 = x^6 - 1
- base_extend(R)[source]¶
alias of
change_ring().
- base_ring()[source]¶
Return the base ring of the hyperelliptic curve.
EXAMPLES:
sage: R.<x> = QQ[] sage: H = HyperellipticCurve(x^7 + 3*x + 2) sage: H.base_ring() Rational Field sage: S.<x> = FiniteField(19)[] sage: H = HyperellipticCurve(x^5 - x + 2) sage: H.base_ring() Finite Field of size 19
- change_ring(R)[source]¶
Return this hyperelliptic curve over a new ring
R.EXAMPLES:
sage: R.<x> = QQ[] sage: H = HyperellipticCurve(x^5 - 10*x + 9) sage: K = Qp(3, 5) # optional - sage.rings.padics sage: L.<a> = K.extension(x^30 - 3) # optional - sage.rings.padics sage: HK = H.change_ring(K) # optional - sage.rings.padics sage: HL = HK.change_ring(L); HL # optional - sage.rings.padics 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)[] # optional - sage.rings.finite_rings sage: H = HyperellipticCurve(x^8 + x + 5) # optional - sage.rings.finite_rings sage: H.base_extend(FiniteField(7^2, 'a')) # optional - sage.rings.finite_rings Hyperelliptic Curve over Finite Field in a of size 7^2 defined by y^2 = x^8 + x + 5
It is also possible to compute the reduction at a prime by changing the base ring to the residue field:
sage: R.<x> = PolynomialRing(QQ); sage: H = HyperellipticCurve(R([0, -1, 2, 0, -2]), R([0, 1, 0, 1])); #LMFDB label: 763.a.763.1 sage: H.change_ring(FiniteField(2)) Hyperelliptic Curve over Finite Field of size 2 defined by y^2 + (x^3 + x)*y = x sage: H.change_ring(FiniteField(3)) Hyperelliptic Curve over Finite Field of size 3 defined by y^2 + (x^3 + x)*y = x^4 + 2*x^2 + 2*x
Note that this only works when the curve has good reduction at \(p\):
sage: H.change_ring(FiniteField(7)) Traceback (most recent call last): ... ValueError: singularity in the provided affine patch
- discriminant()[source]¶
Return the discriminant of this curve.
The discriminant of the hyperelliptic curve \(y^2 + hy = f\) is \(\Delta = 2^{-4(g + 1)} \Delta(h^2 + 4f)\). See https://www.math.u-bordeaux.fr/~qliu/Notes/disc.pdf for the derivation.
EXAMPLES:
sage: R.<x> = QQ[] sage: f = 2*x^6 + x^2 - 3*x + 1 sage: h = x^2 + x + 1 sage: H = HyperellipticCurve(f, h) sage: H.discriminant() -1622970410 sage: F = 4*f + h^2 sage: Delta = F.discriminant() / 16^3; Delta -1622970410 sage: G = f.derivative()^2 - f*h.derivative()^2 + f.derivative()*h.derivative()*h sage: F.resultant(G) == Delta^2*F.lc()^2 True
sage: # H.affine_patch() is not implemented sage: H_patch = H.projective_curve().affine_patch(2) sage: for p in prime_range(3, 50): ....: Hp = H_patch.change_ring(GF(p)) ....: assert Hp.is_smooth() == (H.discriminant() % p != 0)
- distinguished_point()[source]¶
Return the distinguished point of the hyperelliptic curve. By default, this is one of the points at infinity if possible.
See also
set_distinguished_point()EXAMPLE:
sage: R.<x> = GF(11)[] sage: H1 = HyperellipticCurve(x^2 + x, x^5 - 3*x + 4) sage: H1.distinguished_point() (1 : 0 : 0) sage: H2 = HyperellipticCurve(x^6 + x^5 + 1, 2*x^3) sage: H2.points_at_infinity() [] sage: H2.distinguished_point() (0 : 1 : 1)
- genus()[source]¶
Return the genus of the hyperelliptic curve.
EXAMPLES:
sage: R.<x> = QQ[] sage: H = HyperellipticCurve(x^7 + 3*x + 2) sage: H.genus() 3 sage: H = HyperellipticCurve(x^3 + 2, x^5 + 1) sage: H.genus() 4
- has_odd_degree_model()[source]¶
Return
Trueif an odd degree model ofselfexists over the field of definition;Falseotherwise.Use
odd_degree_modelto 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
- hyperelliptic_involution(P)[source]¶
Return the image of
Punder the hyperelliptic involution.EXAMPLES:
sage: R.<x> = FiniteField(17)[] sage: H = HyperellipticCurve(x^6 + 2, x^2 + 1) sage: P = H.point([8,12]) sage: P_inv = H.hyperelliptic_involution(P); P_inv (8 : 8 : 1) sage: H.hyperelliptic_involution(P_inv) == P True sage: Q = H.point([15,6]) sage: H.is_weierstrass_point(Q) True sage: H.hyperelliptic_involution(Q) == Q True
- hyperelliptic_polynomials()[source]¶
Return the polynomials \((f, h)\) such that \(C : y^2 + hy = f\).
EXAMPLES:
sage: R.<x> = PolynomialRing(QQ) sage: H = HyperellipticCurve(R([0, 1, 2, 0, 0, 1]), R([1, 1, 0, 1])) sage: H.hyperelliptic_polynomials() (x^5 + 2*x^2 + x, x^3 + x + 1) sage: H = HyperellipticCurve(x^7 + x + 2) sage: H.hyperelliptic_polynomials() (x^7 + x + 2, 0)
- invariant_differential()[source]¶
Return \(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
- is_inert()[source]¶
Return
Trueif the curve is inert, i.e. there are no rational points at infinity.EXAMPLES:
sage: R.<x> = PolynomialRing(QQ) sage: H = HyperellipticCurve(x^6+1,-x^3+1) sage: H.is_inert() True sage: K.<a> = QQ.extension(x^2+x-1) sage: HK = H.change_ring(K) sage: HK.is_inert() False sage: HF = H.change_ring(FiniteField(29)) sage: HF.is_inert() False
- is_ramified()[source]¶
Return
Trueif the curve is ramified, i.e. there is exactly one rational point at infinity.EXAMPLES:
sage: R.<x> = PolynomialRing(QQ) sage: H = HyperellipticCurve(x^5+1) sage: H.is_ramified() True sage: H = HyperellipticCurve(x^5+1, x^3+1) sage: H.is_ramified() False
- is_singular()[source]¶
Return
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
- is_smooth()[source]¶
Return
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
- is_split()[source]¶
Return
Trueif the curve is split, i.e. there are two rational points at infinity.EXAMPLES:
sage: R.<x> = PolynomialRing(QQ) sage: H = HyperellipticCurve(x^6+1, x^3+1) sage: H.is_split() False sage: HK = H.change_ring(FiniteField(19)) sage: HK.is_split() True
- is_weierstrass_point(P)[source]¶
Return
TrueifPis a Weierstrass point ofself.TODO: It would be better to define this function for points directly.
EXAMPLES:
sage: R.<x> = QQ[] sage: H = HyperellipticCurve(x^6 - 1) sage: P = H.point([1,0]) sage: H.is_weierstrass_point(P) True sage: Q = H.point([1,1,0]) sage: H.is_weierstrass_point(Q) False
This also works for hyperelliptic curves with \(h(x)\) nonzero. Note that in this case the \(y\)-coordinate of a Weierstrass point is not necessarily zero:
sage: R.<x> = FiniteField(17)[] sage: H = HyperellipticCurve(x^6 + 2, x^2 + 1) sage: P = H.point([15,6,1]) sage: H.is_weierstrass_point(P) True sage: Q = H.point([3,0,1]) sage: H.is_weierstrass_point(Q) False
- is_x_coord(x)[source]¶
Return
Trueifxis the \(x\)-coordinate of a point on this curve.See also
See also
lift_x()to find the point(s) with a given \(x\)-coordinate. This function may be useful in cases where testing an element of the base field for being a square is faster than finding its square root.INPUT:
x– an element of the base ring of the curve
OUTPUT:
A bool stating whether or not
xis the \(x\)-coordinate of a point on the curveEXAMPLES:
When \(x\) is the \(x\)-coordinate of a rational point on the curve, we can request these:
sage: R.<x> = PolynomialRing(QQ) sage: f = x^5 + x^3 + 1 sage: H = HyperellipticCurve(f) sage: H.is_x_coord(0) True
There are no rational points with \(x\)-coordinate 3:
sage: H.is_x_coord(3) False
The function also handles the case when \(h(x)\) is not zero:
sage: R.<x> = PolynomialRing(QQ) sage: f = x^5 + x^3 + 1 sage: h = x + 1 sage: H = HyperellipticCurve(f, h) sage: H.is_x_coord(1) True
We can perform these operations over finite fields too:
sage: # needs sage.rings.finite_rings sage: R.<x> = PolynomialRing(GF(163)) sage: f = x^7 + x + 1 sage: H = HyperellipticCurve(f) sage: H.is_x_coord(13) True
Including the case of characteristic two:
sage: # needs sage.rings.finite_rings sage: F.<z4> = GF(2^4) sage: R.<x> = PolynomialRing(F) sage: f = x^7 + x^3 + 1 sage: h = x + 1 sage: H = HyperellipticCurve(f, h) sage: H.is_x_coord(z4^3 + z4^2 + z4) True
AUTHORS:
Giacomo Pope (2024): adapted from
lift_x()
- jacobian()[source]¶
Return the Jacobian of the hyperelliptic curve.
Elements of the Jacobian are represented by tuples of the form \((u, v, n)\), where
\((u, v)\) is the Mumford representative of a divisor \(P_1 + ... + P_r\),
\(n\) is a non-negative integer
This tuple represents the equivalence class
\[[P_1 + ... + P_r + n \cdot \infty_+ + m\cdot \infty_- - D_\infty],\]where \(m = g - \deg(u) - n\), and \(\infty_+\), \(\infty_-\) are the points at infinity of the hyperelliptic curve,
\[D_\infty = \lceil g/2 \rceil \infty_+ + \lfloor g/2 \rfloor \infty_-.\]Here, \(\infty_- = \infty_+\), if the hyperelliptic curve is ramified.
Such a representation exists and is unique, unless the genus \(g\) is odd and the curve is inert.
If the hyperelliptic curve is ramified or inert, then \(n\) can be deduced from \(\deg(u)\) and \(g\). In these cases, \(n\) is omitted in the description.
EXAMPLES:
sage: R.<x> = QQ[] sage: H = HyperellipticCurve(2*x^5 + 4*x^4 + x^3 - x, x^3 + x + 1) sage: J = H.jacobian(); J Jacobian of Hyperelliptic Curve over Rational Field defined by y^2 + (x^3 + x + 1)*y = 2*x^5 + 4*x^4 + x^3 - x
The points \(P = (0, 0)\) and \(Q = (-1, -1)\) are on \(H\). We construct the element \(D_1 = [P - Q] = [P + (-Q) - D_\infty\)] on the Jacobian:
sage: P = H.point([0, 0]) sage: Q = H.point([-1, -1]) sage: D1 = J(P,Q); D1 (x^2 + x, -2*x : 0)
Elements of the Jacobian can also be constructed by directly providing the Mumford representation:
sage: D1 == J(x^2 + x, -2*x, 0) True
We can also embed single points into the Jacobian. Below we construct \(D_2 = [P - P_0]\), where \(P_0\) is the distinguished point of \(H\) (by default one of the points at infinity):
sage: D2 = J(P); D2 (x, 0 : 0) sage: P0 = H.distinguished_point(); P0 (1 : 0 : 0) sage: D2 == J(P, P0) True
We may add elements, or multiply by integers:
sage: 2*D1 (x, -1 : 1) sage: D1 + D2 (x^2 + x, -1 : 0) sage: -D2 (x, -1 : 1)
Note that the neutral element is given by \([D_\infty - D_\infty]\), in particular \(n = \lceil g/2 \rceil\):
sage: J.zero() (1, 0 : 1)
There are two more elements of the Jacobian that are only supported at infinity: \([\infty_+ - \infty_-]\) and \([\infty_- - \infty_+]\):
sage: [P_plus, P_minus] = H.points_at_infinity() sage: P_plus == P0 True sage: J(P_plus,P_minus) (1, 0 : 2) sage: J(P_minus, P_plus) (1, 0 : 0)
Now, we consider the Jacobian of a hyperelliptic curve with only one point at infinity, defined over a finite field:
sage: K = FiniteField(7) sage: R.<x> = K[] sage: H = HyperellipticCurve(x^7 + 3*x + 2) sage: J = H.jacobian(); J Jacobian of Hyperelliptic Curve over Finite Field of size 7 defined by y^2 = x^7 + 3*x + 2
Elements on the Jacobian can be constructed as before. But the value \(n\) is not used here, since there is exactly one point at infinity:
sage: P = H.point([3, 0]) sage: Q = H.point([5, 1]) sage: D1 = J(P,Q); D1 (x^2 + 6*x + 1, 3*x + 5) sage: D2 = J(x^3 + 3*x^2 + 4*x + 3, 2*x^2 + 4*x) sage: D1 + D2 (x^3 + 2, 4)
Over finite fields, we may also construct random elements and compute the order of the Jacobian:
sage: J.random_element() #random (x^3 + x^2 + 4*x + 5, 3*x^2 + 3*x) sage: J.order() 344
Note that arithmetic on the Jacobian is not implemented if the underlying hyperelliptic curve is inert (i.e. has no points at infinity) and the genus is odd:
sage: R.<x> = GF(13)[] sage: H = HyperellipticCurve(x^8+1,x^4+1) sage: J = H.jacobian() sage: J.zero() Traceback (most recent call last): ... ValueError: unable to perform arithmetic for inert models of odd genus
- lift_x(x, all=False)[source]¶
Return one or all finite points with given \(x\)-coordinate.
This method is deterministic: It returns the same data each time when called again with the same \(x\).
INPUT:
x– an element of the base ring of the curveall(bool, defaultFalse) – ifTrue, return a (possibly empty) list of all points; ifFalse, return just one point, or raise aValueErrorif there are none.
OUTPUT:
A point or list of up to two points on this curve.
See also
AUTHORS:
Giacomo Pope (2024): Allowed for the case of characteristic two
EXAMPLES:
When \(x\) is the \(x\)-coordinate of a rational point on the curve, we can request these:
sage: R.<x> = PolynomialRing(QQ) sage: f = x^5 + x^3 + 1 sage: H = HyperellipticCurve(f) sage: H.lift_x(0) (0 : -1 : 1) sage: H.lift_x(4, all=True) [(4 : -33 : 1), (4 : 33 : 1)]
There are no rational points with \(x\)-coordinate 3:
sage: H.lift_x(3) Traceback (most recent call last): ... ValueError: No point with x-coordinate 3 on Hyperelliptic Curve over Rational Field defined by y^2 = x^5 + x^3 + 1
An empty list is returned when there are no points and
all=True:sage: H.lift_x(3, all=True) []
The function also handles the case when \(h(x)\) is not zero:
sage: R.<x> = PolynomialRing(QQ) sage: f = x^5 + x^3 + 1 sage: h = x + 1 sage: H = HyperellipticCurve(f, h) sage: H.lift_x(1) (1 : -3 : 1)
We can perform these operations over finite fields too:
sage: # needs sage.rings.finite_rings sage: R.<x> = PolynomialRing(GF(163)) sage: f = x^7 + x + 1 sage: H = HyperellipticCurve(f) sage: H.lift_x(13) (13 : 41 : 1)
Including the case of characteristic two:
sage: # needs sage.rings.finite_rings sage: F.<z4> = GF(2^4) sage: R.<x> = PolynomialRing(F) sage: f = x^7 + x^3 + 1 sage: h = x + 1 sage: H = HyperellipticCurve(f, h) sage: H.lift_x(z4^3 + z4^2 + z4, all=True) [(z4^3 + z4^2 + z4 : z4^2 + z4 + 1 : 1), (z4^3 + z4^2 + z4 : z4^3 : 1)]
Points at infinity are not included, as they do not have a unique x-coordinate:
sage: R.<x> = QQ[] sage: H = HyperellipticCurve(x^8 + 1) sage: H(1, -1, 0) (1 : -1 : 0) sage: H.lift_x(1, all=True) []
- local_coord(P, prec=20, name='t')[source]¶
For point
P = (a,b)on the hyperelliptic curve \(y^2 + h(x)*y = f(x)\), return \((x(t), y(t))\) such that \((y(t))^2 + h(x(t))*y(t) = f(x(t))\), where \(t\) is the local parameter at that point.INPUT:
P– a point onselfprec– desired precision of the local coordinatesname– generator of the power series ring (default:t)
OUTPUT:
\((x(t),y(t))\) such that \(y(t)^2 + h(x(t))*y(t) = f(x(t))\), where \(t\) is the local parameter at \(P\)
EXAMPLES:
We compute the local coordinates of several points of the curve with defining equation \(y^2 = x^5 - 23 x^3 + 18 x^2 + 40 x\):
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(1, 0, 0), prec=5) (t^-2 - 23*t^2 + 18*t^4 - 1018*t^6 + O(t^7), t^-5 - 69*t^-1 + 54*t - 1467*t^3 + 3726*t^5 + O(t^6))
We compute the local coordinates of several points of the curve with defining equation \(y^2 + (x^3 + 1) y = x^4 + 2 x^3 + x^2 - x\).
sage: H = HyperellipticCurve(x^4+2*x^3+x^2-x,x^3+1) sage: H.local_coord(H(1,-3,1), prec=5) (1 + t + O(t^5), -3 - 5*t - 3*t^2 - 3/4*t^3 - 3/16*t^4 + O(t^5)) sage: H.local_coord(H(1,-1,0), prec=5) (t^-1 + O(t^7), -t^-3 - t^-1 - 3 + 6*t^2 + 6*t^3 - 12*t^4 - 42*t^5 + O(t^6))
AUTHOR:
Jennifer Balakrishnan (2007-12)
Sabrina Kunzweiler, Gareth Ma, Giacomo Pope (2024): adapt to smooth model
- local_coordinates_at_infinity_ramified(prec=20, name='t')[source]¶
For a hyperelliptic curve with ramified model \(y^2 + h(x)*y = f(x)\), return \((x(t), y(t))\) such that \((y(t))^2 = f(x(t))\), where \(t = y/x^{g+1}\) is the local parameter at the unique (Weierstrass) point at infinity.
TODO/NOTE: In the previous implementation \(t = x^g/y\) was used. This is not a valid parameter on the smooth model, and the output is necessarily different.
INPUT:
prec– desired precision of the local coordinatesname– generator of the power series ring (default:t)
OUTPUT:
\((x(t),y(t))\) such that \(y(t)^2 = f(x(t))\) and \(t = y/x^{g+1}\) is the local parameter at infinity
EXAMPLES:
We compute the local coordinates at the point at infinity of the hyperelliptic curve \(y^2 = x^5 - 5 x^2 + 1\):
sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^5 - 5*x^2 + 1) sage: xt, yt = H.local_coordinates_at_infinity_ramified(prec=10) sage: (xt,yt) (t^-2 - 5*t^4 + t^8 - 75*t^10 + O(t^12), t^-5 - 15*t + 3*t^5 - 150*t^7 + 90*t^11 + O(t^12))
We verify that \(y(t)^2 = f(x(t))\) and \(t = y(t)/x(t)^3\):
sage: f,_ = H.hyperelliptic_polynomials() sage: (yt^2 - f(xt)).is_zero() True sage: yt/xt^3 t + O(t^15)
The method also works when \(h\) is nonzero. We compute the local coordinates of the point at infinity of the hyperelliptic curve \(y^2 + y = x^5 - 9 x^4 + 14 x^3 - 19 x^2 + 11 x - 6\):
sage: H = HyperellipticCurve(x^5-9*x^4+14*x^3-19*x^2+11*x-6,1) sage: f,h = H.hyperelliptic_polynomials() sage: xt,yt = H.local_coordinates_at_infinity_ramified() sage: (yt^2 + h(xt)*yt - f(xt)).is_zero() True
Note that the point at infinity has to be a Weierstrass point.
AUTHOR:
Jennifer Balakrishnan (2007-12)
Sabrina Kunzweiler, Gareth Ma, Giacomo Pope (2024): adapt to smooth model
- local_coordinates_at_infinity_split(P, prec=20, name='t')[source]¶
For a point at infinity
P = (a:b:0)on a hyperelliptic curve with split model \(y^2 + h(x)*y = f(x)\), return \((x(t), y(t))\) such that \((y(t))^2 = f(x(t))\). Here \(t = a/x\) is the local parameter atP.INPUT:
P– a point at infinity of a selfprec– desired precision of the local coordinatesname– generator of the power series ring (default:t)
OUTPUT:
\((x(t),y(t))\) such that \(y(t)^2 = f(x(t))\) and \(t = y/x^{g+1}\) is the local parameter at infinity
EXAMPLES:
We compute the local coordinates at the point at infinity of the hyperelliptic curve:
sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^6+4*x^4 + 4*x^2+1) sage: P1 = H(1,-1,0) sage: xt1,yt1 = H.local_coordinates_at_infinity_split(P1)
Note the similarity to the local coordinates of the other point at infinity:
sage: P2 = H(1,1,0) sage: xt2,yt2 = H.local_coordinates_at_infinity_split(P2) sage: xt1 == xt2 and yt1 == - yt2 True
Similarly, if \(h\) is nonzero, the relation between the local coordinates at the points at infinity is obtained from the hyperelliptic involution:
sage: H = HyperellipticCurve(-x^5, x^3+x+1) sage: f,h = H.hyperelliptic_polynomials() sage: P1 = H(1,0,0) sage: P2 = H(1,-1,0) sage: xt1,yt1 = H.local_coordinates_at_infinity_split(P1) sage: xt2,yt2 = H.local_coordinates_at_infinity_split(P2) sage: (yt1 + yt2 + h(xt1)).is_zero() True
AUTHOR:
Jennifer Balakrishnan (2007-12)
Sabrina Kunzweiler, Gareth Ma, Giacomo Pope (2024): adapt to smooth model
- local_coordinates_at_nonweierstrass(P, prec=20, name='t')[source]¶
For a non-Weierstrass point
P = (a, b)on the hyperelliptic curve \(y^2 + h(x) * y = f(x)\), return \((x(t), y(t))\) such that \((y(t))^2 = f(x(t))\), where \(t = x - a\) is the local parameter.INPUT:
P = (a, b)– a non-Weierstrass point onselfprec– desired precision of the local coordinatesname– gen of the power series ring (default:t)
OUTPUT:
\((x(t),y(t))\) such that \(y(t)^2 + y(t)*h(x(t)) = f(x(t))\) and \(t = x - a\) is the local parameter at \(P\).
EXAMPLES:
We compute the local coordinates of \(H : y^2 = x^5 - 23*x^3 + 18*x^2 + 40*x\) at the point \(P = (1, 6)\):
sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^5 - 23*x^3 + 18*x^2 + 40*x) sage: P = H(1, 6) sage: xt, yt = H.local_coordinates_at_nonweierstrass(P, prec=5) sage: (xt, yt) (1 + t + O(t^5), 6 + t - 7/2*t^2 - 1/2*t^3 - 25/48*t^4 + O(t^5))
We verify that \(y(t) = f(x(t))\):
sage: f,_ = H.hyperelliptic_polynomials() sage: (yt^2 - f(xt)).is_zero() True
We can also compute the local coordinates of points on a hyperelliptic curve with equation \(y^2 + h(x)*y = f(x)\):
sage: H = HyperellipticCurve(x^6+3*x^5+6*x^4+7*x^3+6*x^2+3*x+1, x^2+x) # 196.a.21952.1 sage: P = H(-1,1) sage: xt, yt = H.local_coordinates_at_nonweierstrass(P, prec=5) sage: (xt, yt) (-1 + t + O(t^5), 1 - t + 3/2*t^2 - 3/4*t^3 + O(t^5)) sage: f,h = H.hyperelliptic_polynomials() sage: (yt^2 + h(xt)*yt -f(xt)).is_zero() True
AUTHORS:
Jennifer Balakrishnan (2007-12)
Sabrina Kunzweiler, Gareth Ma, Giacomo Pope (2024): adapt to smooth model
- local_coordinates_at_weierstrass(P, prec=20, name='t')[source]¶
For a finite Weierstrass point
P = (a,b)on the hyperelliptic curve \(y^2 + h(x)*y = f(x)\), return \((x(t), y(t))\) such that \(y(t)^2 + h(x(t))*y(t) = f(x(t))\), where \(t = y - b\) is the local parameter.INPUT:
P– a finite Weierstrass point onselfprec– desired precision of the local coordinatesname– gen of the power series ring (default: \(t\))
OUTPUT:
\((x(t),y(t))\) such that \(y(t)^2 + h(x(t))*y(t) = f(x(t))\) and \(t = y - b\) is the local parameter at \(P = (a,b)\).
EXAMPLES:
We compute the local coordinates of the Weierstrass point \(P = (4,0)\) on the hyperelliptic curve \(y^2 = x^5 - 23 x^3 + 18 x^2 + 40 x\):
sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^5 - 23*x^3 + 18*x^2 + 40*x) sage: P = H(4, 0) sage: xt, yt = H.local_coordinates_at_weierstrass(P, prec=7) sage: xt 4 + 1/360*t^2 - 191/23328000*t^4 + 7579/188956800000*t^6 + O(t^7) sage: yt t + O(t^7)
We verify that \(y(t) = f(x(t))\):
sage: f,_ = H.hyperelliptic_polynomials() sage: (yt^2 - f(xt)).is_zero() True
We compute the local coordinates at the Weierstrass point \((1,-1)\) of the hyperelliptic curve \(y^2 + (x^3 + 1) y = -x^2\):
sage: H = HyperellipticCurve(-x^2, x^3+1) sage: P = H(1,-1) sage: xt,yt = H.local_coordinates_at_weierstrass(P) sage: f,h = H.hyperelliptic_polynomials() sage: (yt^2 + h(xt)*yt - f(xt)).is_zero() True
AUTHOR:
Jennifer Balakrishnan (2007-12)
Francis Clarke (2012-08-26)
Sabrina Kunzweiler, Gareth Ma, Giacomo Pope (2024): adapt to smooth model
- monsky_washnitzer_gens()[source]¶
Compute the generators of the special hyperelliptic quotient ring
EXAMPLES:
sage: R.<x> = QQ[] sage: H = HyperellipticCurve(x^5+1) sage: [x0, y0] = H.monsky_washnitzer_gens(); x0, y0 (x, y*1) sage: x0^10 (1-2*y^2+y^4)*1
- odd_degree_model()[source]¶
Return an odd degree model of
self, or raiseValueErrorif one does not exist over the field of definition. The term odd degree model refers to a model of the form \(y^2 = f(x)\) with \(\deg(f) = 2 g + 1\).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,
Hp2andHp3are 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
The case where \(h(x)\) is nonzero is also supported:
sage: HyperellipticCurve(x^5 + 1, 1).odd_degree_model() Hyperelliptic Curve over Rational Field defined by y^2 = 4*x^5 + 5
- points_at_infinity()[source]¶
Compute the points at infinity on the curve.
EXAMPLES:
sage: R.<x> = PolynomialRing(QQ) sage: H = HyperellipticCurve(x^6 + 1, x^3 + 1) sage: H.points_at_infinity() [] sage: K.<omega> = QQ.extension(x^2 + x -1) sage: H.change_ring(K).points_at_infinity() [(1 : omega : 0), (1 : -omega - 1 : 0)]
sage: _.<x> = GF(103)[] sage: H = HyperellipticCurve(x^5 + 1) sage: H.points_at_infinity() [(1 : 0 : 0)] sage: H = HyperellipticCurve(x^6 + 1) sage: H.points_at_infinity() [(1 : 1 : 0), (1 : 102 : 0)] sage: H = HyperellipticCurve(3*x^6 + 1) sage: H.points_at_infinity() []
- polynomial_ring()[source]¶
Return the parent ring of the defining polynomials \(f, h\), of this hyperelliptic curve.
EXAMPLES:
sage: R.<x> = QQ[] sage: H = HyperellipticCurve(x^7 + 3*x + 2) sage: H.polynomial_ring() Univariate Polynomial Ring in x over Rational Field sage: # optional - sage.rings.padics sage: K = Qp(7, 10) sage: HK = H.change_ring(K) sage: HK.polynomial_ring() Univariate Polynomial Ring in x over 7-adic Field with capped relative precision 10
- projective_curve()[source]¶
Return a (singular) plane model of the hyperelliptic curve
self.TODO: renaming to plane_model ?
EXAMPLES:
We consider the hyperelliptic curve with affine equation \(y^2 = x^5 + x\):
sage: R.<x> = FiniteField(11)[] sage: H = HyperellipticCurve(x^6 + 2) sage: C = H.projective_curve(); C Projective Plane Curve over Finite Field of size 11 defined by -x^6 + y^2*z^4 - 2*z^6
Note that the projective coordinates of points on \(H\) and their images in \(C\) are in general not the same:
sage: P = H.point([9,4,2]) sage: Q = C.point([9,4,2]) Traceback (most recent call last): ... TypeError: Coordinates [10, 2, 1] do not define a point on Projective Plane Curve over Finite Field of size 11 defined by -x^6 + y^2*z^4 - 2*z^6
However, the affine coordinates coincide:
sage: H.affine_coordinates(P) (10, 6) sage: Q = C.point([10,6,1])
The model \(C\) has one singular point at infinity, while \(H\) is non-singular and has two points at infinity.
sage: H.points_at_infinity() [(1 : 1 : 0), (1 : 10 : 0)] sage: [P for P in C.rational_points() if P[2]==0] [(0 : 1 : 0)]
- rational_points(**kwds)[source]¶
Find rational points on the hyperelliptic curve. Arguments are passed on to
sage.schemes.generic.algebraic_scheme.rational_points().ALGORITHM:
We use
points_at_infinity()to compute the points at infinity, andsage.schemes.generic.algebraic_scheme.rational_points()on this curve’sprojective_curve()for the affine 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 : 1 : 0), (1 : -1 : 0), (-1 : -3 : 1), (-1 : 2 : 1), (0 : -1 : 1), (0 : 0 : 1), (1/2 : -5/8 : 1), (1/2 : -3/8 : 1), (1 : -1 : 1), (1 : 0 : 1)]
Check that 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) # long time (6s) [(1 : 0 : 0), (1 : -1 : 0), (-1 : 0 : 1), (-1 : 1 : 1), (0 : -1 : 1), (0 : 0 : 1)] 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) [(1 : 0 : 0), (-1 : 0 : 1), (0 : -1 : 1), (0 : 1 : 1), (1 : -a : 1), (1 : a : 1)] sage: R.<x> = QQ[] sage: H = HyperellipticCurve(x^8 + 33) sage: H.rational_points(bound=20) # long time (6s) [(1 : 1 : 0), (1 : -1 : 0), (-2 : -17 : 1), (-2 : 17 : 1), (2 : -17 : 1), (2 : 17 : 1)]
- rational_weierstrass_points()[source]¶
Return the rational Weierstrass points of the hyperelliptic curve. These are the points that are fixed by the hyperelliptic involution.
EXAMPLES:
When \(h(x)\) is zero, then the Weierstrass points are the points with \(y\)-coordinate equal to zero:
sage: R.<x> = QQ[] sage: H = HyperellipticCurve(x^5 - x) sage: H.rational_weierstrass_points() [(1 : 0 : 0), (1 : 0 : 1), (0 : 0 : 1), (-1 : 0 : 1)]
The function also handles the case with \(h(x)\) nonzero:
sage: R.<x> = FiniteField(17)[] sage: H = HyperellipticCurve(x^6 + 2, x^2 + 1) sage: H.rational_weierstrass_points() [(15 : 6 : 1), (2 : 6 : 1)] sage: P = H.point([15,6,1]) sage: H.is_weierstrass_point(P) True
- roots_at_infinity()[source]¶
Compute the roots of: \(Y^2 + h_{g+1} Y - f_{2g+2} = 0\).
When the curve is ramified, we expect one root. When the curve is split we expect two roots. When the curve is inert we expect zero roots.
EXAMPLES:
sage: R.<x> = PolynomialRing(QQ) sage: H = HyperellipticCurve(x^7 + 1) sage: H.roots_at_infinity() [0] sage: H = HyperellipticCurve(x^8 + 1) sage: H.roots_at_infinity() [1, -1] sage: H = HyperellipticCurve(-x^8 + 1) sage: H.roots_at_infinity() []
- set_distinguished_point(P0)[source]¶
Change the distinguished point of the hyperelliptic curve to
P0.EXAMPLES:
sage: R.<x> = PolynomialRing(QQ) sage: f = x^6 - 6*x^4 + x^2 + 28 sage: H = HyperellipticCurve(f) sage: H.distinguished_point() (1 : 1 : 0) sage: P = H(2,0) sage: H.set_distinguished_point(P) sage: H.distinguished_point() (2 : 0 : 1)
- split_G_plus_minus()[source]¶
Return \(G^{\pm(x)}\) for curves in the split degree model.
This is used for Cantor composition with points at infinity when performing arithmetic on the Jacobian. See Definition 4 in [GHM2008].
See also
cantor_compose_at_infinity()EXAMPLES:
sage: R.<x> = QQ[] sage: H = HyperellipticCurve(x^6 + x^4 + 1) sage: H.split_G_plus_minus() (x^3 + 1/2*x, -x^3 - 1/2*x) sage: H = HyperellipticCurve(4*x^6 + x^4 + 1) sage: H.split_G_plus_minus() (2*x^3 + 1/4*x, -2*x^3 - 1/4*x)
The function is only defined for hyperelliptic curves with two rational points at infinity:
sage: H = HyperellipticCurve(2*x^6 + x^4 + 1) sage: H.is_split() False sage: H.split_G_plus_minus() Traceback (most recent call last): ... ValueError: hyperelliptic curve does not have the split model
- weights()[source]¶
Return the weights of the weighted projective space this hyperelliptic curve lives in, i.e. \((1, g + 1, 1)\), where \(g\) is the genus of the curve.
EXAMPLES:
sage: R.<x> = GF(13)[] sage: H = HyperellipticCurve(x^5 - 1) sage: H.weights() (1, 3, 1) sage: H = HyperellipticCurve(x^9 - 1) sage: H.weights() (1, 5, 1)