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

Commit

Permalink
Add coercion map from a submodule to the free module
Browse files Browse the repository at this point in the history
  • Loading branch information
kwankyu committed Jun 9, 2022
1 parent b2870da commit fcb51da
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 3 deletions.
47 changes: 45 additions & 2 deletions src/sage/modules/free_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,49 @@ def __init__(self, base_ring, degree, sparse=False, category=None):
self.__degree = degree
self.__is_sparse = sparse

def _element_constructor_(self, x, coerce=True, copy=True, check=True):
r"""
Create an element of this module from ``x``.
The ``coerce`` and ``copy`` arguments are passed on to the underlying
element constructor.
EXAMPLES::
sage: S.<x,y,z> = PolynomialRing(QQ)
sage: M = S**2
sage: N = M.submodule([vector([x - y, z]), vector([y*z , x*z])])
sage: Q = M.quotient_module(N)
sage: Q(0)
(0, 0)
sage: Q([x, x + y])
(x, x + y)
sage: phi = Q.coerce_map_from(M)
sage: phi(M.gen(1))
(0, 1)
sage: _ in Q
True
"""
if isinstance(x, (int, sage.rings.integer.Integer)) and x == 0:
return self.zero_vector()
elif isinstance(x, free_module_element.FreeModuleElement):
if x.parent() is self:
if copy:
return x.__copy__()
else:
return x
x = x.list()
if check and self.coordinate_ring().is_exact():
# No check if x belongs to this module as there is no algorithm.
try:
R = self.base_ring()
for d in x:
if d not in R:
raise ArithmeticError
except ArithmeticError:
raise TypeError("element {!r} is not in free module".format(x))
return self.element_class(self, x, coerce, copy)

def degree(self):
"""
Return the degree of this free module. This is the dimension of the
Expand Down Expand Up @@ -5053,13 +5096,13 @@ def _coerce_map_from_(self, M):
sage: V.coerce_map_from(M)
"""
if isinstance(M, FreeModule_ambient):
if isinstance(M, FreeModule_base):
from sage.modules.quotient_module import FreeModule_ambient_field_quotient
if isinstance(M, FreeModule_ambient_field_quotient):
# No forgetful map.
return None
elif (self.base_ring().has_coerce_map_from(M.base_ring())
and self.rank() == M.rank()):
and self.degree() == M.degree()):
# We could return M.hom(self.basis(), self), but the
# complexity of this is quadratic in space and time,
# since it constructs a matrix.
Expand Down
31 changes: 30 additions & 1 deletion src/sage/modules/submodule.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,23 @@ class Submodule_ambient_domain(FreeModule_base):
sage: M = S**2
sage: N = M.submodule([vector([x - y, z]), vector([y * z, x * z])])
sage: N
Submodule of Ambient free module of rank 2 over the integral domain Multivariate Polynomial Ring in x, y, z over Rational Field
Submodule of Ambient free module of rank 2 over the integral domain
Multivariate Polynomial Ring in x, y, z over Rational Field
Generated by the rows of the matrix:
[x - y z]
[ y*z x*z]
::
sage: M.coerce_map_from(N)
Coercion map:
From: Submodule of Ambient free module of rank 2 over the integral domain
Multivariate Polynomial Ring in x, y, z over Rational Field
Generated by the rows of the matrix:
[x - y z]
[ y*z x*z]
To: Ambient free module of rank 2 over the integral domain
Multivariate Polynomial Ring in x, y, z over Rational Field
"""
def __init__(self, ambient, gens, check=True):
r"""
Expand Down Expand Up @@ -149,6 +162,22 @@ def gens(self):
"""
return self.__gens

def gen(self, i=0):
"""
Return the `i`-th generator of this module.
EXAMPLES::
sage: S.<x,y,z> = PolynomialRing(QQ)
sage: M = S**2
sage: N = M.submodule([vector([x - y, z]), vector([y*z, x*z])])
sage: N.gen(0)
(x - y, z)
"""
if i < 0 or i >= len(self.__gens):
raise ValueError('no generator with index %s' % i)
return self.__gens[i]

def is_submodule(self, other):
"""
Return ``True`` if this module is a submodule of the free module ``other``.
Expand Down

0 comments on commit fcb51da

Please sign in to comment.