Ticket #15305: trac_15305-coercion_tensor_products-ts.patch

File trac_15305-coercion_tensor_products-ts.patch, 4.5 KB (added by tscrim, 6 years ago)
  • sage/combinat/free_module.py

    # HG changeset patch
    # User Travis Scrimshaw <tscrim@ucdavis.edu>
    # Date 1382136349 25200
    # Node ID b047299615a43e8b054043ac0d542eb5ee0fd50b
    # Parent 2b8177c4c6bab273392ca1d7efdeac6e7f0a2a2c
    #15305: Implement the natural coercion induced from tensor factors.
    
    diff --git a/sage/combinat/free_module.py b/sage/combinat/free_module.py
    a b class CombinatorialFreeModule(UniqueRepr 
    14781478            sage: S = SymmetricFunctions(QQ)
    14791479            sage: s = S.s(); p = S.p()
    14801480            sage: ss = tensor([s,s]); pp = tensor([p,p])
    1481             sage: a = tensor((s[5],s[5]))
    1482             sage: pp(a) # used to yield p[[5]] # p[[5]]
    1483             Traceback (most recent call last):
    1484                ...
    1485             NotImplementedError
     1481            sage: a = tensor((s[2],s[2]))
     1482
     1483        The following originally used to yield ``p[[2]] # p[[2]]``, and if
     1484        there was no natural coercion between ``s`` and ``p``, this would
     1485        raise a ``NotImplementedError``. Since :trac:`15305`, this takes the
     1486        coercion between ``s`` and ``p`` and lifts it to the tensor product. ::
     1487
     1488            sage: pp(a)
     1489            1/4*p[1, 1] # p[1, 1] + 1/4*p[1, 1] # p[2] + 1/4*p[2] # p[1, 1] + 1/4*p[2] # p[2]
    14861490
    14871491        Extensions of the ground ring should probably be reintroduced
    14881492        at some point, but via coercions, and with stronger sanity
    class CombinatorialFreeModule_Tensor(Com 
    26432647            """
    26442648            return self.tensor_constructor(tuple(element.parent() for element in elements))(*elements)
    26452649
     2650        def _coerce_map_from_(self, R):
     2651            """
     2652            Return ``True`` if there is a coercion from ``R`` into ``self`` and
     2653            ``False`` otherwise.  The things that coerce into ``self`` are:
     2654
     2655            - Anything with a coercion into ``self.base_ring()``.
     2656
     2657            - A tensor algebra whose factors have a coercion into the
     2658              corresponding factors of ``self``.
     2659
     2660            TESTS::
     2661
     2662                sage: C = CombinatorialFreeModule(ZZ, ZZ)
     2663                sage: C2 = CombinatorialFreeModule(ZZ, NN)
     2664                sage: M = C.module_morphism(lambda x: C2.monomial(abs(x)), codomain=C2)
     2665                sage: M.register_as_coercion()
     2666                sage: C2(C.basis()[3])
     2667                B[3]
     2668                sage: C2(C.basis()[3] + C.basis()[-3])
     2669                2*B[3]
     2670                sage: S = C.tensor(C)
     2671                sage: S2 = C2.tensor(C2)
     2672                sage: S2.has_coerce_map_from(S)
     2673                True
     2674                sage: S.has_coerce_map_from(S2)
     2675                False
     2676                sage: S.an_element()
     2677                3*B[0] # B[-1] + 2*B[0] # B[0] + 2*B[0] # B[1]
     2678                sage: S2(S.an_element())
     2679                2*B[0] # B[0] + 5*B[0] # B[1]
     2680
     2681            ::
     2682
     2683                sage: C = CombinatorialFreeModule(ZZ, Set([1,2])) 
     2684                sage: D = CombinatorialFreeModule(ZZ, Set([2,4])) 
     2685                sage: f = C.module_morphism(on_basis=lambda x: D.monomial(2*x), codomain=D)
     2686                sage: f.register_as_coercion()
     2687                sage: T = tensor((C,C))
     2688                sage: p = D.an_element()
     2689                sage: T(tensor((p,p)))
     2690                Traceback (most recent call last):
     2691                ...
     2692                NotImplementedError
     2693                sage: T = tensor((D,D))
     2694                sage: p = C.an_element()
     2695                sage: T(tensor((p,p)))
     2696                4*B[2] # B[2] + 4*B[2] # B[4] + 4*B[4] # B[2] + 4*B[4] # B[4]
     2697            """
     2698            if R in ModulesWithBasis(self.base_ring()).TensorProducts() \
     2699                    and isinstance(R, CombinatorialFreeModule_Tensor) \
     2700                    and len(R._sets) == len(self._sets) \
     2701                    and all(self._sets[i].has_coerce_map_from(M)
     2702                            for i,M in enumerate(R._sets)):
     2703                modules = R._sets
     2704                vector_map = [self._sets[i].coerce_map_from(M)
     2705                              for i,M in enumerate(modules)]
     2706                return R.module_morphism(lambda x: self._tensor_of_elements(
     2707                        [vector_map[i](M.monomial(x[i]))
     2708                         for i,M in enumerate(modules)]),
     2709                                         codomain=self)
     2710
     2711            return super(CombinatorialFreeModule_Tensor, self)._coerce_map_from_(R)
     2712
    26462713class CartesianProductWithFlattening(object):
    26472714    """
    26482715    A class for cartesian product constructor, with partial flattening