253 lines
9.6 KiB
Python
253 lines
9.6 KiB
Python
r"""
|
|
This module implements the ExtGroup and ExtGroupElement classes used for
|
|
building extensions of vector bundles.
|
|
|
|
AUTHORS:
|
|
|
|
_Mickaël Montessinos: initial implementation
|
|
"""
|
|
|
|
###########################################################################
|
|
# Copyright (C) 2024 Mickaël Montessinos (mickael.montessinos@mif.vu.lt),#
|
|
# #
|
|
# Distributed under the terms of the GNU General Public License (GPL) #
|
|
# either version 3, or (at your option) any later version #
|
|
# #
|
|
# http://www.gnu.org/licenses/ #
|
|
###########################################################################
|
|
|
|
from sage.structure.sage_object import SageObject
|
|
from sage.structure.element import is_Matrix
|
|
from sage.matrix.special import block_matrix
|
|
from sage.modules.free_module_element import vector
|
|
|
|
class ExtGroup(SageObject):
|
|
r"""
|
|
The group of extensions of ``left`` by ``right``.
|
|
|
|
The group `Ext^1(\mathrm{left},\mathrm{right})` is
|
|
`H^1(\mathrm{left}^\vee \otimes \mathrm{right})`.
|
|
Its elements may be represented as matrices of infinite répartitions
|
|
lying in `M_{\mathrm{right}.rank(),\mathrm{left}.rank()}(R)` or as
|
|
vectors of length ``self.dim()`` with coefficients in the coefficient
|
|
field, representing linear forms on
|
|
`H^0(\omega \otimes \mathrm{right}^\vee \otimes \mathrm{left})`, where
|
|
`\omega` is the canonical bundle of the function field of ``left`` and
|
|
``right``
|
|
The two representations are related via Serre duality.
|
|
|
|
If ``precompute_basis`` is set to ``True``, a basis of répartition
|
|
matrices is computed. Its element represent the linear forms
|
|
``vector([0,...,0,1,0,...,0])``. Otherwise, linear forms are converted
|
|
to elements of the `H^1` on the fly. You should set ``precompute_basis``
|
|
to ``True`` only if you plan to create several extensions with this group.
|
|
|
|
INPUT:
|
|
|
|
- ``left`` -- VectorBundle
|
|
- ``right`` -- VectorBundle; must have the same function field as left
|
|
- ``precompute_basis`` -- boolean
|
|
|
|
EXAMPLES ::
|
|
|
|
sage: from vector_bundle import VectorBundle, trivial_bundle
|
|
sage: F.<x> = FunctionField(GF(3))
|
|
sage: triv = trivial_bundle(F)
|
|
sage: triv.extension_group(triv)
|
|
Extension group of Vector bundle of rank 1 over Rational function field in x over Finite Field of size 3 by Vector bundle of rank 1 over Rational function field in x over Finite Field of size 3.
|
|
"""
|
|
def __init__(self, left, right, precompute_basis=False):
|
|
if not left._function_field == right._function_field:
|
|
raise ValueError('left and right should have the same function'
|
|
+ 'field')
|
|
self._left = left
|
|
self._right = right
|
|
self._hom = left.hom(right)
|
|
self._ext_dual_basis, self._ext_dual_bundle = self._hom.h1_dual()
|
|
self._s = len(self._ext_dual_basis)
|
|
if precompute_basis:
|
|
self._compute_basis()
|
|
else:
|
|
self._basis = None
|
|
|
|
def __hash__(self):
|
|
return hash((self._left, self._right))
|
|
|
|
def __eq__(self, other):
|
|
return self._left == other._left and self._right == other._right
|
|
|
|
def _repr_(self):
|
|
return "Extension group of %s by %s." % (self._left, self._right)
|
|
|
|
def _compute_basis(self):
|
|
r"""
|
|
Compute the representation of basis elements of ``self`` as elements of the `H^1`
|
|
"""
|
|
if self._basis is None:
|
|
self._basis = [self._hom.h1_element(
|
|
vector([0] * i + [1] + [0] * (self._s-i-1)))
|
|
for i in range(self._s)]
|
|
|
|
def dim(self):
|
|
r"""
|
|
Return the dimension of the extension group as a vector space over the
|
|
base coefficient field
|
|
|
|
EXAMPLES ::
|
|
|
|
sage: from vector_bundle import VectorBundle
|
|
sage: F.<x> = FunctionField(GF(11))
|
|
sage: R.<y> = F[]
|
|
sage: K.<y> = F.extension(y^2 - x^5 - 1)
|
|
sage: ksi = VectorBundle(K, K.places_finite()[0].divisor())
|
|
sage: ext = ksi.extension_group(ksi.dual()); ext.dim()
|
|
3
|
|
"""
|
|
return self._s
|
|
|
|
def left(self):
|
|
r"""
|
|
Return the left vector bundle of ``self``.
|
|
|
|
EXAMPLES ::
|
|
|
|
sage: from vector_bundle import VectorBundle
|
|
sage: F.<x> = FunctionField(GF(3))
|
|
sage: L1 = VectorBundle(F, x.zeros()[0].divisor())
|
|
sage: L2 = VectorBundle(F, x.poles()[0].divisor())
|
|
sage: ext = L1.extension_group(L2); ext.left() == L1
|
|
True
|
|
"""
|
|
return self._left
|
|
|
|
def right(self):
|
|
r"""
|
|
Return the right vector bundle of ``self``.
|
|
|
|
EXAMPLES ::
|
|
|
|
sage: from vector_bundle import VectorBundle
|
|
sage: F.<x> = FunctionField(GF(3))
|
|
sage: L1 = VectorBundle(F, x.zeros()[0].divisor())
|
|
sage: L2 = VectorBundle(F, x.poles()[0].divisor())
|
|
sage: ext = L1.extension_group(L2); ext.right() == L2
|
|
True
|
|
"""
|
|
return self._right
|
|
|
|
def dual_basis(self):
|
|
r"""
|
|
Return a basis of the dual of the `Ext^1` group. This is a basis of
|
|
`H^0(\omega \otimes \mathrm{right}^\vee \otimes \mathrm{left})`, where
|
|
`\omega` is a canonical line bundle.
|
|
|
|
EXAMPLES ::
|
|
|
|
sage: from vector_bundle import VectorBundle
|
|
sage: F.<x> = FunctionField(GF(11))
|
|
sage: R.<y> = F[]
|
|
sage: K.<y> = F.extension(y^2 - x^5 - 1)
|
|
sage: ksi = VectorBundle(K, K.places_finite()[0].divisor())
|
|
sage: ext = ksi.extension_group(ksi.dual()); ext.dual_basis()
|
|
[[x^4/(x^5 + 6)], [x^5/(x^5 + 6)], [(x^2/(x^5 + 6))*y + 10*x^2/(x^5 + 6)]]
|
|
"""
|
|
return self._ext_dual_basis
|
|
|
|
def basis(self):
|
|
r"""Return a basis of `Ext^1` group. Its element are matrices of
|
|
infinite répartitions represented by field elements.
|
|
|
|
Computes and stores the basis if it was not precomputed yet.
|
|
|
|
EXAMPLES ::
|
|
|
|
sage: from vector_bundle import VectorBundle
|
|
sage: F.<x> = FunctionField(GF(11))
|
|
sage: R.<y> = F[]
|
|
sage: K.<y> = F.extension(y^2 - x^5 - 1)
|
|
sage: ksi = VectorBundle(K, K.places_finite()[0].divisor())
|
|
sage: ext = ksi.extension_group(ksi.dual()); ext.basis()
|
|
[[(x^9/(x^10 + 2*x^5 + 1))*y], [(x^3/(x^5 + 1))*y], [x^6/(x^5 + 1)]]
|
|
"""
|
|
self._compute_basis()
|
|
return self._basis
|
|
|
|
def _extension_from_ext_element(self, ext):
|
|
r"""
|
|
Return the extension of ``self.left() by ``self.right()`` encoded by
|
|
``ext``.
|
|
|
|
``ext`` is a matrix of elements of ``self._function_field`` which
|
|
represents the constant value over the infinite places of a répartition
|
|
matrix with support at infinity representing an element of
|
|
`H^1(\mathrm{hom}(\mathrm{left},\mathrm{right}))`.
|
|
Such an element encodes an extension `V`:
|
|
`0 \to \mathrm{other} \to V \to \mathrm{self} \to 0`
|
|
|
|
INPUT:
|
|
|
|
- ``ext`` -- a matrix of dimension ``right.rank(),left.rank()``
|
|
"""
|
|
from vector_bundle import VectorBundle
|
|
function_field = self._left._function_field
|
|
ideals = self._right._ideals + self._left._ideals
|
|
g_finite = block_matrix([[self._right._g_finite, 0],
|
|
[0, self._left._g_finite]])
|
|
g_infinite = block_matrix([[self._right._g_infinite,
|
|
-ext * self._left._g_infinite],
|
|
[0, self._left._g_infinite]])
|
|
return VectorBundle(function_field, ideals, g_finite, g_infinite)
|
|
|
|
def _extension_from_linear_form(self, form):
|
|
if self._basis is None:
|
|
ext = self._hom.h1_element(form)
|
|
ext = self._ext_dual_bundle._vector_to_matrix(ext).transpose()
|
|
else:
|
|
ext = sum([coeff * e for coeff, e in zip(form, self._basis)])
|
|
return self._extension_from_ext_element(ext)
|
|
|
|
def extension(self, ext=None):
|
|
r"""
|
|
Return the extension of ``self.left()`` by ``self.right()`` encoded by
|
|
``ext``.
|
|
|
|
``ext`` can be a matrix of elements of ``self._function_field``
|
|
which represents the constant value over the infinite places of a
|
|
répartition matrix with support at infinity representing an element of
|
|
`H^1(\mathrm{hom}(\mathrm{left},\mathrm{right}))`.
|
|
Such an element encodes an extension `V`:
|
|
`0 \to \mathrm{other} \to V \to \mathrm{self} \to 0`
|
|
|
|
``ext`` can also be a vector of length `self.dim()` representing an
|
|
extension in the basis of the Ext vector space.
|
|
|
|
By default, ``ext`` is chosen as any non trivial extension.
|
|
|
|
EXAMPLES ::
|
|
|
|
sage: from vector_bundle import VectorBundle, trivial_bundle
|
|
sage: F.<x> = FunctionField(GF(11))
|
|
sage: R.<y> = F[]
|
|
sage: K.<y> = F.extension(y^2 - x^3 - x)
|
|
sage: triv = trivial_bundle(K)
|
|
sage: ext = triv.extension_group(triv)
|
|
sage: V = ext.extension()
|
|
sage: V.rank()
|
|
2
|
|
sage: V.determinant() == triv
|
|
True
|
|
sage: V.h0()
|
|
[(1, 0)]
|
|
sage: V.end().h0()
|
|
[
|
|
[0 1] [1 0]
|
|
[0 0], [0 1]
|
|
]
|
|
"""
|
|
if ext is None:
|
|
ext = vector([1] + [0]*(self._s-1))
|
|
if is_Matrix(ext):
|
|
return self._extension_from_ext_element(ext)
|
|
else:
|
|
return self._extension_from_linear_form(ext)
|