-
-
Notifications
You must be signed in to change notification settings - Fork 517
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bugfix in the genus code (addresses #28336
)
- Loading branch information
katie
committed
Jan 26, 2025
1 parent
5188024
commit 98b29b9
Showing
1 changed file
with
86 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,8 @@ | |
AUTHORS: | ||
- William Stein (2005) | ||
- Katie Ahrens (2024): fixed #28336 | ||
""" | ||
# **************************************************************************** | ||
# Copyright (C) 2005 William Stein <[email protected]> | ||
|
@@ -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.<y> =QQ[] | ||
sage: R.<x> = 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 | ||
<https://stacks.math.columbia.edu/tag/0BYE>`_. This method does not | ||
check the condition. You may get a nonsensical result if the curve is | ||
not geometrically irreducible:: | ||
sage: P2.<x,y,z> = 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:: | ||
|