Skip to content

Commit 74db9ee

Browse files
author
Release Manager
committed
sagemathgh-39161: Add hyperelliptic curves using the smooth model ## Overview This PR includes a whole new module into schemes which implements hyperelliptic curves over the smooth model, and focuses on implementing decent arithmetic for Jac(H) for all reasonable cases, something which is not done properly in the current implementation due to limitations of the curve model used. The idea is that `hyperelliptic_curves_sm` will be available with the old model for some time, until someone decides we should depreciate the old model in favour of this new implementation. ## Motivation The current implementation of hyperelliptic curves in SageMath uses the projective plane model. Although this works nicely enough for imaginary curves with only one point at infinity, it is not descriptive enough for the real models. My gut feeling is the projective plane model was used as in early Sage days this was easier to do and allowed hyperelliptic curves to be supported at all. Mathematically, I believe it makes much more sense to use a weighted projective model to have this new description but it requires more tools which we only have thanks to the work of others in sage since it was released. This PR is a total rewrite of the hyperelliptic curve classes to instead use the smooth model for hyperelliptic curves which facilitates implementing arithmetic of Jacobians of hyperelliptic curves for (almost) all cases. In particular, now if one tries to perform arithmetic on Jac(C) one either gets the correct value or a well-handled error instead of just returning something which is wrong. The hope is that with this new model for the curves, more recent research in the area of hyperelliptic curves and their jacobians can be more easily integrated. As a personal example, being able to compute arithmetic in Jac(H) for the real model unconditionally would help with the implementation of genus two isogenies which are "in vogue" right now in the cryptography world. ### Content of PR This PR looks WAY bigger than it is, as it duplicates ALL code from `hyperelliptic_curves` and then has modifications to allow this to work in the new curve model. I believe the best thing to do in the long run is to depreciate the old hyperelliptic curve impl and have this replace it, but this will take years(?) so I think we'll just have to have both side by side for a while. This PR still needs a lot of work including: - more tests - better comments and docstrings - potentially refactoring of which files belong where but the code has sat at this stage for a long time without much more progress from the three of us, so I think the best thing to do is open up the PR and try and get some extra attention on getting this code ready to be included. One benefit is that all this code is "new" in that it should not conflict with anyone else's work, so we can get this code into a good position and keep adding to it with more interesting maths once the base layer is in place ### Example of better arithmetic For example, this code fixed the following issue: sagemath#32024 ```py sage: R.<x> = QQ[] sage: f = 144*x^6 - 240*x^5 + 148*x^4 + 16*x^3 - 16*x^2 - 4*x + 1 sage: H = HyperellipticCurveSmoothModel(f) sage: J = Jacobian(H) sage: P = J(H(0,1))-J(H(0,-1)) sage: (5*P).is_zero() False sage: sage: H = HyperellipticCurve(f) sage: J = Jacobian(H) sage: P = J(H(0,1))-J(H(0,-1)) sage: (5*P).is_zero() True ``` and is also related to the issues sagemath#37109 sagemath#37093 sagemath#37101 sagemath#37626 ### Help! This code needs more work, and lots of time spent on the review which I don't think is a reasonable thing to do for one person. So if this area interests you any help would be appreciated (either in the review of some of the code or some extra commits which tidy up aspects) URL: sagemath#39161 Reported by: Giacomo Pope Reviewer(s): Frédéric Chapoton, Giacomo Pope, grhkm21, sabrinakunzweiler, Vincent Macri
2 parents 31a24ce + 130cbd2 commit 74db9ee

38 files changed

Lines changed: 7248 additions & 4102 deletions

src/doc/en/reference/arithmetic_curves/index.rst

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,22 +110,33 @@ Hyperelliptic curves
110110
sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field
111111
sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field
112112
sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field
113+
sage/schemes/hyperelliptic_curves/hyperelliptic_g2
113114

115+
sage/schemes/hyperelliptic_curves/invariants
114116
sage/schemes/hyperelliptic_curves/mestre
115-
116117
sage/schemes/hyperelliptic_curves/monsky_washnitzer
117118
sage/schemes/hyperelliptic_curves/hypellfrob
118119

120+
sage/interfaces/genus2reduction
121+
122+
Jacobians of hyperelliptic curves
123+
------------------------------------------------
124+
125+
.. toctree::
126+
:maxdepth: 1
127+
119128
sage/schemes/hyperelliptic_curves/jacobian_generic
120-
sage/schemes/hyperelliptic_curves/jacobian_g2
121-
sage/schemes/hyperelliptic_curves/jacobian_homset
122-
sage/schemes/hyperelliptic_curves/jacobian_morphism
123-
sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils
129+
sage/schemes/hyperelliptic_curves/jacobian_homset_generic
130+
sage/schemes/hyperelliptic_curves/jacobian_homset_ramified
131+
sage/schemes/hyperelliptic_curves/jacobian_homset_split
132+
sage/schemes/hyperelliptic_curves/jacobian_homset_inert
124133

125-
sage/schemes/hyperelliptic_curves/hyperelliptic_g2
126-
sage/schemes/hyperelliptic_curves/invariants
127-
sage/schemes/hyperelliptic_curves/kummer_surface
134+
sage/schemes/hyperelliptic_curves/jacobian_g2_generic
135+
sage/schemes/hyperelliptic_curves/jacobian_g2_homset_ramified
136+
sage/schemes/hyperelliptic_curves/jacobian_g2_homset_split
137+
sage/schemes/hyperelliptic_curves/jacobian_g2_homset_inert
138+
139+
sage/schemes/hyperelliptic_curves/jacobian_morphism
128140

129-
sage/interfaces/genus2reduction
130141

131142
.. include:: ../footer.txt

src/doc/en/reference/references/index.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2984,6 +2984,10 @@ REFERENCES:
29842984
50(2):259-273, 1995.
29852985
:doi:`10.1006/jcss.1995.1022`
29862986
2987+
.. [Gal2018] Steven D Galbraith. *Mathematics of Public Key Cryptography*.
2988+
Version 2.0, October 31, 2018.
2989+
https://www.math.auckland.ac.nz/~sgal018/crypto-book/main.pdf
2990+
29872991
.. [Gallai] \T. Gallai, *Elementare Relationen bezueglich der
29882992
Glieder und trennenden Punkte von Graphen*, Magyar
29892993
Tud. Akad. Mat. Kutato Int. Kozl. 9 (1964) 235-236
@@ -3071,6 +3075,10 @@ REFERENCES:
30713075
.. [GHJV1994] \E. Gamma, R. Helm, R. Johnson, J. Vlissides, *Design
30723076
Patterns: Elements of Reusable Object-Oriented
30733077
Software*. Addison-Wesley (1994). ISBN 0-201-63361-2.
3078+
3079+
.. [GHM2008] \S. Galbraith, M. Harrison, D. Mireles Morales,
3080+
*Efficient hyperelliptic arithmetic using balanced representation for divisors*,
3081+
Algorithmic Number Theory: 8th International Symposium, ANTS-VIII Banff, Canada, May 17-22, 2008 Proceedings 8.
30743082
30753083
.. [Gil1959] Edgar Nelson Gilbert. *Random Graphs*, Annals of Mathematical
30763084
Statistics. 30 (4): 1141-1144, 1959.
@@ -5245,6 +5253,10 @@ REFERENCES:
52455253
LexDFS, LexUP and LexDown orderings*. (2017)
52465254
:arxiv:`1701.00305`
52475255
5256+
.. [Mireles2008] David J. Mireles Morales, *Efficient Arithmetic on Hyperelliptic Curves With Real Representation*,
5257+
PhD thesis, University of London, UK, 2008.
5258+
https://www.math.auckland.ac.nz/~sgal018/Dave-Mireles-Full.pdf
5259+
52485260
.. [MirMor2009] \R. Miranda, D.R. Morrison, "Embeddings of Integral Quadratic Forms"
52495261
http://www.math.ucsb.edu/~drm/manuscripts/eiqf.pdf .
52505262
@@ -5460,6 +5472,9 @@ REFERENCES:
54605472
Number Theory" (ed. Y. Motohashi), London Math. Soc. Lecture Notes
54615473
247 (1997), 313-320, Cambridge Univ. Press.
54625474
5475+
.. [Mue2010] Jan Steffen Mueller, *Explicit Kummer surface formulas for arbitrary characteristic*.
5476+
LMS Journal of Computation and Mathematics, Volume 13, 47--64, 2010.
5477+
54635478
.. [Mul2004] Siguna Muller, *On the Computation of Square Roots in
54645479
Finite Fields*, in Designs, Codes and Cryptography,
54655480
Volume 31, Issue 3 (March 2004)

src/sage/schemes/all.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,5 @@
4747
from sage.schemes.cyclic_covers.all import *
4848

4949
from sage.schemes.berkovich.all import *
50+
51+
from sage.schemes.weighted_projective.all import *

src/sage/schemes/curves/projective_curve.py

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -807,19 +807,6 @@ def plot(self, *args, **kwds):
807807
Graphics object consisting of 1 graphics primitive
808808
sage: C.plot(patch=1)
809809
Graphics object consisting of 1 graphics primitive
810-
811-
A hyperelliptic curve::
812-
813-
sage: # needs sage.plot
814-
sage: P.<x> = QQ[]
815-
sage: f = 4*x^5 - 30*x^3 + 45*x - 22
816-
sage: C = HyperellipticCurve(f)
817-
sage: C.plot()
818-
Graphics object consisting of 1 graphics primitive
819-
sage: C.plot(patch=0)
820-
Graphics object consisting of 1 graphics primitive
821-
sage: C.plot(patch=1)
822-
Graphics object consisting of 1 graphics primitive
823810
"""
824811
# if user has not specified a favorite affine patch, take the
825812
# one avoiding "infinity", i.e. the one corresponding to the
@@ -2391,9 +2378,11 @@ def random_element(self):
23912378
23922379
Sampling from points on a hyperelliptic curve::
23932380
2394-
sage: R.<x,y> = GF(13)[]
2395-
sage: C = HyperellipticCurve(y^2 + 3*x^2*y - (x^5 + x + 1))
2396-
sage: P = C.random_element(); P # random
2381+
sage: R.<x> = GF(13)[]
2382+
sage: f = x^5 + x + 1
2383+
sage: h = 3*x^2
2384+
sage: C = HyperellipticCurve(f, h)
2385+
sage: P = C.random_point(); P # random
23972386
(0 : 1 : 0)
23982387
sage: P in C
23992388
True

src/sage/schemes/curves/weighted_projective_curve.py

Lines changed: 106 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,12 @@
3434
# ****************************************************************************
3535

3636
from sage.schemes.curves.curve import Curve_generic
37-
from sage.schemes.weighted_projective.weighted_projective_space import WeightedProjectiveSpace_ring
37+
from sage.schemes.projective.projective_subscheme import (
38+
AlgebraicScheme_subscheme_projective,
39+
)
40+
from sage.schemes.weighted_projective.weighted_projective_space import (
41+
WeightedProjectiveSpace_ring,
42+
)
3843

3944

4045
class WeightedProjectiveCurve(Curve_generic):
@@ -49,6 +54,7 @@ class WeightedProjectiveCurve(Curve_generic):
4954
sage: C = Curve(y^2 - x^5 * z - 3 * x^2 * z^4 - 2 * z^6, WP); C
5055
Weighted Projective Curve over Rational Field defined by y^2 - x^5*z - 3*x^2*z^4 - 2*z^6
5156
"""
57+
5258
def __init__(self, A, X, *kwargs):
5359
if not isinstance(A, WeightedProjectiveSpace_ring):
5460
raise TypeError(f"A(={A}) is not a weighted projective space")
@@ -94,12 +100,108 @@ def projective_curve(self):
94100
from sage.schemes.projective.projective_space import ProjectiveSpace
95101

96102
WP = self.ambient_space()
97-
PP = ProjectiveSpace(WP.dimension_relative(), WP.base_ring(), WP.variable_names())
103+
PP = ProjectiveSpace(
104+
WP.dimension_relative(), WP.base_ring(), WP.variable_names()
105+
)
98106
PP_ring = PP.coordinate_ring()
99-
subs_dict = {name: var**weight for (name, var), weight in
100-
zip(WP.gens_dict().items(), WP.weights())}
107+
subs_dict = {
108+
name: var**weight
109+
for (name, var), weight in zip(WP.gens_dict().items(), WP.weights())
110+
}
101111

102112
wp_polys = self.defining_polynomials()
103113
pp_polys = [PP_ring(poly.subs(**subs_dict)) for poly in wp_polys]
104114

105115
return PP.curve(pp_polys)
116+
117+
def affine_patch(self, i, AA=None):
118+
r"""
119+
Return the `i`-th affine patch of this projective curve.
120+
121+
INPUT:
122+
123+
- ``i`` -- affine coordinate chart of the projective ambient space of
124+
this curve to compute affine patch with respect to
125+
126+
- ``AA`` -- (default: ``None``) ambient affine space, this is constructed
127+
if it is not given
128+
129+
.. TODO:
130+
131+
Implement this directly for weighted projective space, this code currently
132+
just computes the related projective model and continues the computation from
133+
there.
134+
135+
OUTPUT: a curve in affine space
136+
137+
EXAMPLES::
138+
139+
sage: WP.<x,y,z> = WeightedProjectiveSpace([1, 1, 1], QQ)
140+
sage: C = WP.curve(x^3 - x^2*y + y^3 - x^2*z)
141+
sage: C.affine_patch(1)
142+
Affine Plane Curve over Rational Field defined by x^3 - x^2*z - x^2 + 1
143+
"""
144+
from .constructor import Curve
145+
146+
projective_curve = self.projective_curve()
147+
return Curve(
148+
AlgebraicScheme_subscheme_projective.affine_patch(projective_curve, i, AA)
149+
)
150+
151+
def riemann_surface(self, **kwargs):
152+
r"""
153+
Return the complex Riemann surface determined by this curve.
154+
155+
.. TODO:
156+
157+
Implement this directly for weighted projective space, this code currently
158+
just computes the related projective model and continues the computation from
159+
there.
160+
161+
OUTPUT: a :class:`~sage.schemes.riemann_surfaces.riemann_surface.RiemannSurface` object
162+
163+
EXAMPLES::
164+
165+
sage: WP.<x,y,z> = WeightedProjectiveSpace([1, 1, 1], QQ)
166+
sage: C = WP.curve(x^3 + 3*y^3 + 5*z^3)
167+
sage: C.riemann_surface()
168+
Riemann surface defined by polynomial f = x^3 + 3*y^3 + 5 = 0,
169+
with 53 bits of precision
170+
"""
171+
return self.affine_patch(2).riemann_surface(**kwargs)
172+
173+
def plot(self, *args, **kwds):
174+
"""
175+
Plot the real points of an affine patch of the associated projective
176+
plane curve.
177+
178+
INPUT:
179+
180+
- ``self`` -- an affine plane curve
181+
182+
- ``patch`` -- (optional) the affine patch to be plotted; if not
183+
specified, the patch corresponding to the last projective
184+
coordinate being nonzero
185+
186+
- ``*args`` -- (optional) tuples (variable, minimum, maximum) for
187+
plotting dimensions
188+
189+
- ``**kwds`` -- optional keyword arguments passed on to ``implicit_plot``
190+
191+
EXAMPLES:
192+
193+
A hyperelliptic curve::
194+
195+
sage: # needs sage.plot
196+
sage: P.<x> = QQ[]
197+
sage: f = 4*x^5 - 30*x^3 + 45*x - 22
198+
sage: C = HyperellipticCurve(f)
199+
sage: C.plot()
200+
Graphics object consisting of 1 graphics primitive
201+
sage: C.plot(patch=0)
202+
Graphics object consisting of 1 graphics primitive
203+
sage: C.plot(patch=1)
204+
Graphics object consisting of 1 graphics primitive
205+
"""
206+
projective_curve = self.projective_curve()
207+
return projective_curve.plot(*args, **kwds)

0 commit comments

Comments
 (0)