Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Merge #34424
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthias Koeppe committed Aug 26, 2022
2 parents dc7aad2 + 134c44f commit b7e5319
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 145 deletions.
8 changes: 5 additions & 3 deletions src/sage/manifolds/differentiable/tensorfield_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ class TensorFieldModule(UniqueRepresentation, Parent):
`T^{(2,0)}(M)` is not a free module::
sage: isinstance(T20, FiniteRankFreeModule)
sage: from sage.tensor.modules.finite_rank_free_module import FiniteRankFreeModule_abstract
sage: isinstance(T20, FiniteRankFreeModule_abstract)
False
because `M = S^2` is not parallelizable::
Expand All @@ -142,7 +143,7 @@ class TensorFieldModule(UniqueRepresentation, Parent):
free module, since `U` is parallelizable (being a coordinate domain)::
sage: T20U = U.tensor_field_module((2,0))
sage: isinstance(T20U, FiniteRankFreeModule)
sage: isinstance(T20U, FiniteRankFreeModule_abstract)
True
sage: U.is_manifestly_parallelizable()
True
Expand Down Expand Up @@ -658,7 +659,8 @@ class TensorFieldFreeModule(TensorFreeModule):
`T^{(2,0)}(\RR^3)` is a free module::
sage: isinstance(T20, FiniteRankFreeModule)
sage: from sage.tensor.modules.finite_rank_free_module import FiniteRankFreeModule_abstract
sage: isinstance(T20, FiniteRankFreeModule_abstract)
True
because `M = \RR^3` is parallelizable::
Expand Down
18 changes: 7 additions & 11 deletions src/sage/tensor/modules/ext_pow_free_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@
from sage.misc.cachefunc import cached_method
from sage.rings.integer import Integer
from sage.rings.integer_ring import ZZ
from sage.tensor.modules.finite_rank_free_module import FiniteRankFreeModule
from sage.tensor.modules.finite_rank_free_module import FiniteRankFreeModule_abstract
from sage.tensor.modules.free_module_tensor import FreeModuleTensor
from sage.tensor.modules.alternating_contr_tensor import AlternatingContrTensor
from sage.tensor.modules.free_module_alt_form import FreeModuleAltForm

class ExtPowerFreeModule(FiniteRankFreeModule):
class ExtPowerFreeModule(FiniteRankFreeModule_abstract):
r"""
Exterior power of a free module of finite rank over a commutative
ring.
Expand Down Expand Up @@ -247,10 +247,8 @@ def __init__(self, fmodule, degree, name=None, latex_name=None):
if latex_name is None and fmodule._latex_name is not None:
latex_name = r'\Lambda^{' + str(degree) + r'}\left(' \
+ fmodule._latex_name + r'\right)'
FiniteRankFreeModule.__init__(self, fmodule._ring, rank,
name=name, latex_name=latex_name,
start_index=fmodule._sindex,
output_formatter=fmodule._output_formatter)
super().__init__(fmodule._ring, rank,
name=name, latex_name=latex_name)
fmodule._all_modules.add(self)

#### Parent methods
Expand Down Expand Up @@ -431,7 +429,7 @@ def basis(self, *args, **kwds):
#***********************************************************************


class ExtPowerDualFreeModule(FiniteRankFreeModule):
class ExtPowerDualFreeModule(FiniteRankFreeModule_abstract):
r"""
Exterior power of the dual of a free module of finite rank
over a commutative ring.
Expand Down Expand Up @@ -652,10 +650,8 @@ def __init__(self, fmodule, degree, name=None, latex_name=None):
if latex_name is None and fmodule._latex_name is not None:
latex_name = r'\Lambda^{' + str(degree) + r'}\left(' \
+ fmodule._latex_name + r'^*\right)'
FiniteRankFreeModule.__init__(self, fmodule._ring, rank, name=name,
latex_name=latex_name,
start_index=fmodule._sindex,
output_formatter=fmodule._output_formatter)
super().__init__(fmodule._ring, rank, name=name,
latex_name=latex_name)
fmodule._all_modules.add(self)

#### Parent methods
Expand Down
282 changes: 157 additions & 125 deletions src/sage/tensor/modules/finite_rank_free_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,158 @@ class :class:`~sage.modules.free_module.FreeModule_generic`
from sage.tensor.modules.free_module_element import FiniteRankFreeModuleElement


class FiniteRankFreeModule(UniqueRepresentation, Parent):
class FiniteRankFreeModule_abstract(UniqueRepresentation, Parent):
r"""
Abstract base class for free modules of finite rank over a commutative ring.
"""

def __init__(
self,
ring,
rank,
name=None,
latex_name=None,
category=None,
ambient=None,
):
r"""
See :class:`FiniteRankFreeModule` for documentation and examples.
TESTS::
sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: TestSuite(M).run()
sage: e = M.basis('e')
sage: TestSuite(M).run()
sage: f = M.basis('f')
sage: TestSuite(M).run()
"""
# This duplicates the normalization done in __classcall_private__,
# but it is needed for various subclasses.
if ring not in Rings().Commutative():
raise TypeError("the module base ring must be commutative")
category = Modules(ring).FiniteDimensional().or_subcategory(category)
Parent.__init__(self, base=ring, category=category)
self._ring = ring # same as self._base
if ambient is None:
self._ambient_module = self
else:
self._ambient_module = ambient
self._rank = rank
self._name = name
# This duplicates the normalization done in __classcall_private__,
# but it is needed for various subclasses.
if latex_name is None:
self._latex_name = self._name
else:
self._latex_name = latex_name

def _latex_(self):
r"""
LaTeX representation of ``self``.
EXAMPLES::
sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: M._latex_()
'M'
sage: latex(M)
M
sage: M1 = FiniteRankFreeModule(ZZ, 3, name='M', latex_name=r'\mathcal{M}')
sage: M1._latex_()
'\\mathcal{M}'
sage: latex(M1)
\mathcal{M}
"""
if self._latex_name is None:
return r'\mbox{' + str(self) + r'}'
else:
return self._latex_name

def rank(self) -> int:
r"""
Return the rank of the free module ``self``.
Since the ring over which ``self`` is built is assumed to be
commutative (and hence has the invariant basis number property), the
rank is defined uniquely, as the cardinality of any basis of ``self``.
EXAMPLES:
Rank of free modules over `\ZZ`::
sage: M = FiniteRankFreeModule(ZZ, 3)
sage: M.rank()
3
sage: M.tensor_module(0,1).rank()
3
sage: M.tensor_module(0,2).rank()
9
sage: M.tensor_module(1,0).rank()
3
sage: M.tensor_module(1,1).rank()
9
sage: M.tensor_module(1,2).rank()
27
sage: M.tensor_module(2,2).rank()
81
"""
return self._rank

@cached_method
def zero(self):
r"""
Return the zero element of ``self``.
EXAMPLES:
Zero elements of free modules over `\ZZ`::
sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: M.zero()
Element zero of the Rank-3 free module M over the Integer Ring
sage: M.zero().parent() is M
True
sage: M.zero() is M(0)
True
sage: T = M.tensor_module(1,1)
sage: T.zero()
Type-(1,1) tensor zero on the Rank-3 free module M over the Integer Ring
sage: T.zero().parent() is T
True
sage: T.zero() is T(0)
True
Components of the zero element with respect to some basis::
sage: e = M.basis('e')
sage: M.zero()[e,:]
[0, 0, 0]
sage: all(M.zero()[e,i] == M.base_ring().zero() for i in M.irange())
True
sage: T.zero()[e,:]
[0 0 0]
[0 0 0]
[0 0 0]
sage: M.tensor_module(1,2).zero()[e,:]
[[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]]
"""
resu = self._element_constructor_(name='zero', latex_name='0')
for basis in self._known_bases:
resu._add_comp_unsafe(basis)
# (since new components are initialized to zero)
resu._is_zero = True # This element is certainly zero
resu.set_immutable()
return resu


class FiniteRankFreeModule(FiniteRankFreeModule_abstract):
r"""
Free module of finite rank over a commutative ring.
Expand Down Expand Up @@ -780,7 +931,7 @@ def __classcall_private__(cls, ring, rank, name=None, latex_name=None, start_ind
if latex_name is None:
latex_name = name
return super(FiniteRankFreeModule, cls).__classcall__(
cls, ring, rank, name, latex_name, start_index, output_formatter, category)
cls, ring, rank, name, latex_name, start_index, output_formatter, category, ambient)

def __init__(
self,
Expand All @@ -806,25 +957,8 @@ def __init__(
sage: TestSuite(M).run()
"""
# This duplicates the normalization done in __classcall_private__,
# but it is needed for various subclasses.
if ring not in Rings().Commutative():
raise TypeError("the module base ring must be commutative")
category = Modules(ring).FiniteDimensional().or_subcategory(category)
Parent.__init__(self, base=ring, category=category, facade=ambient)
self._ring = ring # same as self._base
if ambient is None:
self._ambient_module = self
else:
self._ambient_module = ambient
self._rank = rank
self._name = name
# This duplicates the normalization done in __classcall_private__,
# but it is needed for various subclasses.
if latex_name is None:
self._latex_name = self._name
else:
self._latex_name = latex_name
super().__init__(ring, rank, name=name, latex_name=latex_name,
category=category, ambient=ambient)
self._sindex = start_index
self._output_formatter = output_formatter
# Dictionary of the tensor modules built on self
Expand Down Expand Up @@ -2021,109 +2155,6 @@ def sym_bilinear_form(self, name=None, latex_name=None):

#### End of methods to be redefined by derived classes ####

def _latex_(self):
r"""
LaTeX representation of ``self``.
EXAMPLES::
sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: M._latex_()
'M'
sage: latex(M)
M
sage: M1 = FiniteRankFreeModule(ZZ, 3, name='M', latex_name=r'\mathcal{M}')
sage: M1._latex_()
'\\mathcal{M}'
sage: latex(M1)
\mathcal{M}
"""
if self._latex_name is None:
return r'\mbox{' + str(self) + r'}'
else:
return self._latex_name

def rank(self) -> int:
r"""
Return the rank of the free module ``self``.
Since the ring over which ``self`` is built is assumed to be
commutative (and hence has the invariant basis number property), the
rank is defined uniquely, as the cardinality of any basis of ``self``.
EXAMPLES:
Rank of free modules over `\ZZ`::
sage: M = FiniteRankFreeModule(ZZ, 3)
sage: M.rank()
3
sage: M.tensor_module(0,1).rank()
3
sage: M.tensor_module(0,2).rank()
9
sage: M.tensor_module(1,0).rank()
3
sage: M.tensor_module(1,1).rank()
9
sage: M.tensor_module(1,2).rank()
27
sage: M.tensor_module(2,2).rank()
81
"""
return self._rank

@cached_method
def zero(self):
r"""
Return the zero element of ``self``.
EXAMPLES:
Zero elements of free modules over `\ZZ`::
sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: M.zero()
Element zero of the Rank-3 free module M over the Integer Ring
sage: M.zero().parent() is M
True
sage: M.zero() is M(0)
True
sage: T = M.tensor_module(1,1)
sage: T.zero()
Type-(1,1) tensor zero on the Rank-3 free module M over the Integer Ring
sage: T.zero().parent() is T
True
sage: T.zero() is T(0)
True
Components of the zero element with respect to some basis::
sage: e = M.basis('e')
sage: M.zero()[e,:]
[0, 0, 0]
sage: all(M.zero()[e,i] == M.base_ring().zero() for i in M.irange())
True
sage: T.zero()[e,:]
[0 0 0]
[0 0 0]
[0 0 0]
sage: M.tensor_module(1,2).zero()[e,:]
[[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]]
"""
resu = self._element_constructor_(name='zero', latex_name='0')
for basis in self._known_bases:
resu._add_comp_unsafe(basis)
# (since new components are initialized to zero)
resu._is_zero = True # This element is certainly zero
resu.set_immutable()
return resu

def dual(self):
r"""
Return the dual module of ``self``.
Expand All @@ -2140,7 +2171,8 @@ def dual(self):
The dual is a free module of the same rank as M::
sage: isinstance(M.dual(), FiniteRankFreeModule)
sage: from sage.tensor.modules.finite_rank_free_module import FiniteRankFreeModule_abstract
sage: isinstance(M.dual(), FiniteRankFreeModule_abstract)
True
sage: M.dual().rank()
3
Expand Down
Loading

0 comments on commit b7e5319

Please sign in to comment.