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

Commit becb176

Browse files
author
Travis Scrimshaw
committed
Merge commit '4f3f1b8b' into public/categories/tensor_maps-15832
Conflicts: src/sage/categories/algebras_with_basis.py src/sage/categories/modules_with_basis.py src/sage/combinat/free_module.py
2 parents e55e315 + 4f3f1b8 commit becb176

File tree

4 files changed

+953
-55
lines changed

4 files changed

+953
-55
lines changed

src/sage/categories/algebras_with_basis.py

Lines changed: 129 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
from sage.misc.cachefunc import cached_method
1313
from sage.misc.lazy_attribute import lazy_attribute
14+
from sage.misc.abstract_method import abstract_method
15+
from sage.misc.constant_function import ConstantFunction
16+
from sage.misc.misc import compose
1417
from sage.misc.lazy_import import LazyImport
1518
from sage.categories.tensor import TensorProductsCategory, tensor
1619
from sage.categories.cartesian_product import CartesianProductsCategory
@@ -193,6 +196,91 @@ def _product_from_combinatorial_algebra_multiply(self,left,right):
193196
# tester.assert_(self.product is not None)
194197
# could check that self.product is in Hom( self x self, self)
195198

199+
def _product_on_basis_tuple(self, tup):
200+
return self.product_on_basis(*tup)
201+
202+
def _product_on_tensor_basis(self):
203+
r"""
204+
Return the function whose sole input is an index for the tensor square of ``self``,
205+
and whose output is the product of monomials indexed by the corresponding pair of basis elements.
206+
207+
EXAMPLES::
208+
209+
sage: W=WeylGroup("A2",prefix="s")
210+
sage: A = W.algebra(ZZ)
211+
sage: AA = tensor([A,A])
212+
sage: k = AA.basis().keys().an_element(); k
213+
(s1*s2*s1, s1*s2*s1)
214+
sage: A._product_on_tensor_basis()(k)
215+
B[1]
216+
sage: AAAA = tensor([AA,AA])
217+
sage: kk = AAAA.basis().keys().an_element(); kk
218+
(s1*s2*s1, s1*s2*s1, s1*s2*s1, s1*s2*s1)
219+
sage: AA._product_on_tensor_basis()(kk)
220+
B[1] # B[1]
221+
222+
"""
223+
# The algebra tensor product has functions which handle basis indices
224+
AA = tensor([self,self])
225+
return compose(self._product_on_basis_tuple, AA.index_to_indices())
226+
227+
def _product_morphism(self):
228+
r"""
229+
The multiplication map as a module morphism from the twofold tensor of ``self``, to ``self``.
230+
231+
EXAMPLES::
232+
233+
sage: W = WeylGroup(CartanType(['A',2]),prefix="s")
234+
sage: A = W.algebra(ZZ); A.rename("A")
235+
sage: mA = A._product_morphism(); mA
236+
Generic morphism:
237+
From: A # A
238+
To: A
239+
sage: a = A.monomial(W.from_reduced_word([1,2])); a
240+
B[s1*s2]
241+
sage: b = A.an_element(); b
242+
B[s1*s2*s1] + 3*B[s1*s2] + 3*B[s2*s1]
243+
sage: ab = tensor([a,b]); ab
244+
B[s1*s2] # B[s1*s2*s1] + 3*B[s1*s2] # B[s1*s2] + 3*B[s1*s2] # B[s2*s1]
245+
sage: mA(mA.domain()(ab))
246+
3*B[s2*s1] + B[s2] + 3*B[1]
247+
sage: a*b
248+
3*B[s2*s1] + B[s2] + 3*B[1]
249+
sage: AA = tensor([A,A])
250+
sage: mAA = AA._product_morphism()
251+
sage: mAA(mAA.domain()(tensor([a,b,b,b])))
252+
27*B[s2*s1] # B[s1*s2] + 27*B[s2*s1] # B[s2*s1] + 18*B[s2*s1] # B[s1] + 18*B[s2*s1] # B[s2] + 57*B[s2*s1] # B[1] + 9*B[s2] # B[s1*s2] + 9*B[s2] # B[s2*s1] + 6*B[s2] # B[s1] + 6*B[s2] # B[s2] + 19*B[s2] # B[1] + 27*B[1] # B[s1*s2] + 27*B[1] # B[s2*s1] + 18*B[1] # B[s1] + 18*B[1] # B[s2] + 57*B[1] # B[1]
253+
254+
"""
255+
from sage.categories.modules_with_basis import ModulesWithBasis
256+
module_category = ModulesWithBasis(self.base_ring())
257+
AA = tensor([self, self], category=module_category)
258+
return AA.module_morphism(on_basis=self._product_on_tensor_basis(), codomain=self, category=module_category)
259+
260+
def _unit_morphism(self):
261+
r"""
262+
The unit map as a module morphism from the base ring to ``self``.
263+
264+
Note that the domain is the tensor unit module,
265+
the base ring viewed as a free module.
266+
267+
EXAMPLES::
268+
269+
sage: W = WeylGroup(CartanType(['A',2]),prefix="s")
270+
sage: A = W.algebra(ZZ); A.rename("A")
271+
sage: unit = A._unit_morphism(); unit
272+
Generic morphism:
273+
From: The unit object in Category of tensor products of hopf algebras with basis over Integer Ring
274+
To: A
275+
sage: unit(3*unit.domain().one())
276+
3*B[1]
277+
278+
"""
279+
from sage.categories.modules_with_basis import ModulesWithBasis
280+
U = self.tensor_unit()
281+
one_func = ConstantFunction(self.one())
282+
return U.module_morphism(on_basis=one_func, codomain=self, category=ModulesWithBasis(self.base_ring()))
283+
196284
class ElementMethods:
197285

198286
def __invert__(self):
@@ -328,8 +416,41 @@ def extra_super_categories(self):
328416

329417
class ParentMethods:
330418
"""
331-
implements operations on tensor products of algebras with basis
419+
Implements operations on tensor products of algebras with basis.
332420
"""
421+
@abstract_method
422+
def factors(self):
423+
r"""
424+
The tensor factor algebras of `self`.
425+
426+
EXAMPLES::
427+
428+
sage: W = WeylGroup("A2",prefix="s")
429+
sage: A = W.algebra(ZZ); A.rename("A")
430+
sage: A2 = tensor([A,A])
431+
sage: A22 = tensor([A2,A2])
432+
sage: A22.factors()
433+
(A # A, A # A)
434+
sage: A4 = tensor([A,A,A,A])
435+
sage: A4.factors()
436+
(A, A, A, A)
437+
438+
"""
439+
pass
440+
441+
@abstract_method
442+
def index_to_indices(self):
443+
r"""
444+
The function which maps a basis index of ``self`` to a tuple of basis indices for ``self.factors()``.
445+
"""
446+
pass
447+
448+
@abstract_method
449+
def indices_to_index(self):
450+
r"""
451+
The function which maps a tuple of basis indices for ``self.factors()`` to an index of ``self.basis()``.
452+
"""
453+
pass
333454

334455
@cached_method
335456
def one_basis(self):
@@ -353,11 +474,11 @@ def one_basis(self):
353474
sage: B.one()
354475
B[word: ] # B[word: ] # B[word: ]
355476
"""
356-
# FIXME: this method should be conditionaly defined,
477+
# FIXME: this method should be conditionally defined,
357478
# so that B.one_basis returns NotImplemented if not
358479
# all modules provide one_basis
359-
if all(hasattr(module, "one_basis") for module in self._sets):
360-
return tuple(module.one_basis() for module in self._sets)
480+
if all(hasattr(module, "one_basis") for module in self.factors()):
481+
return self.indices_to_index()(*tuple(module.one_basis() for module in self.factors()))
361482
else:
362483
raise NotImplementedError
363484

@@ -386,10 +507,12 @@ def product_on_basis(self, t1, t2):
386507
sage: x*y
387508
B[word: a] # B[word: c] + B[word: ac] # B[word: ca] + 2*B[word: b] # B[word: c] + 2*B[word: bc] # B[word: ca]
388509
389-
390510
TODO: optimize this implementation!
511+
512+
FIX THIS EXAMPLE!!!
513+
391514
"""
392-
return tensor( (module.monomial(x1)*module.monomial(x2) for (module, x1, x2) in zip(self._sets, t1, t2)) ) #.
515+
return tensor( (module.monomial(x1)*module.monomial(x2) for (module, x1, x2) in zip(self.factors(), self.index_to_indices()(t1), self.index_to_indices()(t2)))) #.
393516

394517
class ElementMethods:
395518
"""

src/sage/categories/covariant_functorial_construction.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ def category_from_parents(self, parents):
140140
Category of tensor products of vector spaces with basis over Rational Field
141141
"""
142142
from sage.structure.parent import Parent
143-
assert(all(isinstance(parent, Parent) for parent in parents))
143+
if not all(isinstance(parent, Parent) for parent in parents):
144+
raise TypeError, "Not all items are parents"
144145
# Should we pass a set of categories to reduce the cache size?
145146
# But then this would impose that, for any constructor, the
146147
# category of the result does not depend on the order/repetition
@@ -170,7 +171,8 @@ def category_from_categories(self, categories):
170171
sage: cartesian_product.category_from_categories((Cat1, Cat2))
171172
Category of Cartesian products of monoids
172173
"""
173-
assert(len(categories) > 0)
174+
if not len(categories) > 0:
175+
raise ValueError, "There should be at least one category"
174176
return self.category_from_category(Category.meet(categories))
175177

176178
def category_from_category(self, category):
@@ -201,13 +203,14 @@ def _repr_(self):
201203
"""
202204
return "The %s functorial construction"%self._functor_name
203205

204-
def __call__(self, args):
206+
def __call__(self, args, **keywords):
205207
"""
206208
Functorial construction application
207209
208210
INPUT:
209211
- ``self``: a covariant functorial construction `F`
210212
- ``args``: a tuple (or iterable) of parents or elements
213+
- ``keywords``: a dictionary of keyword=value arguments
211214
212215
Returns `F(args)`
213216
@@ -216,11 +219,14 @@ def __call__(self, args):
216219
sage: E = CombinatorialFreeModule(QQ, ["a", "b", "c"]); E.rename("E")
217220
sage: tensor((E, E, E))
218221
E # E # E
222+
219223
"""
220224
args = tuple(args) # a bit brute force; let's see if this becomes a bottleneck later
221-
assert(all( hasattr(arg, self._functor_name) for arg in args))
222-
assert(len(args) > 0)
223-
return getattr(args[0], self._functor_name)(*args[1:])
225+
if not all(hasattr(arg, self._functor_name) for arg in args):
226+
raise TypeError, "Some item cannot apply the functor %s"%self._functor_name
227+
if not len(args) > 0:
228+
raise ValueError, "There should be at least one item"
229+
return getattr(args[0], self._functor_name)(*args[1:], **keywords)
224230

225231
class FunctorialConstructionCategory(Category): # Should this be CategoryWithBase?
226232
"""
@@ -421,7 +427,8 @@ def __init__(self, category, *args):
421427
sage: import __main__; __main__.FooBars = FooBars # Fake FooBars being defined in a python module
422428
sage: TestSuite(C).run()
423429
"""
424-
assert isinstance(category, Category)
430+
if not isinstance(category, Category):
431+
raise TypeError, "Should be a category"
425432
self._base_category = category
426433
self._args = args
427434
super(FunctorialConstructionCategory, self).__init__(*args)

0 commit comments

Comments
 (0)