Skip to content

Commit

Permalink
gh-35467: Attach Jacobians to function fields and curves
Browse files Browse the repository at this point in the history
    
<!-- Please provide a concise, informative and self-explanatory title.
-->
<!-- Don't put issue numbers in the title. Put it in the Description
below. -->
<!-- For example, instead of "Fixes #12345", use "Add a new method to
multiply two integers" -->

### 📚 Description

We attach Jacobians to function fields and curves, enabling arithmetic
with the points of the Jacobian. Fixes #34232.

A point of Jacobian is represented by an effective divisor `D` such that
the point is the divisor class of `D - B` (of degree 0) with a fixed
base divisor `B`.

There are two models for Jacobian arithmetic:

- Hess model:  `D` is internally represented by a pair of certain ideals
and arithmetic relies on divisor reduction using Riemann-Roch space
computation by Hess' algorithm.
- Khuri-Makdisi model: `D` is internally represented by a linear
subspace `W_D` of a linear space `V` and arithmetic uses Khuri-Makdisi's
linear algebra algorithms. For implementation, #15113 was referenced.


An example with non-hyperelliptic genus 3 curve:
```sage
sage: A2.<x,y> = AffineSpace(QQ, 2)
sage: f = y^3 + x^4 - 5*x^2*y + 2*x*y - x^2 - 5*y - 4*x + 1
sage: C = Curve(f, A2)
sage: X = C.projective_closure()
sage: X.genus()
3
sage: X.rational_points(bound=5)
[(0 : 0 : 1), (1/3 : 1/3 : 1)]
sage: Q = X(0,0,1).place()
sage: P = X(1,1,3).place()
sage: D = P - Q
sage: D.degree()
0
sage: J = X.jacobian(model='hess', base_div=3*Q)
sage: G = J.group()
sage: p = G.point(D)
sage: 2*p + 3*p == 5*p
True
```

An example with elliptic curve:
```sage
sage: k.<a> = GF((5,2))
sage: E = EllipticCurve(k,[1,0]); E
Elliptic Curve defined by y^2 = x^3 + x over Finite Field in a of size
5^2
sage: E.order()
32
sage: P = E([a, 2*a + 4])
sage: P
(a : 2*a + 4 : 1)
sage: P.order()
8
sage: p = P.point_of_jacobian_of_curve()
sage: p
[Place (x + 4*a, y + 3*a + 1)]
sage: p.order()
8
sage: Q = 3*P
sage: q = Q.point_of_jacobian_of_curve()
sage: q == 3*p
True
sage: G = p.parent()
sage: G.order()
32
sage: G
Group of rational points of Jacobian over Finite Field in a of size 5^2
(Hess model)
sage: J = G.parent(); J
Jacobian of Projective Plane Curve over Finite Field in a of size 5^2
 defined by x^2*y + y^3 - x*z^2 (Hess model)
sage: J.curve() == E.affine_patch(2).projective_closure()
True
```

An example with hyperelliptic curve:
```sage
sage: R.<x> = PolynomialRing(GF(11))
sage: f = x^6 + x + 1
sage: H = HyperellipticCurve(f)
sage: J = H.jacobian()
sage: D = J(H.lift_x(1))
sage: D  # divisor in Mumford representation
(x + 10, y + 6)
sage: jacobian_order = sum(H.frobenius_polynomial())
sage: jacobian_order
234
sage: p = D.point_of_jacobian_of_curve(); p
sage: p  # Jacobian point represented by an effective divisor
[Place (1/x0, 1/x0^3*x1 + 1)
 + Place (x0 + 10, x1 + 6)]
sage: p.order()
39
sage: 234*p == 0
True
sage: G = p.parent()
sage: G
Group of rational points of Jacobian over Finite Field of size 11 (Hess
model)
sage: J = G.parent()
sage: J
Jacobian of Projective Plane Curve over Finite Field of size 11
 defined by x0^6 + x0^5*x1 + x1^6 - x0^4*x2^2 (Hess model)
sage: C = J.curve()
sage: C
Projective Plane Curve over Finite Field of size 11
 defined by x0^6 + x0^5*x1 + x1^6 - x0^4*x2^2
sage: C.affine_patch(0) == H.affine_patch(2)
True
```

[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2
/gh/kwankyu/sage/p/35467/add-jacobian-groups-notebook-binder) prepared
with #36245

<!-- Describe your changes here in detail. -->
<!-- Why is this change required? What problem does it solve? -->
<!-- If this PR resolves an open issue, please link to it here. For
example "Fixes #12345". -->
<!-- If your change requires a documentation PR, please link it
appropriately. -->

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. It should be `[x]` not `[x
]`. -->

- [x] The title is concise, informative, and self-explanatory.
- [x] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.
- [x] I have created tests covering the changes.
- [x] I have updated the documentation accordingly.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on
- #12345: short description why this is a dependency
- #34567: ...
-->

<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
    
URL: #35467
Reported by: Kwankyu Lee
Reviewer(s): Kwankyu Lee, Matthias Köppe
  • Loading branch information
Release Manager committed Apr 24, 2024
2 parents 54cd43c + d662b20 commit fa7cb94
Show file tree
Hide file tree
Showing 18 changed files with 4,284 additions and 102 deletions.
24 changes: 18 additions & 6 deletions src/doc/en/reference/curves/index.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
Plane and Space Curves
======================

Sage enables computations with curves in affine and projective ambient spaces,
curves over `\CC` as Riemann surfaces, and Jacobians of projective curves.

Curves
======
------

.. toctree::
:maxdepth: 1
Expand All @@ -12,10 +18,8 @@ Curves
sage/schemes/curves/closed_point
sage/schemes/curves/zariski_vankampen

sage/schemes/jacobians/abstract_jacobian

Plane conics
============
------------

.. toctree::
:maxdepth: 1
Expand All @@ -28,7 +32,7 @@ Plane conics
sage/schemes/plane_conics/con_rational_function_field

Plane quartics
=========================
--------------

.. toctree::
:maxdepth: 1
Expand All @@ -37,11 +41,19 @@ Plane quartics
sage/schemes/plane_quartics/quartic_generic

Riemann surfaces
================
----------------

.. toctree::
:maxdepth: 1

sage/schemes/riemann_surfaces/riemann_surface

Jacobians
---------

.. toctree::
:maxdepth: 1

sage/schemes/jacobians/abstract_jacobian

.. include:: ../footer.txt
13 changes: 13 additions & 0 deletions src/doc/en/reference/function_fields/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ algebraic closure of `\QQ`.

A basic reference for the theory of algebraic function fields is [Stich2009]_.

Jacobians of function fields
----------------------------

Arithmetic in Jacobians of function fields are available in two flavors.

.. toctree::
:maxdepth: 1

sage/rings/function_field/jacobian_base
sage/rings/function_field/jacobian_hess
sage/rings/function_field/jacobian_khuri_makdisi
sage/rings/function_field/khuri_makdisi

A Support Module
----------------

Expand Down
6 changes: 6 additions & 0 deletions src/doc/en/reference/references/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3181,6 +3181,9 @@ REFERENCES:
Cryptanalysis* ; 2002' available at
http://www.engr.mun.ca/~howard/PAPERS/ldc_tutorial.pdf
.. [Hes2004] Florian Hess, "Computing relations in divisor class groups of
algebraic curves over finite fields," Preprint, 2004.
.. [Hes2002] Florian Hess, "Computing Riemann-Roch spaces in algebraic
function fields and related topics," J. Symbolic
Comput. 33 (2002), no. 4, 425--445.
Expand Down Expand Up @@ -3776,6 +3779,9 @@ REFERENCES:
block cipher*, Lightweight Cryptography Workshop, 2016.
https://www.nist.gov/sites/default/files/documents/2016/10/18/karpman-paper-lwc2016.pdf
.. [Khu2004] \K. Khuri-Makdisi. *Linear algebra algorithms for divisors on an algebraic curve*,
Mathematics of Computation 73, no. 245 (2004) pp. 333-357.
.. [Kin1992] Nancy G. Kinnersley, *The vertex separation number of a graph
equals its path-width*, Information Processing Letters
42(6):345-350, 1992. :doi:`10.1016/0020-0190(92)90234-M`.
Expand Down
2 changes: 1 addition & 1 deletion src/sage/categories/all.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@

# schemes and varieties
from sage.categories.modular_abelian_varieties import ModularAbelianVarieties
from sage.categories.schemes import Schemes, AbelianVarieties
from sage.categories.schemes import Schemes, AbelianVarieties, Jacobians

# * with basis
from sage.categories.modules_with_basis import ModulesWithBasis
Expand Down
1 change: 1 addition & 0 deletions src/sage/categories/category.py
Original file line number Diff line number Diff line change
Expand Up @@ -2597,6 +2597,7 @@ def category_sample():
Category of Hecke modules over Rational Field,
Category of Hopf algebras over Rational Field,
Category of Hopf algebras with basis over Rational Field,
Category of Jacobians over Rational Field,
Category of Lie algebras over Rational Field,
Category of Weyl groups,
Category of abelian varieties over Rational Field,
Expand Down
129 changes: 112 additions & 17 deletions src/sage/categories/schemes.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
r"""
Schemes
"""

# ****************************************************************************
# Copyright (C) 2005 David Kohel <kohel@maths.usyd.edu>
# Copyright (C) 2005 David Kohel <kohel@maths.usyd.edu>
# William Stein <wstein@math.ucsd.edu>
# 2008-2012 Nicolas M. Thiery <nthiery at users.sf.net>
# 2008-2012 Nicolas M. Thiery <nthiery@users.sf.net>
#
# Distributed under the terms of the GNU General Public License (GPL)
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
# https://www.gnu.org/licenses/
# *****************************************************************************
# ****************************************************************************

from sage.categories.category import Category
from sage.categories.category_types import Category_over_base
Expand All @@ -18,6 +22,7 @@
from sage.categories.rings import Rings
from sage.categories.fields import Fields
from sage.categories.homsets import HomsetsCategory
from sage.misc.abstract_method import abstract_method


class Schemes(Category):
Expand Down Expand Up @@ -55,7 +60,6 @@ class Schemes(Category):
sage: Schemes().Homsets().super_categories()
[Category of homsets]
"""

@staticmethod
def __classcall_private__(cls, X=None):
"""
Expand All @@ -73,8 +77,7 @@ def __classcall_private__(cls, X=None):
Category of schemes over Integer Ring
"""
if X is not None:
from sage.schemes.generic.scheme import is_Scheme
if not is_Scheme(X):
if X not in Schemes():
X = Schemes()(X)
return Schemes_over_base(X)
return super().__classcall__(cls)
Expand Down Expand Up @@ -155,9 +158,6 @@ def _call_(self, x):
raise TypeError("No way to create an object or morphism in %s from %s" % (self, x))


#############################################################
# Schemes over a given base scheme.
#############################################################
class Schemes_over_base(Category_over_base):
"""
The category of schemes over a given base scheme.
Expand All @@ -172,7 +172,6 @@ class Schemes_over_base(Category_over_base):
sage: C = Schemes(ZZ)
sage: TestSuite(C).run()
"""

def base_scheme(self):
"""
EXAMPLES::
Expand All @@ -198,12 +197,12 @@ def _repr_object_names(self):
sage: Schemes(Spec(ZZ)) # indirect doctest
Category of schemes over Integer Ring
"""
# To work around the name of the class (schemes_over_base)
from sage.schemes.generic.scheme import is_AffineScheme
if is_AffineScheme(self.base_scheme()):
return "schemes over %s" % self.base_scheme().coordinate_ring()
else:
return "schemes over %s" % self.base_scheme()
base = self.base()
if is_AffineScheme(base):
base = base.coordinate_ring()
return f"schemes over {base}"


class AbelianVarieties(Schemes_over_base):
r"""
Expand Down Expand Up @@ -236,6 +235,18 @@ def __init__(self, base):
raise ValueError('category of abelian varieties is only defined over fields')
super().__init__(base)

def base_scheme(self):
"""
EXAMPLES::
sage: Schemes(Spec(ZZ)).base_scheme()
Spectrum of Integer Ring
"""
base = self.base()
if base not in Schemes():
base = Schemes()(base)
return base

def super_categories(self):
"""
EXAMPLES::
Expand All @@ -253,7 +264,7 @@ def _repr_object_names(self):
sage: AbelianVarieties(Spec(QQ)) # indirect doctest
Category of abelian varieties over Rational Field
"""
return "abelian varieties over %s" % self.base_scheme()
return "abelian varieties over %s" % self.base()

class Homsets(HomsetsCategory):
r"""
Expand Down Expand Up @@ -294,3 +305,87 @@ def extra_super_categories(self):
True
"""
return [Rings()]


class Jacobians(Schemes_over_base):
"""
The category of Jacobians attached to curves or function fields.
EXAMPLES::
sage: Jacobians(QQ)
Category of Jacobians over Rational Field
TESTS::
sage: TestSuite(Jacobians(QQ)).run()
"""
def __init__(self, base):
r"""
Constructor of this category.
EXAMPLES::
sage: Jacobians(QQ)
Category of Jacobians over Rational Field
sage: Jacobians(Spec(QQ))
Category of Jacobians over Rational Field
"""
from sage.schemes.generic.scheme import is_AffineScheme
if is_AffineScheme(base):
base = base.coordinate_ring()
if base not in Fields():
raise ValueError('category of Jacobians is only defined over fields')
super().__init__(base)

def base_scheme(self):
"""
Return the base scheme of this Jacobians category.
EXAMPLES::
sage: Jacobians(QQ).base_scheme()
Spectrum of Rational Field
"""
base = self.base()
if base not in Schemes():
base = Schemes()(base)
return base

def super_categories(self):
"""
Return the super categories of this Jacobians category.
EXAMPLES::
sage: Jacobians(QQ).super_categories()
[Category of abelian varieties over Rational Field]
"""
return [AbelianVarieties(self.base_scheme())]

def _repr_object_names(self):
"""
Return the string representation of this category.
EXAMPLES::
sage: Jacobians(Spec(QQ)) # indirect doctest
Category of Jacobians over Rational Field
"""
return "Jacobians over %s" % self.base()

class ParentMethods:

@abstract_method
def base_curve(self):
"""
Return the curve to which this Jacobian is attached.
EXAMPLES::
sage: # needs sage.rings.function_field
sage: K.<x> = FunctionField(GF(2))
sage: J = K.jacobian()
sage: J.base_curve()
Rational function field in x over Finite Field of size 2
"""
Original file line number Diff line number Diff line change
Expand Up @@ -2066,7 +2066,7 @@ def scalar_multiplication(self, x):
sage: phi = DrinfeldModule(A, [z, 0, 1, z])
sage: phi
Drinfeld module defined by T |--> z*t^3 + t^2 + z
sage: phi.hom(T)
sage: phi.hom(T) # indirect doctest
Endomorphism of Drinfeld module defined by T |--> z*t^3 + t^2 + z
Defn: z*t^3 + t^2 + z
Expand Down
Loading

0 comments on commit fa7cb94

Please sign in to comment.