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

Commit

Permalink
Merge branch 'public/categories/improve_submodules-19448' of trac.sag…
Browse files Browse the repository at this point in the history
…emath.org:sage into public/categories/improve_submodules-19448

Conflicts:
	src/sage/categories/modules_with_basis.py
	src/sage/modules/with_basis/subquotient.py
  • Loading branch information
Travis Scrimshaw committed Apr 29, 2016
2 parents 950f0f5 + 98dc756 commit 8006b8e
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 12 deletions.
33 changes: 31 additions & 2 deletions src/sage/categories/modules_with_basis.py
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,8 @@ def echelon_form(self, elements, row_reduced=False):
return [self.from_vector(vec) for vec in mat if vec]

def submodule(self, gens, check=True, already_echelonized=False,
unitriangular=False, category=None):
unitriangular=False, support_order=None, category=None,
*args, **opts):
r"""
The submodule spanned by a finite set of elements.
Expand All @@ -673,6 +674,10 @@ def submodule(self, gens, check=True, already_echelonized=False,
- ``unitrangular`` -- (default: ``False``) whether
the lift morphism is unitrangular
- ``support_order`` -- (optional) either an instance of class
with an ``index`` method (ex. a list), which returns an index
of an element in `\ZZ`, or a comparison function
If ``already_echelonized`` is ``False``, then the
generators are put in reduced echelon form using
:meth:`echelonize`, and reindexed by `0,1,...`.
Expand Down Expand Up @@ -801,17 +806,41 @@ def submodule(self, gens, check=True, already_echelonized=False,
[ 0 1]
[-1 -1]
We now construct a (finite-dimensional) submodule of an
infinite-dimensional free module. Due to current implementation
limitations, we must pass an echelonized basis::
sage: R.<a,b> = QQ[]
sage: C = CombinatorialFreeModule(R, range(3), prefix='x')
sage: x = C.basis()
sage: gens = [x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]]
sage: Y = C.submodule(gens, unitriangular=True)
sage: Y.lift.matrix()
[ 1 0]
[ 0 1]
[-1 -1]
TESTS::
sage: TestSuite(Y).run()
sage: TestSuite(center).run()
"""
if not already_echelonized:
gens = self.echelon_form(gens, unitriangular)
if support_order is None:
try:
support_order = self.get_order()
except NotImplementedError:
support_order = list(reduce( lambda x,y: x.union(y.support()),
gens, set() ))
elif not hasattr(support_order, 'index') and callable(support_order):
support_order = sorted(gens, cmp=support_order)

from sage.modules.with_basis.subquotient import SubmoduleWithBasis
return SubmoduleWithBasis(gens, ambient=self,
support_order=support_order,
unitriangular=unitriangular,
category=category)
category=category, *args, **opts)

def tensor(*parents):
"""
Expand Down
30 changes: 20 additions & 10 deletions src/sage/modules/with_basis/subquotient.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ class SubmoduleWithBasis(CombinatorialFreeModule):
:class:`module with basis <ModulesWithBasis>` `V`, or data that
can be converted into such a family
- ``support_order`` -- an ordering of the support of ``basis``
expressed in ``ambient``
- ``unitriangular`` -- if the lift morphism is unitriangular
- ``ambient`` -- the ambient space `V`
Expand All @@ -192,17 +195,17 @@ class SubmoduleWithBasis(CombinatorialFreeModule):
"""

@staticmethod
def __classcall_private__(cls, basis, ambient=None, unitriangular=False,
category=None, *args, **opts):
def __classcall_private__(cls, basis, support_order, ambient=None,
unitriangular=False, category=None, *args, **opts):
r"""
Normalize the input.
TESTS::
sage: from sage.modules.with_basis.subquotient import SubmoduleWithBasis
sage: X = CombinatorialFreeModule(QQ, range(3)); x = X.basis()
sage: Y1 = SubmoduleWithBasis((x[0]-x[1], x[1]-x[2]), X)
sage: Y2 = SubmoduleWithBasis([x[0]-x[1], x[1]-x[2]], X)
sage: Y1 = SubmoduleWithBasis((x[0]-x[1], x[1]-x[2]), [0,1,2], X)
sage: Y2 = SubmoduleWithBasis([x[0]-x[1], x[1]-x[2]], (0,1,2), X)
sage: Y1 is Y2
True
"""
Expand All @@ -211,10 +214,12 @@ def __classcall_private__(cls, basis, ambient=None, unitriangular=False,
ambient = basis.an_element().parent()
default_category = ModulesWithBasis(ambient.category().base_ring()).Subobjects()
category = default_category.or_subcategory(category, join=True)
return super(SubmoduleWithBasis, cls).__classcall__(
cls, basis, ambient, unitriangular, category, *args, **opts)
return super(SubmoduleWithBasis, cls).__classcall__(cls,
basis, tuple(support_order), ambient, unitriangular, category,
*args, **opts)

def __init__(self, basis, ambient, unitriangular, category):
def __init__(self, basis, support_order, ambient, unitriangular, category,
*args, **opts):
r"""
Initialization.
Expand All @@ -223,7 +228,7 @@ def __init__(self, basis, ambient, unitriangular, category):
sage: from sage.modules.with_basis.subquotient import SubmoduleWithBasis
sage: X = CombinatorialFreeModule(QQ, range(3), prefix="x"); x = X.basis()
sage: ybas = (x[0]-x[1], x[1]-x[2])
sage: Y = SubmoduleWithBasis(ybas, X)
sage: Y = SubmoduleWithBasis(ybas, [0, 1, 2], X)
sage: Y.print_options(prefix='y')
sage: Y.basis().list()
[y[0], y[1]]
Expand All @@ -234,11 +239,14 @@ def __init__(self, basis, ambient, unitriangular, category):
import operator
ring = ambient.base_ring()
CombinatorialFreeModule.__init__(self, ring, basis.keys(),
category=category.Subobjects())
category=category.Subobjects(),
*args, **opts)
self._ambient = ambient
self._basis = basis
self._unitriangular = unitriangular
self._support_order = support_order
self.lift_on_basis = self._basis.__getitem__
self.lift.register_as_coercion()

def ambient(self):
"""
Expand Down Expand Up @@ -271,11 +279,13 @@ def lift(self):
sage: (y[0] + y[1]).lift()
x[0] - x[2]
"""
support_cmp = lambda x,y: cmp(self._support_order.index(x),
self._support_order.index(y))
return self.module_morphism(self.lift_on_basis,
codomain=self.ambient(),
triangular="lower",
unitriangular=self._unitriangular,
cmp=self.ambient().get_order_cmp(),
cmp=support_cmp,
inverse_on_support="compute")

@lazy_attribute
Expand Down

0 comments on commit 8006b8e

Please sign in to comment.