diff --git a/src/sage/schemes/curves/curve.py b/src/sage/schemes/curves/curve.py index be072ba3873..728f812b4e0 100644 --- a/src/sage/schemes/curves/curve.py +++ b/src/sage/schemes/curves/curve.py @@ -19,6 +19,8 @@ AUTHORS: - William Stein (2005) + +- Katie Ahrens (2024): fixed #28336 """ # **************************************************************************** # Copyright (C) 2005 William Stein @@ -38,8 +40,10 @@ from sage.schemes.generic.divisor_group import DivisorGroup from sage.schemes.generic.divisor import Divisor_curve +from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF from sage.rings.integer import Integer - +from sage.rings.rational_field import is_RationalField +from sage.rings.qqbar import QQbar class Curve_generic(AlgebraicScheme_subscheme): r""" @@ -153,8 +157,8 @@ def divisor_group(self, base_ring=None): INPUT: - - ``base_ring`` -- the base ring of the divisor group; usually, this is - `\ZZ` (default) or `\QQ` + - ``base_ring`` -- the base ring of the divisor group. Usually, this is + `\ZZ` (default) or `\QQ`. OUTPUT: the divisor group of the curve @@ -201,16 +205,52 @@ def genus(self): sage: C = Curve(y^2*z - x^3 - 17*x*z^2 + y*z^2) sage: C.genus() 1 + + Throw an error if the curve is not geometrically irreducible. Addresses issue #28336. + sage: x,y = PolynomialRing(QQ, 2, names='x,y').gens() + sage: C = Curve(x^2+y^2) + sage: C.genus() + Traceback (most recent call last): + ... + NotImplementedError: Curve is not geometrically irreducible + + sage: FF. =QQ[] + sage: R. = FF[] + sage: K = QQ[y, x] + sage: poly2 = K(x^2 - y^4) + sage: C2 = Curve(poly2) + sage: C2.genus() + Traceback (most recent call last): + ... + NotImplementedError: Curve is not irreducible over the ground field + + + Geometric irreducibility is also checked for finite fields. + sage: x,y = PolynomialRing(GF(5), 2, names='x,y').gens() + sage: C = Curve(x^2+2) + sage: C.genus() + Traceback (most recent call last): + ... + NotImplementedError: Curve is not geometrically irreducible """ + return self.geometric_genus() def geometric_genus(self): r""" Return the geometric genus of the curve. + This is by definition the genus of the normalization of the projective + closure of the curve over the algebraic closure of the base field; the + base field must be a prime field. + + .. NOTE:: + + This calls Singular's genus command. + EXAMPLES: - Examples of projective curves:: + Examples of projective curves. :: sage: P2 = ProjectiveSpace(2, GF(5), names=['x','y','z']) sage: x, y, z = P2.coordinate_ring().gens() @@ -224,7 +264,14 @@ def geometric_genus(self): sage: C.geometric_genus() 3 - Examples of affine curves:: + Addressing issue #28336 + sage: C = Curve(x^2+y^2) + sage: C.geometric_genus() + Traceback (most recent call last): + ... + NotImplementedError: Curve is not irreducible over the ground field + + Examples of affine curves. :: sage: x, y = PolynomialRing(GF(5), 2, 'xy').gens() sage: C = Curve(y^2 - x^3 - 17*x + y) @@ -237,22 +284,31 @@ def geometric_genus(self): sage: C.geometric_genus() 3 - .. WARNING:: - - Geometric genus is only defined for `geometrically irreducible curve - `_. This method does not - check the condition. You may get a nonsensical result if the curve is - not geometrically irreducible:: - - sage: P2. = ProjectiveSpace(QQ, 2) - sage: C = Curve(x^2 + y^2, P2) - sage: C.geometric_genus() # nonsense! - -1 """ + k=self.base_ring() + + #handle the rational case + if is_RationalField(k): + curve_over_closure = self.change_ring(QQbar) + if len(curve_over_closure.defining_polynomial().factor()) > 1: + if self.is_irreducible(): + raise NotImplementedError("Curve is not geometrically irreducible") + else: + raise NotImplementedError("Curve is not irreducible over the ground field") + + #handle the finite field case + if k.is_finite(): + if len(self.change_ring(GF(k.characteristic()**self.defining_polynomial().degree())).defining_polynomial().factor()) > 1: + if self.is_irreducible(): + raise NotImplementedError("Curve is not geometrically irreducible") + else: + raise NotImplementedError("Curve is not irreducible over the ground field") + try: return self._genus except AttributeError: - raise NotImplementedError + self._genus = self.defining_ideal().genus() + return self._genus def union(self, other): """ @@ -275,7 +331,9 @@ def singular_subscheme(self): r""" Return the subscheme of singular points of this curve. - OUTPUT: a subscheme in the ambient space of this curve + OUTPUT: + + - a subscheme in the ambient space of this curve. EXAMPLES:: @@ -313,10 +371,10 @@ def singular_points(self, F=None): INPUT: - - ``F`` -- (default: ``None``) field over which to find the singular + - ``F`` -- (default: None) field over which to find the singular points; if not given, the base ring of this curve is used - OUTPUT: list of points in the ambient space of this curve + OUTPUT: a list of points in the ambient space of this curve EXAMPLES:: @@ -360,13 +418,13 @@ def is_singular(self, P=None): INPUT: - - ``P`` -- (default: ``None``) a point on this curve + - ``P`` -- (default: None) a point on this curve OUTPUT: - boolean; if a point ``P`` is provided, and if ``P`` lies on this - curve, returns ``True`` if ``P`` is a singular point of this curve, and - ``False`` otherwise. If no point is provided, returns ``True`` or False + A boolean. If a point ``P`` is provided, and if ``P`` lies on this + curve, returns True if ``P`` is a singular point of this curve, and + False otherwise. If no point is provided, returns True or False depending on whether this curve is or is not singular, respectively. EXAMPLES:: @@ -393,9 +451,9 @@ def intersects_at(self, C, P): INPUT: - - ``C`` -- a curve in the same ambient space as this curve + - ``C`` -- a curve in the same ambient space as this curve. - - ``P`` -- a point in the ambient space of this curve + - ``P`` -- a point in the ambient space of this curve. EXAMPLES:: @@ -448,11 +506,11 @@ def intersection_points(self, C, F=None): - ``C`` -- a curve in the same ambient space as this curve - - ``F`` -- (default: ``None``) field over which to compute the + - ``F`` -- (default: None); field over which to compute the intersection points; if not specified, the base ring of this curve is used - OUTPUT: list of points in the ambient space of this curve + OUTPUT: a list of points in the ambient space of this curve EXAMPLES::