diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 09b78514e1c..8921374bcea 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -4049,6 +4049,10 @@ REFERENCES: 293-311 (1987). :doi:`10.1007/BF00337892` +.. [Kudo2017] Momonari Kudo, "Analysis of an algorithm to compute the cohomology + groups of coherent sheaves and its applications", Japan Journal of + Industrial and Applied Mathematics 34 (2017), 1--40. + .. [Kuh1987] \W. Kühnel, "Minimal triangulations of Kummer varieties", Abh. Math. Sem. Univ. Hamburg 57 (1987), 7-20. diff --git a/src/doc/en/reference/schemes/index.rst b/src/doc/en/reference/schemes/index.rst index ef2f2595104..15d96706ed2 100644 --- a/src/doc/en/reference/schemes/index.rst +++ b/src/doc/en/reference/schemes/index.rst @@ -46,6 +46,15 @@ Projective Schemes sage/schemes/projective/projective_rational_point sage/schemes/projective/projective_homset +Coherent Sheaves +---------------- + +.. toctree:: + :maxdepth: 1 + + sage/schemes/sheaves/sheaf + sage/schemes/sheaves/cohomology + Products of Projective Spaces ----------------------------- @@ -61,6 +70,7 @@ Products of Projective Spaces Toric Varieties --------------- + .. toctree:: :maxdepth: 1 @@ -85,6 +95,7 @@ Toric Varieties Cyclic Covers --------------- + .. toctree:: :maxdepth: 1 @@ -95,6 +106,7 @@ Cyclic Covers Berkovich Analytic Space ------------------------ + .. toctree:: :maxdepth: 1 diff --git a/src/sage/misc/latex.py b/src/sage/misc/latex.py index f409dacbddc..faa6300b556 100644 --- a/src/sage/misc/latex.py +++ b/src/sage/misc/latex.py @@ -583,6 +583,10 @@ def latex_extra_preamble(): \newcommand{\PSL}{\mathrm{PSL}} \newcommand{\lcm}{\mathop{\operatorname{lcm}}} \newcommand{\dist}{\mathrm{dist}} + \newcommand{\im}{\mathop{\operatorname{im}}} + \newcommand{\rank}{\mathop{\operatorname{rank}}} + \newcommand{\PP}{\mathbf{P}} + \newcommand{\OO}{\mathcal{O}} \newcommand{\Bold}[1]{\mathbf{#1}} """ diff --git a/src/sage/misc/latex_macros.py b/src/sage/misc/latex_macros.py index 93fb11fbf48..1b17c71ef41 100644 --- a/src/sage/misc/latex_macros.py +++ b/src/sage/misc/latex_macros.py @@ -175,7 +175,12 @@ def convert_latex_macro_to_mathjax(macro): latex_macros = [r"\newcommand{\SL}{\mathrm{SL}}", r"\newcommand{\PSL}{\mathrm{PSL}}", r"\newcommand{\lcm}{\mathop{\operatorname{lcm}}}", - r"\newcommand{\dist}{\mathrm{dist}}"] + r"\newcommand{\dist}{\mathrm{dist}}", + r"\newcommand{\im}{\mathop{\operatorname{im}}}", + r"\newcommand{\rank}{\mathop{\operatorname{rank}}}", + r"\newcommand{\PP}{\mathbf{P}}", + r"\newcommand{\OO}{\mathcal{O}}", + ] # The following is to allow customization of typesetting of rings: # mathbf vs mathbb. See latex.py for more information. diff --git a/src/sage/schemes/affine/affine_point.py b/src/sage/schemes/affine/affine_point.py index dabcaa134f9..3fd64593c35 100644 --- a/src/sage/schemes/affine/affine_point.py +++ b/src/sage/schemes/affine/affine_point.py @@ -1,27 +1,19 @@ r""" Points on affine varieties -Scheme morphism for points on affine varieties. - +This module implements scheme morphism for points on affine varieties. AUTHORS: -- David Kohel, William Stein - -- Volker Braun (2011-08-08): Renamed classes, more documentation, misc - cleanups. - -- Ben Hutz (2013) +- David Kohel, William Stein (2006): initial version +- Volker Braun (2011-08-08): renamed classes, more documentation, misc cleanups +- Ben Hutz (2013): many improvements """ -# Historical note: in trac #11599, V.B. renamed -# * _point_morphism_class -> _morphism -# * _homset_class -> _point_homset - # **************************************************************************** -# Copyright (C) 2011 Volker Braun # Copyright (C) 2006 David Kohel # Copyright (C) 2006 William Stein +# Copyright (C) 2011 Volker Braun # # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of @@ -34,13 +26,11 @@ from sage.schemes.generic.morphism import SchemeMorphism_point, SchemeMorphism, is_SchemeMorphism from sage.structure.sequence import Sequence -_NumberFields = NumberFields() - -############################################################################ -# Rational points on schemes, which we view as morphisms determined -# by coordinates. -############################################################################ +# -------------------------------------------------------------------- +# Rational points on schemes, which we view as morphisms determined by +# coordinates. +# -------------------------------------------------------------------- class SchemeMorphism_point_affine(SchemeMorphism_point): """ @@ -211,7 +201,7 @@ def global_height(self, prec=None): R = RealField(prec) H = max([self[i].abs() for i in range(self.codomain().ambient_space().dimension_relative())]) return R(max(H,1)).log() - if self.domain().base_ring() in _NumberFields or isinstance(self.domain().base_ring(), sage.rings.abc.Order): + if self.domain().base_ring() in NumberFields() or isinstance(self.domain().base_ring(), sage.rings.abc.Order): return max([self[i].global_height(prec) for i in range(self.codomain().ambient_space().dimension_relative())]) else: raise NotImplementedError("must be over a number field or a number field Order") @@ -410,6 +400,29 @@ def multiplicity(self): raise TypeError("this point must be a point on an affine subscheme") return self.codomain().multiplicity(self) + def as_subscheme(self): + r""" + Return the subscheme associated with this rational point. + + EXAMPLES:: + + sage: A2. = AffineSpace(QQ, 2) + sage: p1 = A2.point([0,0]).as_subscheme(); p1 + Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: + x, y + sage: p2 = A2.point([1,1]).as_subscheme(); p2 + Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: + x - 1, y - 1 + sage: p1 + p2 + Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: + x - y, y^2 - y + """ + A = self.codomain().ambient_space() + g = A.gens() + v = self._coords + n = len(v) + return A.subscheme([g[i] - v[i] for i in range(n)]) + class SchemeMorphism_point_affine_finite_field(SchemeMorphism_point_affine_field): diff --git a/src/sage/schemes/affine/affine_space.py b/src/sage/schemes/affine/affine_space.py index fdf38862068..a65276fad23 100644 --- a/src/sage/schemes/affine/affine_space.py +++ b/src/sage/schemes/affine/affine_space.py @@ -1,5 +1,5 @@ """ -Affine `n` space over a ring +Affine `n`-space over a ring """ # **************************************************************************** diff --git a/src/sage/schemes/projective/projective_point.py b/src/sage/schemes/projective/projective_point.py index dea15db15e5..d688b5a6bdd 100644 --- a/src/sage/schemes/projective/projective_point.py +++ b/src/sage/schemes/projective/projective_point.py @@ -1,29 +1,23 @@ r""" Points on projective varieties -Scheme morphism for points on projective varieties - - +This module implements scheme morphism for points on projective varieties. AUTHORS: -- David Kohel, William Stein - -- William Stein (2006-02-11): fixed bug where P(0,0,0) was allowed as - a projective point. - -- Volker Braun (2011-08-08): Renamed classes, more documentation, misc - cleanups. - -- Ben Hutz (June 2012) added support for projective ring; - (March 2013) iteration functionality and new directory structure +- David Kohel, William Stein (2006): initial version +- William Stein (2006-02-11): fixed bug where P(0,0,0) was allowed as a + projective point +- Volker Braun (2011-08-08): Renamed classes, more documentation, misc cleanups +- Ben Hutz (2012-06): added support for projective ring +- Ben Hutz (2013-03): added iteration functionality and new directory structure for affine/projective, height functionality """ # **************************************************************************** -# Copyright (C) 2011 Volker Braun # Copyright (C) 2006 David Kohel # Copyright (C) 2006 William Stein +# Copyright (C) 2011 Volker Braun # # 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 @@ -34,7 +28,6 @@ from sage.categories.integral_domains import IntegralDomains from sage.categories.number_fields import NumberFields -_NumberFields = NumberFields() from sage.rings.fraction_field import FractionField from sage.rings.number_field.order import is_NumberFieldOrder, Order as NumberFieldOrder from sage.rings.qqbar import number_field_elements_from_algebraics @@ -52,9 +45,11 @@ from sage.structure.sequence import Sequence from sage.structure.richcmp import richcmp, op_EQ, op_NE -#******************************************************************* + +# -------------------- # Projective varieties -#******************************************************************* +# -------------------- + class SchemeMorphism_point_projective_ring(SchemeMorphism_point): """ A rational point of projective space over a ring. @@ -752,7 +747,7 @@ def global_height(self, prec=None): if prec is None: prec = 53 K = self.codomain().base_ring() - if K in _NumberFields or is_NumberFieldOrder(K): + if K in NumberFields() or is_NumberFieldOrder(K): P = self else: try: @@ -807,7 +802,7 @@ def local_height(self, v, prec=None): 0.693147180559945 """ K = FractionField(self.domain().base_ring()) - if K not in _NumberFields: + if K not in NumberFields(): raise TypeError("must be over a number field or a number field order") return max([K(c).local_height(v, prec=prec) for c in self]) @@ -842,7 +837,7 @@ def local_height_arch(self, i, prec=None): 3.401197381662155375413236691607 """ K = FractionField(self.domain().base_ring()) - if K not in _NumberFields: + if K not in NumberFields(): raise TypeError("must be over a number field or a number field order") if K == QQ: return max(K(c).local_height_arch(prec=prec) for c in self) @@ -1054,6 +1049,7 @@ def is_preperiodic(self, f, err=0.1, return_period=False): except AttributeError: raise TypeError("map must be a dynamical system") + class SchemeMorphism_point_projective_field(SchemeMorphism_point_projective_ring): """ A rational point of projective space over a field. @@ -1401,6 +1397,35 @@ def multiplicity(self): raise TypeError("this point must be a point on a projective subscheme") return self.codomain().multiplicity(self) + def as_subscheme(self): + r""" + Return the subscheme associated with this rational point. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ,2) + sage: p1 = P2.point([0,0,1]).as_subscheme(); p1 + Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: + x, y + sage: p2 = P2.point([1,1,1]).as_subscheme(); p2 + Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: + x - z, y - z + sage: p1 + p2 + Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: + x - y, y^2 - y*z + """ + P = self.codomain().ambient_space() + g = P.gens() + v = self._coords + n = len(v) + for i in range(n - 1, -1, -1): + if v[i]: + break + a = v[i] + x = g[i] + return P.subscheme([a*g[j] - v[j]*x for j in range(n) if j != i]) + + class SchemeMorphism_point_projective_finite_field(SchemeMorphism_point_projective_field): def __hash__(self): @@ -1438,9 +1463,11 @@ def __hash__(self): N = self.codomain().ambient_space().dimension_relative() return hash(sum(hash(self[i]) * p**i for i in range(N + 1))) -#******************************************************************* + +# ----------------- # Abelian varieties -#******************************************************************* +# ----------------- + class SchemeMorphism_point_abelian_variety_field(AdditiveGroupElement, SchemeMorphism_point_projective_field): """ A rational point of an abelian variety over a field. diff --git a/src/sage/schemes/projective/projective_space.py b/src/sage/schemes/projective/projective_space.py index 5c55a62106e..07939aa7387 100644 --- a/src/sage/schemes/projective/projective_space.py +++ b/src/sage/schemes/projective/projective_space.py @@ -1,5 +1,5 @@ r""" -Projective `n` space over a ring +Projective `n`-space over a ring EXAMPLES: @@ -110,6 +110,7 @@ from sage.combinat.tuple import UnorderedTuples from sage.combinat.subset import Subsets from sage.matrix.constructor import matrix +from sage.modules.free_module import FreeModule from sage.modules.free_module_element import prepare from sage.schemes.generic.ambient_space import AmbientSpace from sage.schemes.projective.projective_homset import (SchemeHomset_points_projective_ring, @@ -2266,6 +2267,71 @@ def line_through(self, p, q): m = matrix(3, list(self.gens()) + list(p) + list(q)) return Curve([f for f in m.minors(3) if f]) + def coherent_sheaf(self, module, twist=0): + r""" + Return the sheaf defined by the graded ``module``. + + If ``twist`` is a non-zero integer `n`, the sheaf twisted by + `\OO_{\PP^r}(n)` is returned. + + INPUT: + + - ``module`` -- a free module or a quotient module over the coordinate + ring of this space + + - ``twist`` -- (default: `0`) an integer + + EXAMPLES:: + + sage: P2 = ProjectiveSpace(QQ, 2, 'x') + sage: S = P2.coordinate_ring() + sage: SS = FreeModule(S, 2) + sage: P2.coherent_sheaf(SS, twist=2) + Twisted Sheaf on Projective Space of dimension 2 over Rational Field + """ + from sage.schemes.sheaves.sheaf import Sheaf_on_projective_space + return Sheaf_on_projective_space(self, module, twist=twist) + + def structure_sheaf(self, twist=0): + r""" + Return the structure sheaf `\OO_{\PP^r}` of this projective space. + + If ``twist`` is a non-zero integer `n`, the sheaf twisted by + `\OO_{\PP^r}(n)` is returned. + + INPUT: + + - ``twist`` -- (default: `0`) an integer + + EXAMPLES:: + + sage: P3. = ProjectiveSpace(QQ, 3) + sage: P3.structure_sheaf() + Sheaf on Projective Space of dimension 3 over Rational Field + """ + M = FreeModule(self.coordinate_ring(), rank=1) + return self.coherent_sheaf(M, twist=twist) + + def arithmetic_genus(self): + r""" + Return the arithmetic genus of this projective space. + + This is known to be zero. This method simply checks the fact. + + EXAMPLES:: + + sage: P1 = ProjectiveSpace(QQ, 1) + sage: P1.arithmetic_genus() + 0 + sage: P2 = ProjectiveSpace(QQ, 2) + sage: P2.arithmetic_genus() + 0 + """ + p = self.structure_sheaf().euler_characteristic() - 1 + if self.dimension() % 2: + p = -p + return p + class ProjectiveSpace_finite_field(ProjectiveSpace_field): def _point(self, *args, **kwds): diff --git a/src/sage/schemes/projective/projective_subscheme.py b/src/sage/schemes/projective/projective_subscheme.py index 3ea963e0e04..ea485eb35dc 100644 --- a/src/sage/schemes/projective/projective_subscheme.py +++ b/src/sage/schemes/projective/projective_subscheme.py @@ -1515,3 +1515,77 @@ def local_height_arch(self, i, prec=None): 4.61512051684126 """ return self.Chow_form().local_height_arch(i, prec) + + def coherent_sheaf(self, module, twist=0): + r""" + Return the sheaf defined by the graded ``module``. + + If ``twist`` is a non-zero integer `n`, the sheaf twisted by + `\OO_{\PP^r}(n)` is returned. + + INPUT: + + - ``module`` -- a free module or a quotient module + + - ``twist`` -- (default: `0`) an integer + + EXAMPLES:: + + sage: P3. = ProjectiveSpace(QQ, 3) + sage: X = P3.subscheme(x0^3 + x1^3 + x2^3 + x3^3) + sage: S = X.coordinate_ring() + sage: SS = FreeModule(S, 2) + sage: X.coherent_sheaf(SS, twist=2) + Twisted Sheaf on Closed subscheme of Projective Space of dimension 3 over + Rational Field defined by: x0^3 + x1^3 + x2^3 + x3^3 + """ + from sage.schemes.sheaves.sheaf import Sheaf_on_projective_subscheme + return Sheaf_on_projective_subscheme(self, module, twist=twist) + + def structure_sheaf(self, twist=0): + r""" + Return the structure sheaf `\OO_{\PP^r}` of this projective space. + + If ``twist`` is a non-zero integer `n`, the sheaf twisted by + `\OO_{\PP^r}(n)` is returned. + + INPUT: + + - ``twist`` -- (default: `0`) an integer + + EXAMPLES:: + + sage: P3. = ProjectiveSpace(QQ, 3) + sage: X = P3.subscheme(x0^3 + x1^3 + x2^3 + x3^3) + sage: X.structure_sheaf() + Sheaf on Closed subscheme of Projective Space of dimension 3 over + Rational Field defined by: x0^3 + x1^3 + x2^3 + x3^3 + """ + from sage.modules.free_module import FreeModule + M = FreeModule(self.coordinate_ring(), rank=1) + return self.coherent_sheaf(M, twist=twist) + + def arithmetic_genus(self): + r""" + Return the arithmetic genus of this subscheme of a projective space. + + EXAMPLES: + + This is an example of a curve whose arithmetic genus is smaller than + geometric genus due to a singular point:: + + sage: A2. = AffineSpace(QQ,2) + sage: C = Curve(x^4 - 5*x^2 - y^2 + 4, A2) + sage: X = C.projective_closure() + sage: X.arithmetic_genus() + 3 + sage: X.geometric_genus() + 1 + sage: X.is_singular() + True + """ + p = self.structure_sheaf().euler_characteristic() - 1 + if self.dimension() % 2: + p = -p + return p + diff --git a/src/sage/schemes/sheaves/__init__.py b/src/sage/schemes/sheaves/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/sage/schemes/sheaves/cohomology.py b/src/sage/schemes/sheaves/cohomology.py new file mode 100644 index 00000000000..45276167854 --- /dev/null +++ b/src/sage/schemes/sheaves/cohomology.py @@ -0,0 +1,492 @@ +r""" +Cohomology of coherent sheaves + +This module implements Maruyama's method for computing cohomology of coherent +sheaves on a projective space. The method is explained and proved in detail in +[Kudo2017]_. + +Let `M` be a graded module finitely generated over the homogeneous coordinate +ring `S` of the projective `r`-space over a field `k`. We aim for computing the +cohomology groups `H^q(\tilde M)` for the coherent sheaf `\tilde M`. + +Let `S=k[x_0,x_2,\dots,x_r]`. Then `M` is a quotient of the free module +`\bigoplus_{i=1}^{t}S` by a submodule. Let + +.. MATH:: + + 0\to\bigoplus_{j=1}^{t_{r+1}}S(-m^{(r+1)}_j)\overset{f_{r+1}}{\longrightarrow}\dots + \overset{f_1}{\longrightarrow}\bigoplus_{j=1}^{t_0}S(-m^{(0)}_j)\overset{f_0}{\longrightarrow}M\to 0 + +be a minimal free resolution of `M`. Then it induces a complex of (top) cohomology groups + +.. MATH:: + + \bigoplus_{j=1}^{t_{i+1}}H^r(\OO_{\PP^r}(-m^{(i+1)}_j))\overset{H^r(f_{i+1})}{\longrightarrow} + \bigoplus_{j=1}^{t_i}H^r(\OO_{\PP^r}(-m^{(i)}_j))\overset{H^r(f_{i})}{\longrightarrow} + \bigoplus_{j=1}^{t_{i-1}}H^r(\OO_{\PP^r}(-m^{(i-1)}_j)) + +where `i` runs from `1` to `r`. Now it holds that + +.. MATH:: + + H^q(\tilde M)\cong \ker H^r(f_{r-q})/\im H^r(f_{r-q+1}) + +for `1\le q\le r - 1` and + +.. MATH:: + + H^r(\tilde M)\cong \bigoplus_{j=1}^{t_0}H^r(\OO_{\PP^r}(-m^{(0)}_j))/\im H^r(f_1) + +and `\dim H^0(\tilde M)` can be computed by the formula + +.. MATH:: + + \begin{split} + &\dim \bigoplus_{j=1}^{t_{0}}H^0(\OO_{\PP^r}(-m^{(0)}_j)) + -\dim \bigoplus_{j=1}^{t_{r+1}}H^r(\OO_{\PP^r}(-m^{(r+1)}_j)) + +\dim \bigoplus_{j=1}^{t_{r}}H^r(\OO_{\PP^r}(-m^{(r)}_j)) \\ + &\quad -\rank H^0(f_1)-\rank H^r(f_r) + \end{split} + +in which the complex of (bottom) cohomology groups + +.. MATH:: + + \bigoplus_{j=1}^{t_{i+1}}H^0(\OO_{\PP^r}(-m^{(i+1)}_j))\overset{H^0(f_{i+1})}{\longrightarrow} + \bigoplus_{j=1}^{t_i}H^0(\OO_{\PP^r}(-m^{(i)}_j))\overset{H^0(f_{i})}{\longrightarrow} + \bigoplus_{j=1}^{t_{i-1}}H^0(\OO_{\PP^r}(-m^{(i-1)}_j)) + +where `i` runs from `1` to `r` is used. + +The implemented algorithm works more generally for twisted coherent sheaves and +accepts as input shifted graded module `M(-n)` with shift `n`. + +EXAMPLES: + +We define the Fermat cubic surface (a curve in `\PP^2`) and compute its cohomology groups:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme([x^4 + y^4 + z^4]) + sage: sh = X.structure_sheaf() + sage: sh.cohomology(1) + 3 + sage: sh.cohomology_group(1) + Vector space quotient V/W of dimension 3 over Rational Field where + V: Vector space of degree 3 and dimension 3 over Rational Field + Basis matrix: + [1 0 0] + [0 1 0] + [0 0 1] + W: Vector space of degree 3 and dimension 0 over Rational Field + Basis matrix: + [] + sage: sh.cohomology_group(1).dimension() + 3 + sage: sh.cohomology(2) + 0 + sage: sh.cohomology_group(2) + Vector space quotient V/W of dimension 0 over Rational Field where + V: Vector space of dimension 0 over Rational Field + W: Vector space of degree 0 and dimension 0 over Rational Field + Basis matrix: + [] + sage: sh.cohomology_group(2).dimension() + 0 + + +The rather complicated form (as a quotient of vector spaces) of the cohomology +group reflects the relationship of the cohomology group with those of the +twisted structure sheaves of the projective space. + +On the other hand, it is not clear how to realize `H^0(\tilde M)` +in terms of twisted structure sheaves of the projective space. Hence it is +merely created as a vector space over `k` with the correct dimension:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme([x^4 + y^4 + z^4]) + sage: sh = X.structure_sheaf() + sage: sh.cohomology(0) + 1 + sage: sh.cohomology_group(0) + Vector space of dimension 1 over Rational Field +""" + +from sage.misc.flatten import flatten +from sage.combinat.integer_lists.invlex import IntegerListsLex +from sage.modules.free_module import VectorSpace +from sage.modules.free_module_element import vector + + +class CohomologyGroupBottom: + r""" + Bottom cohomology group of the twisted structure sheaf of a projective space. + + INPUT: + + - ``S`` -- a direct sum of copies of the coordinate ring of a projective space + + - ``shifts`` -- shifts of the component rings of ``S`` + + This represents `\bigoplus_{j=1}^{t_i}H^0(\OO_{\PP^r}(-m^{(i)}_j))` for shifts `m^{(i)}_j`. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme([x^4 + y^4 + z^4]) + sage: c = X.structure_sheaf()._cohomology + sage: c.cohomology_group_bottom(0) + Bottom Cohomology Group of dimension 1 + """ + def __init__(self, S, shifts): + """ + Initialize. + + TESTS:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme([x^4 + y^4 + z^4]) + sage: c = X.structure_sheaf(twist=1)._cohomology + sage: c.cohomology_group_bottom(0) + Bottom Cohomology Group of dimension 3 + """ + self.graded_ring = S + self.shifts = shifts + + n = S.ngens() + + basis = [] + summands_basis = [] + summands_index = [] + rank = 0 + for m in self.shifts: + # list of integer vectors whose entries are all non-negative integers and sum to -m + l = [vector(e) for e in IntegerListsLex(length=n, min_sum=-m, max_sum=-m)] + basis += l + summands_basis.append(l) + summands_index.append(rank) + rank += len(l) + + self.summands_basis = summands_basis + self.summands_index = summands_index + self.basis = basis + self.vector_space = VectorSpace(S.base_ring(), rank) + self.rank = rank + + def __repr__(self): + r""" + Return the string representation of ``self``. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme([x^4 + y^4 + z^4]) + sage: c = X.structure_sheaf()._cohomology + sage: c.cohomology_group_bottom(0) + Bottom Cohomology Group of dimension 1 + """ + return f'Bottom Cohomology Group of dimension {self.rank}' + + +class CohomologyGroupTop: + r""" + Top cohomology group of the twisted structure sheaf of a projective space. + + INPUT: + + - ``S`` -- a direct sum of copies of the coordinate ring of a projective space + + - ``shifts`` -- shifts of the component rings of ``S`` + + This represents `\bigoplus_{j=1}^{t_i}H^r(\OO_{\PP^r}(-m^{(i)}_j))` for shifts `m^{(i)}_j`. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme([x^4 + y^4 + z^4]) + sage: c = X.structure_sheaf()._cohomology + sage: c.cohomology_group_top(0) + Top Cohomology Group of dimension 0 + """ + def __init__(self, S, shifts): + """ + Initialize. + + TESTS:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme([x^4 + y^4 + z^4]) + sage: c = X.structure_sheaf(twist=1)._cohomology + sage: c.cohomology_group_top(1) + Top Cohomology Group of dimension 1 + """ + self.graded_ring = S + self.shifts = shifts + + n = S.ngens() + + basis = [] + summands_basis = [] + summands_index = [] + rank = 0 + for m in self.shifts: + # list of integer vectors whose entries are all negative integers and sum to -m + l = [-vector(e) for e in IntegerListsLex(length=n, min_sum=m, max_sum=m, min_part=1)] + basis += l + summands_basis.append(l) + summands_index.append(rank) + rank += len(l) + + self.summands_basis = summands_basis + self.summands_index = summands_index + self.basis = basis + self.vector_space = VectorSpace(S.base_ring(), rank) + self.rank = rank + + def __repr__(self): + r""" + Return the string representation. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme([x^4 + y^4 + z^4]) + sage: c = X.structure_sheaf()._cohomology + sage: c.cohomology_group_top(1) + Top Cohomology Group of dimension 3 + """ + return f'Top Cohomology Group of dimension {self.rank}' + + +class MaruyamaComplex: + r""" + This class implements Maruyama's method to compute the cohomology group + `H^q(\tilde M(n))` as a vector space over the base field `k` and + `h^q(\tilde M(n))=\dim_kH^q(\tilde M(n))` where `n` denotes the twist. + + INPUT: + + - ``M`` -- a quotient of a free module over `S` by a submodule, where `S` + is a multi-variate polynomial ring + + - ``twist`` -- (default: 0) an integer + + This class provides :meth:`H` and :meth:`h` as public interface, and all + other methods are internal. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme([x^4 + y^4 + z^4]) + sage: sh = X.structure_sheaf(1) # twisted sheaf + sage: sh._cohomology + Maruyama Complex induced from S(1) <-- S(-3) <-- 0 + """ + def __init__(self, M, twist=0): + """ + Initialize. + """ + shifts = [-twist for i in range(M.cover().degree())] + self.resolution = M.relations().graded_free_resolution(shifts=shifts) + self.base_ring = self.resolution.target().base_ring() + self.coefficient_field = self.base_ring.base_ring() + self.projective_space_dimension = self.base_ring.ngens() - 1 + + def __repr__(self): + """ + Return the string representation. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme([x^4 + y^4 + z^4]) + sage: X.structure_sheaf()._cohomology + Maruyama Complex induced from S(0) <-- S(-4) <-- 0 + """ + return f'Maruyama Complex induced from {self.resolution}' + + def cohomology_group_bottom(self, i): + r""" + Return `i`-th bottom cohomology group `\bigoplus_{j=1}^{t_i}H^0(\OO_{\PP^r}(-m^{(i)}_j))` + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme([x^4 + y^4 + z^4]) + sage: c = X.structure_sheaf()._cohomology + sage: c.cohomology_group_bottom(1) + Bottom Cohomology Group of dimension 0 + """ + S = self.base_ring + shifts = self.resolution.shifts(i) + return CohomologyGroupBottom(S, shifts) + + def cohomology_group_top(self, i): + r""" + Return `i`-th top cohomology group `\bigoplus_{j=1}^{t_i}H^r(\OO_{\PP^r}(-m^{(i)}_j))` + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme([x^4 + y^4 + z^4]) + sage: c = X.structure_sheaf()._cohomology + sage: c.cohomology_group_top(1) + Top Cohomology Group of dimension 3 + """ + S = self.base_ring + shifts = self.resolution.shifts(i) + return CohomologyGroupTop(S, shifts) + + def differential_bottom(self, i): + r""" + Return the `i`-th bottom differential map `H^0(f_i)`. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme([x^4 + y^4 + z^4]) + sage: c = X.structure_sheaf()._cohomology + sage: c.differential_bottom(1) + Vector space morphism represented as left-multiplication by the matrix: + [] + Domain: Vector space of dimension 0 over Rational Field + Codomain: Vector space of dimension 1 over Rational Field + """ + H1 = self.cohomology_group_bottom(i) + H0 = self.cohomology_group_bottom(i - 1) + M = self.resolution.differential(i).matrix() + K = self.coefficient_field + zero = K.zero() + + assert M.ncols() == len(H1.summands_basis) + assert M.nrows() == len(H0.summands_basis) + + A = [] + for i in range(M.ncols()): + basis = H1.summands_basis[i] + for v in basis: + image = [zero for e in range(H0.rank)] + for j in range(M.nrows()): + f = M[j,i] + basis = H0.summands_basis[j] + for c, m in zip(f.coefficients(), f.exponents()): + u = v + vector(m) + assert(sum(u) == -H0.shifts[j]) + if any(e < 0 for e in u): + continue + k = H0.summands_index[j] + basis.index(u) + image[k] += c + A.append(vector(K, image)) + + return H1.vector_space.hom(A, codomain=H0.vector_space, side='right') + + def differential_top(self, i): + r""" + Return the `i`-th top differential map `H^r(f_i)`. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme([x^4 + y^4 + z^4]) + sage: c = X.structure_sheaf()._cohomology + sage: c.differential_top(1) + Vector space morphism represented as left-multiplication by the matrix: + [] + Domain: Vector space of dimension 3 over Rational Field + Codomain: Vector space of dimension 0 over Rational Field + """ + H1 = self.cohomology_group_top(i) + H0 = self.cohomology_group_top(i - 1) + M = self.resolution.differential(i).matrix() + K = self.coefficient_field + zero = K.zero() + + assert M.ncols() == len(H1.summands_basis) + assert M.nrows() == len(H0.summands_basis) + + A = [] + for i in range(M.ncols()): + basis = H1.summands_basis[i] + for v in basis: + image = [zero for e in range(H0.rank)] + for j in range(M.nrows()): + f = M[j,i] + basis = H0.summands_basis[j] + for c, m in zip(f.coefficients(), f.exponents()): + u = v + vector(m) + assert(sum(u) == -H0.shifts[j]) + if any(e >= 0 for e in u): + continue + k = H0.summands_index[j] + basis.index(u) + image[k] += c + A.append(vector(K, image)) + + return H1.vector_space.hom(A, codomain=H0.vector_space, side='right') + + def H(self, q): + r""" + Return the `q`-th cohomology group `H^q(\tilde M)`. + + INPUT: + + - ``q`` -- non-negative integer + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme([x^4 + y^4 + z^4]) + sage: c = X.structure_sheaf()._cohomology + sage: c.H(1) + Vector space quotient V/W of dimension 3 over Rational Field where + V: Vector space of degree 3 and dimension 3 over Rational Field + Basis matrix: + [1 0 0] + [0 1 0] + [0 0 1] + W: Vector space of degree 3 and dimension 0 over Rational Field + Basis matrix: + [] + """ + r = self.projective_space_dimension + if q == r: + return self.cohomology_group_top(0).vector_space.quotient(self.differential_top(1).image()) + elif 1 <= q and q < r: + return self.differential_top(r - q).kernel().quotient(self.differential_top(r - q + 1).image()) + elif q == 0: + # 0th cohomology group of (global sections) is not realized in + # terms of cohomology groups and differential maps of twisted + # structure sheaves of the projective space. + return VectorSpace(self.coefficient_field, self.h(0)) + elif q > r: + return VectorSpace(self.coefficient_field, 0) + raise IndexError('index must be non-negative') + + def h(self, q): + r""" + Return the dimension `h^q(\tilde M)` of the `q`-th cohomology group `H^q(\tilde M)`. + + INPUT: + + - ``q`` -- non-negative integer + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme([x^4 + y^4 + z^4]) + sage: c = X.structure_sheaf()._cohomology + sage: c.h(1) + 3 + """ + r = self.projective_space_dimension + if q == r: + return self.cohomology_group_top(0).rank - self.differential_top(1).rank() + elif 1 <= q and q < r: + return self.differential_top(r - q).kernel().dimension() - self.differential_top(r - q + 1).rank() + elif q == 0: + a = (self.cohomology_group_bottom(0).rank - self.cohomology_group_top(r + 1).rank + + self.cohomology_group_top(r).rank) + b = self.differential_bottom(1).rank() + self.differential_top(r).rank() + return a - b + elif q > r: + return 0 + raise IndexError('index must be non-negative') + diff --git a/src/sage/schemes/sheaves/sheaf.py b/src/sage/schemes/sheaves/sheaf.py new file mode 100644 index 00000000000..22e6691ec18 --- /dev/null +++ b/src/sage/schemes/sheaves/sheaf.py @@ -0,0 +1,260 @@ +r""" +Coherent sheaves + +EXAMPLES: + +We define the Fermat cubic surface in \PP^2 and construct its structure sheaf:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme(x^4 + y^4 + z^4) + sage: sh = X.structure_sheaf() + +AUTHORS: + +- Kwankyu Lee (2024-01-22): initial version + +""" + +from functools import cached_property +from sage.structure.sage_object import SageObject +from sage.modules.free_module import FreeModule + + +class Sheaf(SageObject): + r""" + Coherent sheaf on a projective scheme. + + INPUT: + + - ``scheme`` -- the base scheme on which the sheaf is defined + + - ``module`` -- a free module or its quotient by a submodule + + - ``twist`` -- (default: 0) an integer + + This class constructs the coherent sheaf `\tilde M(n)` if `M` is the + ``module`` and `n` is the ``twist``. + """ + def __init__(self, scheme, module, twist=0): + """ + Initialize ``self``. + """ + try: + if module.is_ambient(): + module = module.quotient(module.zero_submodule()) + except AttributeError: + pass + + assert module.cover() == module.free_cover() + + self._base_scheme = scheme + self._module = module + self._twist = twist + + @cached_property + def _cohomology(self): + """ + Return an object that computes the cohomology. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme(x^4 + y^4 + z^4) + sage: sheaf = X.structure_sheaf() + sage: c = sheaf._cohomology + sage: c.H(1).dimension() + 3 + sage: c.h(1) + 3 + """ + raise NotImplementedError('_cohomology is not implemented') + + def _repr_(self): + sheaf = 'Twisted Sheaf' if self._twist else 'Sheaf' + return f'{sheaf} on {self._base_scheme}' + + def base_scheme(self): + """ + Return the base scheme on which this sheaf is defined. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme(x^4 + y^4 + z^4) + sage: s = X.structure_sheaf() + sage: s.base_scheme() + Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: + x^4 + y^4 + z^4 + """ + return self._base_scheme + + def defining_twist(self): + """ + Return the integer by which the module defining this coherent sheaf is + twisted. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme(x^4 + y^4 + z^4) + sage: s = X.structure_sheaf(3) + sage: s.defining_twist() + 3 + """ + return self._twist + + def defining_module(self): + """ + Return the module defining this coherent sheaf. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme(x^4 + y^4 + z^4) + sage: X.structure_sheaf() + Sheaf on Closed subscheme of Projective Space of dimension 2 over + Rational Field defined by: x^4 + y^4 + z^4 + """ + return self._module + + def cohomology_group(self, r=0): + """ + Return the `r`-th cohomology as a vector space. + + INPUT: + + - ``r`` -- (default: 0) a non-negative integer + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme(x^4 + y^4 + z^4) + sage: s = X.structure_sheaf() + sage: s.cohomology_group(1).dimension() + 3 + """ + return self._cohomology.H(r) + + def cohomology(self, r=0): + """ + Return the dimension of the `r`-th cohomology as a vector space. + + INPUT: + + - ``r`` -- (default: 0) a non-negative integer + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme(x^4 + y^4 + z^4) + sage: sheaf = X.structure_sheaf() + sage: sheaf.cohomology(0) + 1 + sage: sheaf.cohomology(1) + 3 + sage: sheaf.cohomology(2) + 0 + """ + return self._cohomology.h(r) + + def twist(self, t=0): + r""" + Return the twisted sheaf `F(n)` of this sheaf `F`. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme(x^4 + y^4 + z^4) + sage: sh = X.structure_sheaf() + sage: sh.twist(1).euler_characteristic() + 2 + sage: sh.twist(2).euler_characteristic() + 6 + """ + return type(self)(self._base_scheme, self._module, self._twist + t) + + def euler_characteristic(self): + """ + Return the Euler characteristic of this coherent sheaf. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme(x^4 + y^4 + z^4) + sage: sh = X.structure_sheaf() + sage: sh.euler_characteristic() + -2 + """ + d = self._base_scheme.dimension() + chi = 0 + for r in range(d + 1): # for Grothendieck's vanishing theorem + d = self.cohomology(r) + if r % 2: + chi = chi - d + else: + chi = chi + d + return chi + + +class Sheaf_on_projective_space(Sheaf): + + @cached_property + def _cohomology(self): + """ + This property keeps the cohomology object for this sheaf. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: P2.structure_sheaf()._cohomology + Maruyama Complex induced from S(0) <-- 0 + """ + from sage.schemes.sheaves.cohomology import MaruyamaComplex + return MaruyamaComplex(self._module, twist=self._twist) + + +class Sheaf_on_projective_subscheme(Sheaf): + + @cached_property + def _cohomology(self): + """ + This property keeps the cohomology object for this sheaf. + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme(x^4 + y^4 + z^4) + sage: X.structure_sheaf()._cohomology + Maruyama Complex induced from S(0) <-- S(-4) <-- 0 + """ + return self.image_to_ambient_space()._cohomology + + def image_to_ambient_space(self): + """ + Return the direct image of this sheaf to the ambient space. + + The image is with respect to the inclusion morphism from the base + scheme into the projective Space. + + INPUT: + + - ``twist`` -- (default: `0`) an integer + + EXAMPLES:: + + sage: P2. = ProjectiveSpace(QQ, 2) + sage: X = P2.subscheme(x^4 + y^4 + z^4) + sage: X.structure_sheaf().image_to_ambient_space() + Sheaf on Projective Space of dimension 2 over Rational Field + """ + X = self._base_scheme + A = X.ambient_space() + S = A.coordinate_ring() + + d = self._module.degree() + M = FreeModule(S, d) + I = X.defining_polynomials() + J = self._module.relations().gens() + G = [f * M.gen(i) for i in range(d) for f in I] + [v.change_ring(S) for v in J] + N = M.submodule(G) + return A.coherent_sheaf(M.quotient(N), twist=self._twist)