Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
""" Helper Classes to implement Tensor Operations
.. warning::
This module is not meant to be used directly. It just provides functionality for other classes to implement tensor operations.
The :class:`VectorCollection` constructs the basis of tensor products (and symmetric/exterior powers) in terms of a chosen collection of vectors that generate the vector space(s).
EXAMPLES::
sage: from sage.modules.tensor_operations import VectorCollection, TensorOperation sage: V = VectorCollection([(1,0), (-1, 0), (1,2)], QQ, 2) sage: W = VectorCollection([(1,1), (1,-1), (-1, 1)], QQ, 2) sage: VW = TensorOperation([V, W], operation='product')
Here is the tensor product of two vectors::
sage: V.vectors()[0] (1, 0) sage: W.vectors()[1] (1, -1)
In a convenient choice of basis, the tensor product is $(a,b)\otimes(c,d)=(ac,ad,bc,bd)$. In this example, it is one of the vectors of the vector collection ``VW`` ::
sage: VW.index_map(0, 1) 1 sage: VW.vectors()[VW.index_map(0, 1)] (1, -1, 0, 0)
sage: rows = [] sage: for i, j in cartesian_product((range(3), range(3))): ....: v = V.vectors()[i] ....: w = W.vectors()[j] ....: i_tensor_j = VW.index_map(i, j) ....: vw = VW.vectors()[i_tensor_j] ....: rows.append([i, v, j, w, i_tensor_j, vw]) sage: table(rows) 0 (1, 0) 0 (1, 1) 0 (1, 1, 0, 0) 0 (1, 0) 1 (1, -1) 1 (1, -1, 0, 0) 0 (1, 0) 2 (-1, 1) 2 (-1, 1, 0, 0) 1 (-1, 0) 0 (1, 1) 3 (-1, -1, 0, 0) 1 (-1, 0) 1 (1, -1) 2 (-1, 1, 0, 0) 1 (-1, 0) 2 (-1, 1) 1 (1, -1, 0, 0) 2 (1, 2) 0 (1, 1) 4 (1, 1, 2, 2) 2 (1, 2) 1 (1, -1) 5 (1, -1, 2, -2) 2 (1, 2) 2 (-1, 1) 6 (-1, 1, -2, 2) """
#***************************************************************************** # Copyright (C) 2013 Volker Braun <vbraun.name@gmail.com> # # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # http://www.gnu.org/licenses/ #*****************************************************************************
""" Return formal symmetrized sum of multi-indices
INPUT:
- ``dim`` -- integer. The dimension (range of each index).
- ``n`` -- integer. The total number of indices.
OUTPUT:
A symmetrized formal sum of multi-indices (tuples of integers)
EXAMPLES::
sage: from sage.modules.tensor_operations import symmetrized_coordinate_sums sage: symmetrized_coordinate_sums(2, 2) ((0, 1) + (1, 0), (0, 0), (1, 1)) """
""" Return formal anti-symmetrized sum of multi-indices
INPUT:
- ``dim`` -- integer. The dimension (range of each index).
- ``n`` -- integer. The total number of indices.
OUTPUT:
An anti-symmetrized formal sum of multi-indices (tuples of integers)
EXAMPLES::
sage: from sage.modules.tensor_operations import antisymmetrized_coordinate_sums sage: antisymmetrized_coordinate_sums(3, 2) ((0, 1) - (1, 0), (0, 2) - (2, 0), (1, 2) - (2, 1)) """
""" An ordered collection of generators of a vector space.
This is like a list of vectors, but with extra argument checking.
.. warning::
This class is only used as a base class for filtered vector spaces. You should not use it yourself.
INPUT:
- ``dim`` -- integer. The dimension of the ambient vector space.
- ``base_ring`` -- a field. The base field of the ambient vector space.
- ``rays`` -- any list/iterable of things than can be converted into vectors of the ambient vector space. These will be used to span the subspaces of the filtration. Must span the ambient vector space.
EXAMPLES::
sage: from sage.modules.tensor_operations import VectorCollection sage: R = VectorCollection([(1,0), (0,1), (1,2)], QQ, 2); R Vector space of dimension 2 over Rational Field
TESTS::
sage: R.vectors() ((1, 0), (0, 1), (1, 2)) sage: r = R._vectors[0] sage: type(r) <type 'sage.modules.vector_rational_dense.Vector_rational_dense'> sage: r.parent() is R True sage: r.is_immutable() True """ """ EXAMPLES::
sage: from sage.modules.tensor_operations import VectorCollection sage: VectorCollection([(1,0), (4,1), (1,2)], QQ, 2) Vector space of dimension 2 over Rational Field """ raise ValueError('the vectors must span the ambient vector space')
""" Return the collection of vectors
OUTPUT:
A tuple of vectors. The vectors that were specified in the constructor, in the same order.
EXAMPLES::
sage: from sage.modules.tensor_operations import VectorCollection sage: V = VectorCollection([(1,0), (0,1), (1,2)], QQ, 2) sage: V.vectors() ((1, 0), (0, 1), (1, 2)) """
""" Return the number of vectors
OUTPUT:
Integer.
EXAMPLES::
sage: from sage.modules.tensor_operations import VectorCollection sage: V = VectorCollection([(1,0), (0,1), (1,2)], QQ, 2) sage: V.n_vectors() 3 """
""" Auxiliary class to compute the tensor product of two :class:`VectorCollection` objects.
.. warning::
This class is only used as a base class for filtered vector spaces. You should not use it yourself.
INPUT:
- ``vector_collections`` -- a nonempty list/tuple/iterable of :class:`VectorCollection` objects.
- ``operation`` -- string. The tensor operation. Currently allowed values are ``product``, ``symmetric``, and ``antisymmetric``.
.. todo::
More general tensor operations (specified by Young tableaux) should be implemented.
EXAMPLES::
sage: from sage.modules.tensor_operations import VectorCollection, TensorOperation sage: R = VectorCollection([(1,0), (1,2), (-1,-2)], QQ, 2) sage: S = VectorCollection([(1,), (-1,)], QQ, 1) sage: R_tensor_S = TensorOperation([R, S]) sage: R_tensor_S.index_map(0, 0) 0 sage: matrix(ZZ, 3, 2, lambda i,j: R_tensor_S.index_map(i, j)) [0 1] [2 3] [3 2] sage: R_tensor_S.vectors() ((1, 0), (-1, 0), (1, 2), (-1, -2)) """ """ EXAMPLES::
sage: from sage.modules.tensor_operations import VectorCollection, TensorOperation sage: R = VectorCollection([(1,0), (5,2), (-1,-2)], QQ, 2) sage: S = VectorCollection([(1,), (-1,)], QQ, 1) sage: TensorOperation([S, R]) Vector space of dimension 2 over Rational Field """ else: raise ValueError('invalid operation')
r""" Helper to build up ``self._vectors`` incrementally during the constructor.
INPUT:
- `i` -- list/tuple of integers. Multi-index of length equal to the number of constituent vector collections. The $j$-th entry $i[j]$ indexes a ray in the $j$-th vector collection. Hence, $i$ specifies one element in each vector collection.
OUTPUT:
This method mutates the :class:`TensorOperation` instance. In particular, the tensor product of the vectors of the vector collection is computed, and added to the elements of the tensor operation if it has not been encountered before.
The index of this tensor product vector is returned as an integer.
.. NOTE::
In a convenient choice of coordinates the tensor product of, say, two vectors $(a,b)$ and $(c,d)$, is $(ac, ad, bc, bd)$.
EXAMPLES::
sage: from sage.modules.tensor_operations import \ ....: VectorCollection, TensorOperation sage: R = VectorCollection([(1,0), (1,2), (-1,-2)], QQ, 2) sage: S = VectorCollection([(1,), (-1,)], QQ, 1) sage: R_tensor_S = TensorOperation([R,S]) sage: R_tensor_S.index_map(1, 1) 3 sage: R_tensor_S.index_map(2, 0) 3 sage: R_tensor_S.vectors() # indirect doctest ((1, 0), (-1, 0), (1, 2), (-1, -2)) """ # Pick out the i[j]-th vector # Note: convert to list, as cartesian_product of vectors is unrelated # Use index of pre-existing tensor product vector if there is one
""" Helper to build up ``self._vectors`` incrementally during the constructor.
INPUT:
- `i` -- list/tuple of integers. Specifies one element (vector) in each vector collection as in :meth:`_init_product_vector`.
- ``linear_combination`` -- formal linear combination of vector indices in the vectors specified by $i$.
EXAMPLES::
sage: from sage.modules.tensor_operations import \ ....: VectorCollection, TensorOperation sage: R = VectorCollection([(1,0), (1,2), (-1,-2)], QQ, 2) sage: Sym2_R = TensorOperation([R,R], operation='symmetric') sage: Sym2_R.vectors() # indirect doctest ((0, 1, 0), (2, 1, 0), (-2, -1, 0), (4, 1, 4), (-4, -1, -4)) sage: Alt2_R = TensorOperation([R, R], operation='antisymmetric') sage: Alt2_R.vectors() # indirect doctest ((2), (-2)) """
""" Initialization for the tensor product
EXAMPLES::
sage: from sage.modules.tensor_operations import \ ....: VectorCollection, TensorOperation sage: R = VectorCollection([(1,0), (1,2), (-1,-2)], QQ, 2) sage: S = VectorCollection([(1,), (-1,)], QQ, 1) sage: R_tensor_S = TensorOperation([R,S], operation='product') sage: sorted(R_tensor_S._index_map.items()) # indirect doctest [((0, 0), 0), ((0, 1), 1), ((1, 0), 2), ((1, 1), 3), ((2, 0), 3), ((2, 1), 2)] """
""" Initialization for the symmetric product.
EXAMPLES::
sage: from sage.modules.tensor_operations import \ ....: VectorCollection, TensorOperation sage: R = VectorCollection([(1,0), (1,2), (-1,-2)], QQ, 2) sage: Sym2_R = TensorOperation([R,R], operation='symmetric') # indirect doctest sage: sorted(Sym2_R._index_map.items()) [((0, 0), 0), ((0, 1), 1), ((0, 2), 2), ((1, 1), 3), ((1, 2), 4), ((2, 2), 3)] """
""" Initialization for the antisymmetric product
EXAMPLES::
sage: from sage.modules.tensor_operations import \ ....: VectorCollection, TensorOperation sage: R = VectorCollection([(1,0), (1,2), (-1,-2)], QQ, 2) sage: Alt2_R = TensorOperation([R, R], operation='antisymmetric') # indirect doctest sage: sorted(Alt2_R._index_map.items()) [((0, 1), 0), ((0, 2), 1)] """
""" Return the result of the tensor operation.
INPUT:
- ``*i`` -- list of integers. The indices (in the corresponding factor of the tensor operation) of the domain vector.
OUTPUT:
The index (in :meth:`vectors`) of the image of the tensor product/operation acting on the domain vectors indexed by `i`.
``None`` is returned if the tensor operation maps the generators to zero (usually because of antisymmetry).
EXAMPLES::
sage: from sage.modules.tensor_operations import \ ....: VectorCollection, TensorOperation sage: R = VectorCollection([(1,0), (1,2), (-1,-2)], QQ, 2) sage: Sym3_R = TensorOperation([R]*3, 'symmetric')
The symmetric product of the first vector ``(1,0)``, the second vector ``(1,2)``, and the third vector ``(-1,-2)`` equals the vector with index number 4 (that is, the fifth) in the symmetric product vector collection::
sage: Sym3_R.index_map(0, 1, 2) 4
In suitable coordinates, this is the vector::
sage: Sym3_R.vectors()[4] (-4, 0, -1, -4)
The product is symmetric::
sage: Sym3_R.index_map(2, 0, 1) 4 sage: Sym3_R.index_map(2, 1, 0) 4
As another example, here is the rank-2 determinant::
sage: from sage.modules.tensor_operations import \ ....: VectorCollection, TensorOperation sage: R = VectorCollection([(1,0), (0,1), (-2,-3)], QQ, 2) sage: detR = TensorOperation([R]*2, 'antisymmetric') sage: detR.index_map(1, 0) 0 sage: detR.index_map(0, 1) 0
TESTS::
sage: sorted(detR._index_map.items()) [((0, 1), 0), ((0, 2), 1), ((1, 2), 2)] sage: detR.vectors() ((1), (-3), (2)) """ i = tuple(i[0])
""" A choice of pre-image multi-indices.
OUTPUT:
A list of multi-indices (tuples of integers) whose image is the entire image under the :meth:`index_map`.
EXAMPLES::
sage: from sage.modules.tensor_operations import \ ....: VectorCollection, TensorOperation sage: R = VectorCollection([(1,0), (0,1), (-2,-3)], QQ, 2) sage: detR = TensorOperation([R]*2, 'antisymmetric') sage: sorted(detR.preimage()) [(0, 1), (0, 2), (1, 2)] sage: sorted(detR.codomain()) [0, 1, 2] """
""" The codomain of the index map.
OUTPUT:
A list of integers. The image of :meth:`index_map`.
EXAMPLES::
sage: from sage.modules.tensor_operations import \ ....: VectorCollection, TensorOperation sage: R = VectorCollection([(1,0), (0,1), (-2,-3)], QQ, 2) sage: detR = TensorOperation([R]*2, 'antisymmetric') sage: sorted(detR.preimage()) [(0, 1), (0, 2), (1, 2)] sage: sorted(detR.codomain()) [0, 1, 2] """ |