Skip to content

Commit

Permalink
Many fixes related with genus
Browse files Browse the repository at this point in the history
  • Loading branch information
kwankyu committed Mar 5, 2024
1 parent cb8e15b commit 2ccffbf
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 70 deletions.
23 changes: 21 additions & 2 deletions src/sage/rings/function_field/function_field_polymod.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,16 @@
from sage.rings.integer import Integer
from sage.categories.homset import Hom
from sage.categories.function_fields import FunctionFields
from sage.categories.number_fields import NumberFields

from .element import FunctionFieldElement
from .element_polymod import FunctionFieldElement_polymod
from .function_field import FunctionField
from .function_field_rational import RationalFunctionField

_FunctionFields = FunctionFields()
_NumberFields = NumberFields()


class FunctionField_polymod(FunctionField):
"""
Expand Down Expand Up @@ -160,7 +164,7 @@ def __init__(self, polynomial, names, category=None):
self._polynomial = polynomial

FunctionField.__init__(self, base_field, names=names,
category=FunctionFields().or_subcategory(category))
category=_FunctionFields.or_subcategory(category))

from .place_polymod import FunctionFieldPlace_polymod
self._place_class = FunctionFieldPlace_polymod
Expand Down Expand Up @@ -1842,11 +1846,26 @@ def genus(self):
sage: L.genus()
6
sage: # needs sage.rings.number_field
sage: R.<T> = QQ[]
sage: N.<a> = NumberField(T^2 + 1)
sage: K.<x> = FunctionField(N); K

Check failure on line 1852 in src/sage/rings/function_field/function_field_polymod.py

View workflow job for this annotation

GitHub Actions / build

Failed example:

Failed example:: Got: Rational function field in x over Number Field in a with defining polynomial T^2 + 1
sage: K.genus()
0
sage: S.<t> = PolynomialRing(K)
sage: L.<y> = K.extension(t^2 - x^3 + x)
sage: L.genus()
1
The genus is computed by the Hurwitz genus formula.
"""
k, _ = self.exact_constant_field()
if k in _NumberFields:
k_degree = k.relative_degree()
else:
k_degree = k.degree()
different_degree = self.different().degree() # must be even
return Integer(different_degree // 2 - self.degree() / k.degree()) + 1
return Integer(different_degree // 2 - self.degree() / k_degree) + 1

def residue_field(self, place, name=None):
"""
Expand Down
41 changes: 28 additions & 13 deletions src/sage/rings/polynomial/multi_polynomial_ideal.py
Original file line number Diff line number Diff line change
Expand Up @@ -1569,13 +1569,20 @@ def _groebner_basis_singular_raw(self, algorithm="groebner", singular=singular_d
@handle_AA_and_QQbar
def genus(self):
r"""
Return the genus of the projective curve defined by this ideal,
which must be 1 dimensional.
Return the geometric genus of the projective curve defined by this
ideal.
OUTPUT:
If the ideal is homogeneous and defines a curve in a projective space,
then the genus of the curve is returned. If the ideal is not
homogeneous and defines a curve in an affine space, the genus of the
projective closure of the curve is returned.
EXAMPLES:
Consider the hyperelliptic curve `y^2 = 4x^5 - 30x^3 + 45x -
22` over `\QQ`, it has genus 2::
Consider the hyperelliptic curve `y^2 = 4x^5 - 30x^3 + 45x - 22` over
`\QQ`, it has genus 2::
sage: P.<x> = QQ[]
sage: f = 4*x^5 - 30*x^3 + 45*x - 22
Expand All @@ -1592,28 +1599,36 @@ def genus(self):
sage: I.genus()
2
TESTS:
Check that the answer is correct for reducible curves::
Geometric genus is only defined for geometrically irreducible curves.
You may get a nonsensical answer if the condition is not met. A curve
reducible over a quadratic extension of `\QQ`::
sage: R.<x, y, z> = QQ[]
sage: C = Curve(x^2 - 2*y^2)
sage: C.is_singular()
True
sage: C.genus()
-1
sage: Ideal(x^4+y^2*x+x).genus()
TESTS:
An ideal that does not define a curve but we get a result! ::
sage: R.<x, y, z> = QQ[]
sage: Ideal(x^4 + y^2*x + x).genus()
0
An ideal that defines a geometrically reducible affine curve::
sage: T.<t1,t2,u1,u2> = QQ[]
sage: TJ = Ideal([t1^2 + u1^2 - 1,t2^2 + u2^2 - 1, (t1-t2)^2 + (u1-u2)^2 -1])
sage: TJ.genus()
-1
Check that this method works over QQbar (:trac:`25351`)::
sage: P.<x,y> = QQbar[] # needs sage.rings.number_field
sage: I = ideal(y^3*z + x^3*y + x*z^3) # needs sage.rings.number_field
sage: I.genus() # needs sage.rings.number_field
sage: # needs sage.rings.number_field
sage: P.<x,y> = QQbar[]
sage: I = ideal(y^3*z + x^3*y + x*z^3)
sage: I.genus()
3
"""
from sage.libs.singular.function_factory import ff
Expand Down
15 changes: 11 additions & 4 deletions src/sage/schemes/curves/affine_curve.py
Original file line number Diff line number Diff line change
Expand Up @@ -2065,13 +2065,20 @@ def _genus(self):
sage: C = Curve(x^5 + y^5 + x*y + 1)
sage: C.genus() # indirect doctest
1
"""
k = self.base_ring()
TESTS::
sage: R.<T> = QQ[]
sage: N.<a> = NumberField(T^2 + 1)
sage: A2.<x,y> = AffineSpace(N, 2)
sage: C = Curve(y^2 - x^3 + x, A2)
sage: C.genus()
1
"""
# Singular's genus command is usually much faster than the genus method
# of function fields in Sage. But unfortunately Singular's genus
# command does not yet work over non-prime finite fields.
if k.is_finite() and k.degree() > 1:
# command does not work over extension fields.
if self.base_ring().degree() > 1:
return self._function_field.genus()

# call Singular's genus command
Expand Down
70 changes: 48 additions & 22 deletions src/sage/schemes/curves/constructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,20 @@
# ********************************************************************

from sage.categories.fields import Fields
from sage.categories.number_fields import NumberFields

from sage.rings.polynomial.multi_polynomial import MPolynomial
from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing
from sage.rings.finite_rings.finite_field_base import FiniteField

from sage.rings.rational_field import QQ

from sage.structure.all import Sequence

from sage.schemes.affine.affine_space import is_AffineSpace
from sage.schemes.generic.ambient_space import is_AmbientSpace
from sage.schemes.generic.algebraic_scheme import is_AlgebraicScheme
from sage.schemes.projective.projective_space import is_ProjectiveSpace

from sage.schemes.affine.affine_space import AffineSpace

from sage.schemes.projective.projective_space import ProjectiveSpace

from sage.schemes.affine.affine_space import AffineSpace, is_AffineSpace
from sage.schemes.projective.projective_space import ProjectiveSpace, is_ProjectiveSpace
from sage.schemes.plane_conics.constructor import Conic

from .projective_curve import (ProjectiveCurve,
ProjectivePlaneCurve,
Expand All @@ -76,8 +72,8 @@
IntegralAffinePlaneCurve,
IntegralAffinePlaneCurve_finite_field)


from sage.schemes.plane_conics.constructor import Conic
_Fields = Fields()
_NumberFields = NumberFields()


def _is_irreducible_and_reduced(F) -> bool:
Expand Down Expand Up @@ -113,11 +109,13 @@ def Curve(F, A=None):
INPUT:
- ``F`` -- a multivariate polynomial, or a list or tuple of polynomials, or an algebraic scheme.
- ``F`` -- a multivariate polynomial, or a list or tuple of polynomials, or an algebraic scheme
- ``A`` -- (default: None) an ambient space in which to create the curve
- ``A`` -- (default: None) an ambient space in which to create the curve.
EXAMPLES:
EXAMPLES: A projective plane curve. ::
A projective plane curve::
sage: x,y,z = QQ['x,y,z'].gens()
sage: C = Curve(x^3 + y^3 + z^3); C
Expand Down Expand Up @@ -215,7 +213,7 @@ def Curve(F, A=None):
sage: Curve(P1)
Projective Line over Finite Field of size 5
::
An affine line::
sage: A1.<x> = AffineSpace(1, QQ)
sage: R = A1.coordinate_ring()
Expand All @@ -224,6 +222,18 @@ def Curve(F, A=None):
sage: Curve(A1)
Affine Line over Rational Field
A projective line::
sage: R.<x> = QQ[]
sage: N.<a> = NumberField(x^2 + 1)
sage: P1.<x,y> = ProjectiveSpace(N, 1)
sage: C = Curve(P1)
sage: C
Projective Line over Number Field in a with defining polynomial x^2 + 1
sage: C.geometric_genus()
0
sage: C.arithmetic_genus()
0
"""
if A is None:
if is_AmbientSpace(F) and F.dimension() == 1:
Expand Down Expand Up @@ -298,12 +308,20 @@ def Curve(F, A=None):
k = A.base_ring()

if is_AffineSpace(A):
if n == 1:
if A.coordinate_ring().ideal(F).is_zero():
if isinstance(k, FiniteField):
return IntegralAffineCurve_finite_field(A, F)
if k in _Fields:
return IntegralAffineCurve(A, F)
return AffineCurve(A, F)
raise TypeError(f"{F} does not define a curve in one-dimensional affine space")
if n != 2:
if isinstance(k, FiniteField):
if A.coordinate_ring().ideal(F).is_prime():
return IntegralAffineCurve_finite_field(A, F)
if k in Fields():
if k == QQ and A.coordinate_ring().ideal(F).is_prime():
if k in _Fields:
if (k == QQ or k in _NumberFields) and A.coordinate_ring().ideal(F).is_prime():
return IntegralAffineCurve(A, F)
return AffineCurve_field(A, F)
return AffineCurve(A, F)
Expand All @@ -316,21 +334,29 @@ def Curve(F, A=None):
if _is_irreducible_and_reduced(F):
return IntegralAffinePlaneCurve_finite_field(A, F)
return AffinePlaneCurve_finite_field(A, F)
if k in Fields():
if k == QQ and _is_irreducible_and_reduced(F):
if k in _Fields:
if (k == QQ or k in _NumberFields) and _is_irreducible_and_reduced(F):
return IntegralAffinePlaneCurve(A, F)
return AffinePlaneCurve_field(A, F)
return AffinePlaneCurve(A, F)

elif is_ProjectiveSpace(A):
if n == 1:
if A.coordinate_ring().ideal(F).is_zero():
if isinstance(k, FiniteField):
return IntegralProjectiveCurve_finite_field(A, F)
if k in _Fields:
return IntegralProjectiveCurve(A, F)
return ProjectiveCurve(A, F)
raise TypeError(f"{F} does not define a curve in one-dimensional projective space")
if n != 2:
if not all(f.is_homogeneous() for f in F):
raise TypeError("polynomials defining a curve in a projective space must be homogeneous")
if isinstance(k, FiniteField):
if A.coordinate_ring().ideal(F).is_prime():
return IntegralProjectiveCurve_finite_field(A, F)
if k in Fields():
if k == QQ and A.coordinate_ring().ideal(F).is_prime():
if k in _Fields:
if (k == QQ or k in _NumberFields) and A.coordinate_ring().ideal(F).is_prime():
return IntegralProjectiveCurve(A, F)
return ProjectiveCurve_field(A, F)
return ProjectiveCurve(A, F)
Expand All @@ -348,8 +374,8 @@ def Curve(F, A=None):
if _is_irreducible_and_reduced(F):
return IntegralProjectivePlaneCurve_finite_field(A, F)
return ProjectivePlaneCurve_finite_field(A, F)
if k in Fields():
if k == QQ and _is_irreducible_and_reduced(F):
if k in _Fields:
if (k == QQ or k in _NumberFields) and _is_irreducible_and_reduced(F):
return IntegralProjectivePlaneCurve(A, F)
return ProjectivePlaneCurve_field(A, F)
return ProjectivePlaneCurve(A, F)
Expand Down
26 changes: 14 additions & 12 deletions src/sage/schemes/curves/curve.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,17 +209,9 @@ 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()
Expand All @@ -233,7 +225,7 @@ def geometric_genus(self):
sage: C.geometric_genus()
3
Examples of affine curves. ::
Examples of affine curves::
sage: x, y = PolynomialRing(GF(5), 2, 'xy').gens()
sage: C = Curve(y^2 - x^3 - 17*x + y)
Expand All @@ -246,12 +238,22 @@ def geometric_genus(self):
sage: C.geometric_genus()
3
Note that the geometric genus is only defined for `geometrically
irreducible curve <https://stacks.math.columbia.edu/tag/0BYE>`_. This
method does not check the condition. Be warned that you may get a
nonsensical result if the curve is not geometrically irreducible.
A curve that 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
"""
try:
return self._genus
except AttributeError:
self._genus = self.defining_ideal().genus()
return self._genus
raise NotImplementedError

def union(self, other):
"""
Expand Down
Loading

0 comments on commit 2ccffbf

Please sign in to comment.