Components as indexed sets of ring elements¶
The class Components is a technical class to take in charge the
storage and manipulation of indexed elements of a commutative ring that
represent the components of some “mathematical entity” with respect to some
“frame”. Examples of entity/frame are vector/vector-space basis or
vector field/vector frame on some manifold. More generally, the components
can be those of a tensor on a free module or those of a tensor field on a
manifold. They can also be non-tensorial quantities, like connection
coefficients or structure coefficients of a vector frame.
The individual components are assumed to belong to a given commutative ring and are labelled by indices, which are tuples of integers. The following operations are implemented on components with respect to a given frame:
- arithmetics (addition, subtraction, multiplication by a ring element) 
- handling of symmetries or antisymmetries on the indices 
- symmetrization and antisymmetrization 
- tensor product 
- contraction 
Various subclasses of class Components are
- CompWithSymfor components with symmetries or antisymmetries w.r.t. index permutations- CompFullySymfor fully symmetric components w.r.t. index permutations- KroneckerDeltafor the Kronecker delta symbol
 
- CompFullyAntiSymfor fully antisymmetric components w.r.t. index permutations
 
AUTHORS:
- Eric Gourgoulhon, Michal Bejger (2014-2015): initial version 
- Joris Vankerschaver (2010): for the idea of storing only the non-zero components as dictionaries, whose keys are the component indices (implemented in the old class - DifferentialForm; see Issue #24444)
- Marco Mancini (2015) : parallelization of some computations 
EXAMPLES:
Set of components with 2 indices on a 3-dimensional vector space, the frame being some basis of the vector space:
sage: from sage.tensor.modules.comp import Components
sage: V = VectorSpace(QQ,3)
sage: basis = V.basis() ; basis
[(1, 0, 0), (0, 1, 0), (0, 0, 1)]
sage: c = Components(QQ, basis, 2) ; c
2-indices components w.r.t. [
(1, 0, 0),
(0, 1, 0),
(0, 0, 1)
]
>>> from sage.all import *
>>> from sage.tensor.modules.comp import Components
>>> V = VectorSpace(QQ,Integer(3))
>>> basis = V.basis() ; basis
[(1, 0, 0), (0, 1, 0), (0, 0, 1)]
>>> c = Components(QQ, basis, Integer(2)) ; c
2-indices components w.r.t. [
(1, 0, 0),
(0, 1, 0),
(0, 0, 1)
]
Actually, the frame can be any object that has some length, i.e. on which
the function len() can be called:
sage: basis1 = V.gens() ; basis1
((1, 0, 0), (0, 1, 0), (0, 0, 1))
sage: c1 = Components(QQ, basis1, 2) ; c1
2-indices components w.r.t. ((1, 0, 0), (0, 1, 0), (0, 0, 1))
sage: basis2 = ['a', 'b' , 'c']
sage: c2 = Components(QQ, basis2, 2) ; c2
2-indices components w.r.t. ['a', 'b', 'c']
>>> from sage.all import *
>>> basis1 = V.gens() ; basis1
((1, 0, 0), (0, 1, 0), (0, 0, 1))
>>> c1 = Components(QQ, basis1, Integer(2)) ; c1
2-indices components w.r.t. ((1, 0, 0), (0, 1, 0), (0, 0, 1))
>>> basis2 = ['a', 'b' , 'c']
>>> c2 = Components(QQ, basis2, Integer(2)) ; c2
2-indices components w.r.t. ['a', 'b', 'c']
A just created set of components is initialized to zero:
sage: c.is_zero()
True
sage: c == 0
True
>>> from sage.all import *
>>> c.is_zero()
True
>>> c == Integer(0)
True
This can also be checked on the list of components, which is returned by
the operator [:]:
sage: c[:]
[0 0 0]
[0 0 0]
[0 0 0]
>>> from sage.all import *
>>> c[:]
[0 0 0]
[0 0 0]
[0 0 0]
Individual components are accessed by providing their indices inside square brackets:
sage: c[1,2] = -3
sage: c[:]
[ 0  0  0]
[ 0  0 -3]
[ 0  0  0]
sage: v = Components(QQ, basis, 1)
sage: v[:]
[0, 0, 0]
sage: v[0]
0
sage: v[:] = (-1,3,2)
sage: v[:]
[-1, 3, 2]
sage: v[0]
-1
>>> from sage.all import *
>>> c[Integer(1),Integer(2)] = -Integer(3)
>>> c[:]
[ 0  0  0]
[ 0  0 -3]
[ 0  0  0]
>>> v = Components(QQ, basis, Integer(1))
>>> v[:]
[0, 0, 0]
>>> v[Integer(0)]
0
>>> v[:] = (-Integer(1),Integer(3),Integer(2))
>>> v[:]
[-1, 3, 2]
>>> v[Integer(0)]
-1
Sets of components with 2 indices can be converted into a matrix:
sage: matrix(c)
[ 0  0  0]
[ 0  0 -3]
[ 0  0  0]
sage: matrix(c).parent()
Full MatrixSpace of 3 by 3 dense matrices over Rational Field
>>> from sage.all import *
>>> matrix(c)
[ 0  0  0]
[ 0  0 -3]
[ 0  0  0]
>>> matrix(c).parent()
Full MatrixSpace of 3 by 3 dense matrices over Rational Field
By default, the indices range from \(0\) to \(n-1\), where \(n\) is the length
of the frame. This can be changed via the argument start_index in
the Components constructor:
sage: v1 = Components(QQ, basis, 1, start_index=1)
sage: v1[:]
[0, 0, 0]
sage: v1[0]
Traceback (most recent call last):
...
IndexError: index out of range: 0 not in [1, 3]
sage: v1[1]
0
sage: v1[:] = v[:]  # list copy of all components
sage: v1[:]
[-1, 3, 2]
sage: v1[1], v1[2], v1[3]
(-1, 3, 2)
sage: v[0], v[1], v[2]
(-1, 3, 2)
>>> from sage.all import *
>>> v1 = Components(QQ, basis, Integer(1), start_index=Integer(1))
>>> v1[:]
[0, 0, 0]
>>> v1[Integer(0)]
Traceback (most recent call last):
...
IndexError: index out of range: 0 not in [1, 3]
>>> v1[Integer(1)]
0
>>> v1[:] = v[:]  # list copy of all components
>>> v1[:]
[-1, 3, 2]
>>> v1[Integer(1)], v1[Integer(2)], v1[Integer(3)]
(-1, 3, 2)
>>> v[Integer(0)], v[Integer(1)], v[Integer(2)]
(-1, 3, 2)
If some formatter function or unbound method is provided via the argument
output_formatter in the Components constructor, it is used to
change the output of the access operator [...]:
sage: a = Components(QQ, basis, 2, output_formatter=Rational.numerical_approx)
sage: a[1,2] = 1/3
sage: a[1,2]
0.333333333333333
>>> from sage.all import *
>>> a = Components(QQ, basis, Integer(2), output_formatter=Rational.numerical_approx)
>>> a[Integer(1),Integer(2)] = Integer(1)/Integer(3)
>>> a[Integer(1),Integer(2)]
0.333333333333333
The format can be passed to the formatter as the last argument of the
access operator [...]:
sage: a[1,2,10] # here the format is 10, for 10 bits of precision
0.33
sage: a[1,2,100]
0.33333333333333333333333333333
>>> from sage.all import *
>>> a[Integer(1),Integer(2),Integer(10)] # here the format is 10, for 10 bits of precision
0.33
>>> a[Integer(1),Integer(2),Integer(100)]
0.33333333333333333333333333333
The raw (unformatted) components are then accessed by the double bracket operator:
sage: a[[1,2]]
1/3
>>> from sage.all import *
>>> a[[Integer(1),Integer(2)]]
1/3
For sets of components declared without any output formatter, there is no
difference between [...] and [[...]]:
sage: c[1,2] = 1/3
sage: c[1,2], c[[1,2]]
(1/3, 1/3)
>>> from sage.all import *
>>> c[Integer(1),Integer(2)] = Integer(1)/Integer(3)
>>> c[Integer(1),Integer(2)], c[[Integer(1),Integer(2)]]
(1/3, 1/3)
The formatter is also used for the complete list of components:
sage: a[:]
[0.000000000000000 0.000000000000000 0.000000000000000]
[0.000000000000000 0.000000000000000 0.333333333333333]
[0.000000000000000 0.000000000000000 0.000000000000000]
sage: a[:,10] # with a format different from the default one (53 bits)
[0.00 0.00 0.00]
[0.00 0.00 0.33]
[0.00 0.00 0.00]
>>> from sage.all import *
>>> a[:]
[0.000000000000000 0.000000000000000 0.000000000000000]
[0.000000000000000 0.000000000000000 0.333333333333333]
[0.000000000000000 0.000000000000000 0.000000000000000]
>>> a[:,Integer(10)] # with a format different from the default one (53 bits)
[0.00 0.00 0.00]
[0.00 0.00 0.33]
[0.00 0.00 0.00]
The complete list of components in raw form can be recovered by the double
bracket operator, replacing : by slice(None) (since a[[:]]
generates a Python syntax error):
sage: a[[slice(None)]]
[  0   0   0]
[  0   0 1/3]
[  0   0   0]
>>> from sage.all import *
>>> a[[slice(None)]]
[  0   0   0]
[  0   0 1/3]
[  0   0   0]
Another example of formatter: the Python built-in function str()
to generate string outputs:
sage: b = Components(QQ, V.basis(), 1, output_formatter=str)
sage: b[:] = (1, 0, -4)
sage: b[:]
['1', '0', '-4']
>>> from sage.all import *
>>> b = Components(QQ, V.basis(), Integer(1), output_formatter=str)
>>> b[:] = (Integer(1), Integer(0), -Integer(4))
>>> b[:]
['1', '0', '-4']
For such a formatter, 2-indices components are no longer displayed as a matrix:
sage: b = Components(QQ, basis, 2, output_formatter=str)
sage: b[0,1] = 1/3
sage: b[:]
[['0', '1/3', '0'], ['0', '0', '0'], ['0', '0', '0']]
>>> from sage.all import *
>>> b = Components(QQ, basis, Integer(2), output_formatter=str)
>>> b[Integer(0),Integer(1)] = Integer(1)/Integer(3)
>>> b[:]
[['0', '1/3', '0'], ['0', '0', '0'], ['0', '0', '0']]
But unformatted outputs still are:
sage: b[[slice(None)]]
[  0 1/3   0]
[  0   0   0]
[  0   0   0]
>>> from sage.all import *
>>> b[[slice(None)]]
[  0 1/3   0]
[  0   0   0]
[  0   0   0]
Internally, the components are stored as a dictionary (_comp) whose
keys are the indices; only the nonzero components are stored:
sage: a[:]
[0.000000000000000 0.000000000000000 0.000000000000000]
[0.000000000000000 0.000000000000000 0.333333333333333]
[0.000000000000000 0.000000000000000 0.000000000000000]
sage: a._comp
{(1, 2): 1/3}
sage: v[:] = (-1, 0, 3)
sage: v._comp  # random output order of the component dictionary
{(0,): -1, (2,): 3}
>>> from sage.all import *
>>> a[:]
[0.000000000000000 0.000000000000000 0.000000000000000]
[0.000000000000000 0.000000000000000 0.333333333333333]
[0.000000000000000 0.000000000000000 0.000000000000000]
>>> a._comp
{(1, 2): 1/3}
>>> v[:] = (-Integer(1), Integer(0), Integer(3))
>>> v._comp  # random output order of the component dictionary
{(0,): -1, (2,): 3}
In case of symmetries, only non-redundant components are stored:
sage: from sage.tensor.modules.comp import CompFullyAntiSym
sage: c = CompFullyAntiSym(QQ, basis, 2)
sage: c[0,1] = 3
sage: c[:]
[ 0  3  0]
[-3  0  0]
[ 0  0  0]
sage: c._comp
{(0, 1): 3}
>>> from sage.all import *
>>> from sage.tensor.modules.comp import CompFullyAntiSym
>>> c = CompFullyAntiSym(QQ, basis, Integer(2))
>>> c[Integer(0),Integer(1)] = Integer(3)
>>> c[:]
[ 0  3  0]
[-3  0  0]
[ 0  0  0]
>>> c._comp
{(0, 1): 3}
- class sage.tensor.modules.comp.CompFullyAntiSym(ring, frame, nb_indices, start_index=0, output_formatter=None)[source]¶
- Bases: - CompWithSym- Indexed set of ring elements forming some components with respect to a given “frame” that are fully antisymmetric with respect to any permutation of the indices. - The “frame” can be a basis of some vector space or a vector frame on some manifold (i.e. a field of bases). The stored quantities can be tensor components or non-tensorial quantities. - INPUT: - ring– commutative ring in which each component takes its value
- frame– frame with respect to which the components are defined; whatever type- frameis, it should have some method- __len__()implemented, so that- len(frame)returns the dimension, i.e. the size of a single index range
- nb_indices– number of indices labeling the components
- start_index– (default: 0) first value of a single index; accordingly a component index i must obey- start_index <= i <= start_index + dim - 1, where- dim = len(frame).
- output_formatter– (default:- None) function or unbound method called to format the output of the component access operator- [...](method __getitem__);- output_formattermust take 1 or 2 arguments: the 1st argument must be an instance of- ringand the second one, if any, some format specification.
 - EXAMPLES: - Antisymmetric components with 2 indices on a 3-dimensional space: - sage: from sage.tensor.modules.comp import CompWithSym, CompFullyAntiSym sage: V = VectorSpace(QQ, 3) sage: c = CompFullyAntiSym(QQ, V.basis(), 2) sage: c[0,1], c[0,2], c[1,2] = 3, 1/2, -1 sage: c[:] # note that all components have been set according to the antisymmetry [ 0 3 1/2] [ -3 0 -1] [-1/2 1 0] - >>> from sage.all import * >>> from sage.tensor.modules.comp import CompWithSym, CompFullyAntiSym >>> V = VectorSpace(QQ, Integer(3)) >>> c = CompFullyAntiSym(QQ, V.basis(), Integer(2)) >>> c[Integer(0),Integer(1)], c[Integer(0),Integer(2)], c[Integer(1),Integer(2)] = Integer(3), Integer(1)/Integer(2), -Integer(1) >>> c[:] # note that all components have been set according to the antisymmetry [ 0 3 1/2] [ -3 0 -1] [-1/2 1 0] - Internally, only non-redundant and nonzero components are stored: - sage: c._comp # random output order of the component dictionary {(0, 1): 3, (0, 2): 1/2, (1, 2): -1} - >>> from sage.all import * >>> c._comp # random output order of the component dictionary {(0, 1): 3, (0, 2): 1/2, (1, 2): -1} - Same thing, but with the starting index set to 1: - sage: c1 = CompFullyAntiSym(QQ, V.basis(), 2, start_index=1) sage: c1[1,2], c1[1,3], c1[2,3] = 3, 1/2, -1 sage: c1[:] [ 0 3 1/2] [ -3 0 -1] [-1/2 1 0] - >>> from sage.all import * >>> c1 = CompFullyAntiSym(QQ, V.basis(), Integer(2), start_index=Integer(1)) >>> c1[Integer(1),Integer(2)], c1[Integer(1),Integer(3)], c1[Integer(2),Integer(3)] = Integer(3), Integer(1)/Integer(2), -Integer(1) >>> c1[:] [ 0 3 1/2] [ -3 0 -1] [-1/2 1 0] - The values stored in - cand- c1are equal:- sage: c1[:] == c[:] True - >>> from sage.all import * >>> c1[:] == c[:] True - but not - cand- c1, since their starting indices differ:- sage: c1 == c False - >>> from sage.all import * >>> c1 == c False - Fully antisymmetric components with 3 indices on a 3-dimensional space: - sage: a = CompFullyAntiSym(QQ, V.basis(), 3) sage: a[0,1,2] = 3 # the only independent component in dimension 3 sage: a[:] [[[0, 0, 0], [0, 0, 3], [0, -3, 0]], [[0, 0, -3], [0, 0, 0], [3, 0, 0]], [[0, 3, 0], [-3, 0, 0], [0, 0, 0]]] - >>> from sage.all import * >>> a = CompFullyAntiSym(QQ, V.basis(), Integer(3)) >>> a[Integer(0),Integer(1),Integer(2)] = Integer(3) # the only independent component in dimension 3 >>> a[:] [[[0, 0, 0], [0, 0, 3], [0, -3, 0]], [[0, 0, -3], [0, 0, 0], [3, 0, 0]], [[0, 3, 0], [-3, 0, 0], [0, 0, 0]]] - Setting a nonzero value incompatible with the antisymmetry results in an error: - sage: a[0,1,0] = 4 Traceback (most recent call last): ... ValueError: by antisymmetry, the component cannot have a nonzero value for the indices (0, 1, 0) sage: a[0,1,0] = 0 # OK sage: a[2,0,1] = 3 # OK - >>> from sage.all import * >>> a[Integer(0),Integer(1),Integer(0)] = Integer(4) Traceback (most recent call last): ... ValueError: by antisymmetry, the component cannot have a nonzero value for the indices (0, 1, 0) >>> a[Integer(0),Integer(1),Integer(0)] = Integer(0) # OK >>> a[Integer(2),Integer(0),Integer(1)] = Integer(3) # OK - The full antisymmetry is preserved by the arithmetics: - sage: b = CompFullyAntiSym(QQ, V.basis(), 3) sage: b[0,1,2] = -4 sage: s = a + 2*b ; s Fully antisymmetric 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: a[:], b[:], s[:] ([[[0, 0, 0], [0, 0, 3], [0, -3, 0]], [[0, 0, -3], [0, 0, 0], [3, 0, 0]], [[0, 3, 0], [-3, 0, 0], [0, 0, 0]]], [[[0, 0, 0], [0, 0, -4], [0, 4, 0]], [[0, 0, 4], [0, 0, 0], [-4, 0, 0]], [[0, -4, 0], [4, 0, 0], [0, 0, 0]]], [[[0, 0, 0], [0, 0, -5], [0, 5, 0]], [[0, 0, 5], [0, 0, 0], [-5, 0, 0]], [[0, -5, 0], [5, 0, 0], [0, 0, 0]]]) - >>> from sage.all import * >>> b = CompFullyAntiSym(QQ, V.basis(), Integer(3)) >>> b[Integer(0),Integer(1),Integer(2)] = -Integer(4) >>> s = a + Integer(2)*b ; s Fully antisymmetric 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> a[:], b[:], s[:] ([[[0, 0, 0], [0, 0, 3], [0, -3, 0]], [[0, 0, -3], [0, 0, 0], [3, 0, 0]], [[0, 3, 0], [-3, 0, 0], [0, 0, 0]]], [[[0, 0, 0], [0, 0, -4], [0, 4, 0]], [[0, 0, 4], [0, 0, 0], [-4, 0, 0]], [[0, -4, 0], [4, 0, 0], [0, 0, 0]]], [[[0, 0, 0], [0, 0, -5], [0, 5, 0]], [[0, 0, 5], [0, 0, 0], [-5, 0, 0]], [[0, -5, 0], [5, 0, 0], [0, 0, 0]]]) - It is lost if the added object is not fully antisymmetric: - sage: b1 = CompWithSym(QQ, V.basis(), 3, antisym=(0,1)) # b1 has only antisymmetry on index positions (0,1) sage: b1[0,1,2] = -4 sage: s = a + 2*b1 ; s # the result has the same symmetry as b1: 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 1) sage: a[:], b1[:], s[:] ([[[0, 0, 0], [0, 0, 3], [0, -3, 0]], [[0, 0, -3], [0, 0, 0], [3, 0, 0]], [[0, 3, 0], [-3, 0, 0], [0, 0, 0]]], [[[0, 0, 0], [0, 0, -4], [0, 0, 0]], [[0, 0, 4], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]], [[[0, 0, 0], [0, 0, -5], [0, -3, 0]], [[0, 0, 5], [0, 0, 0], [3, 0, 0]], [[0, 3, 0], [-3, 0, 0], [0, 0, 0]]]) sage: s = 2*b1 + a ; s 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 1) sage: 2*b1 + a == a + 2*b1 True - >>> from sage.all import * >>> b1 = CompWithSym(QQ, V.basis(), Integer(3), antisym=(Integer(0),Integer(1))) # b1 has only antisymmetry on index positions (0,1) >>> b1[Integer(0),Integer(1),Integer(2)] = -Integer(4) >>> s = a + Integer(2)*b1 ; s # the result has the same symmetry as b1: 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 1) >>> a[:], b1[:], s[:] ([[[0, 0, 0], [0, 0, 3], [0, -3, 0]], [[0, 0, -3], [0, 0, 0], [3, 0, 0]], [[0, 3, 0], [-3, 0, 0], [0, 0, 0]]], [[[0, 0, 0], [0, 0, -4], [0, 0, 0]], [[0, 0, 4], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]], [[[0, 0, 0], [0, 0, -5], [0, -3, 0]], [[0, 0, 5], [0, 0, 0], [3, 0, 0]], [[0, 3, 0], [-3, 0, 0], [0, 0, 0]]]) >>> s = Integer(2)*b1 + a ; s 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 1) >>> Integer(2)*b1 + a == a + Integer(2)*b1 True - interior_product(other)[source]¶
- Interior product with another set of fully antisymmetric components. - The interior product amounts to a contraction over all the \(p\) indices of - selfwith the first \(p\) indices of- other, assuming that the number \(q\) of indices of- otherobeys \(q\geq p\).- Note - self.interior_product(other)yields the same result as- self.contract(0,..., p-1, other, 0,..., p-1)(cf.- contract()), but- interior_productis more efficient, the antisymmetry of- selfbeing not used to reduce the computation in- contract().- INPUT: - other– fully antisymmetric components defined on the same frame as- selfand with a number of indices at least equal to that of- self
 - OUTPUT: - base ring element (case \(p=q\)) or set of components (case \(p<q\)) resulting from the contraction over all the \(p\) indices of - selfwith the first \(p\) indices of- other
 - EXAMPLES: - Interior product of a set of components - awith- pindices with a set of components- bwith- qindices on a 4-dimensional vector space.- Case - p=2and- q=2:- sage: from sage.tensor.modules.comp import CompFullyAntiSym sage: V = VectorSpace(QQ, 4) sage: a = CompFullyAntiSym(QQ, V.basis(), 2) sage: a[0,1], a[0,2], a[0,3] = -2, 4, 3 sage: a[1,2], a[1,3], a[2,3] = 5, -3, 1 sage: b = CompFullyAntiSym(QQ, V.basis(), 2) sage: b[0,1], b[0,2], b[0,3] = 3, -4, 2 sage: b[1,2], b[1,3], b[2,3] = 2, 5, 1 sage: c = a.interior_product(b) sage: c -40 sage: c == a.contract(0, 1, b, 0, 1) True - >>> from sage.all import * >>> from sage.tensor.modules.comp import CompFullyAntiSym >>> V = VectorSpace(QQ, Integer(4)) >>> a = CompFullyAntiSym(QQ, V.basis(), Integer(2)) >>> a[Integer(0),Integer(1)], a[Integer(0),Integer(2)], a[Integer(0),Integer(3)] = -Integer(2), Integer(4), Integer(3) >>> a[Integer(1),Integer(2)], a[Integer(1),Integer(3)], a[Integer(2),Integer(3)] = Integer(5), -Integer(3), Integer(1) >>> b = CompFullyAntiSym(QQ, V.basis(), Integer(2)) >>> b[Integer(0),Integer(1)], b[Integer(0),Integer(2)], b[Integer(0),Integer(3)] = Integer(3), -Integer(4), Integer(2) >>> b[Integer(1),Integer(2)], b[Integer(1),Integer(3)], b[Integer(2),Integer(3)] = Integer(2), Integer(5), Integer(1) >>> c = a.interior_product(b) >>> c -40 >>> c == a.contract(Integer(0), Integer(1), b, Integer(0), Integer(1)) True - Case - p=2and- q=3:- sage: b = CompFullyAntiSym(QQ, V.basis(), 3) sage: b[0,1,2], b[0,1,3], b[0,2,3], b[1,2,3] = 3, -4, 2, 5 sage: c = a.interior_product(b) sage: c[:] [58, 10, 6, 82] sage: c == a.contract(0, 1, b, 0, 1) True - >>> from sage.all import * >>> b = CompFullyAntiSym(QQ, V.basis(), Integer(3)) >>> b[Integer(0),Integer(1),Integer(2)], b[Integer(0),Integer(1),Integer(3)], b[Integer(0),Integer(2),Integer(3)], b[Integer(1),Integer(2),Integer(3)] = Integer(3), -Integer(4), Integer(2), Integer(5) >>> c = a.interior_product(b) >>> c[:] [58, 10, 6, 82] >>> c == a.contract(Integer(0), Integer(1), b, Integer(0), Integer(1)) True - Case - p=2and- q=4:- sage: b = CompFullyAntiSym(QQ, V.basis(), 4) sage: b[0,1,2,3] = 5 sage: c = a.interior_product(b) sage: c[:] [ 0 10 30 50] [-10 0 30 -40] [-30 -30 0 -20] [-50 40 20 0] sage: c == a.contract(0, 1, b, 0, 1) True - >>> from sage.all import * >>> b = CompFullyAntiSym(QQ, V.basis(), Integer(4)) >>> b[Integer(0),Integer(1),Integer(2),Integer(3)] = Integer(5) >>> c = a.interior_product(b) >>> c[:] [ 0 10 30 50] [-10 0 30 -40] [-30 -30 0 -20] [-50 40 20 0] >>> c == a.contract(Integer(0), Integer(1), b, Integer(0), Integer(1)) True - Case - p=3and- q=3:- sage: a = CompFullyAntiSym(QQ, V.basis(), 3) sage: a[0,1,2], a[0,1,3], a[0,2,3], a[1,2,3] = 2, -1, 3, 5 sage: b = CompFullyAntiSym(QQ, V.basis(), 3) sage: b[0,1,2], b[0,1,3], b[0,2,3], b[1,2,3] = -2, 1, 4, 2 sage: c = a.interior_product(b) sage: c 102 sage: c == a.contract(0, 1, 2, b, 0, 1, 2) True - >>> from sage.all import * >>> a = CompFullyAntiSym(QQ, V.basis(), Integer(3)) >>> a[Integer(0),Integer(1),Integer(2)], a[Integer(0),Integer(1),Integer(3)], a[Integer(0),Integer(2),Integer(3)], a[Integer(1),Integer(2),Integer(3)] = Integer(2), -Integer(1), Integer(3), Integer(5) >>> b = CompFullyAntiSym(QQ, V.basis(), Integer(3)) >>> b[Integer(0),Integer(1),Integer(2)], b[Integer(0),Integer(1),Integer(3)], b[Integer(0),Integer(2),Integer(3)], b[Integer(1),Integer(2),Integer(3)] = -Integer(2), Integer(1), Integer(4), Integer(2) >>> c = a.interior_product(b) >>> c 102 >>> c == a.contract(Integer(0), Integer(1), Integer(2), b, Integer(0), Integer(1), Integer(2)) True - Case - p=3and- q=4:- sage: b = CompFullyAntiSym(QQ, V.basis(), 4) sage: b[0,1,2,3] = 5 sage: c = a.interior_product(b) sage: c[:] [-150, 90, 30, 60] sage: c == a.contract(0, 1, 2, b, 0, 1, 2) True - >>> from sage.all import * >>> b = CompFullyAntiSym(QQ, V.basis(), Integer(4)) >>> b[Integer(0),Integer(1),Integer(2),Integer(3)] = Integer(5) >>> c = a.interior_product(b) >>> c[:] [-150, 90, 30, 60] >>> c == a.contract(Integer(0), Integer(1), Integer(2), b, Integer(0), Integer(1), Integer(2)) True - Case - p=4and- q=4:- sage: a = CompFullyAntiSym(QQ, V.basis(), 4) sage: a[0,1,2,3] = 3 sage: c = a.interior_product(b) sage: c 360 sage: c == a.contract(0, 1, 2, 3, b, 0, 1, 2, 3) True - >>> from sage.all import * >>> a = CompFullyAntiSym(QQ, V.basis(), Integer(4)) >>> a[Integer(0),Integer(1),Integer(2),Integer(3)] = Integer(3) >>> c = a.interior_product(b) >>> c 360 >>> c == a.contract(Integer(0), Integer(1), Integer(2), Integer(3), b, Integer(0), Integer(1), Integer(2), Integer(3)) True 
 
- class sage.tensor.modules.comp.CompFullySym(ring, frame, nb_indices, start_index=0, output_formatter=None)[source]¶
- Bases: - CompWithSym- Indexed set of ring elements forming some components with respect to a given “frame” that are fully symmetric with respect to any permutation of the indices. - The “frame” can be a basis of some vector space or a vector frame on some manifold (i.e. a field of bases). The stored quantities can be tensor components or non-tensorial quantities. - INPUT: - ring– commutative ring in which each component takes its value
- frame– frame with respect to which the components are defined; whatever type- frameis, it should have some method- __len__()implemented, so that- len(frame)returns the dimension, i.e. the size of a single index range
- nb_indices– number of indices labeling the components
- start_index– (default: 0) first value of a single index; accordingly a component index i must obey- start_index <= i <= start_index + dim - 1, where- dim = len(frame).
- output_formatter– (default:- None) function or unbound method called to format the output of the component access operator- [...](method __getitem__);- output_formattermust take 1 or 2 arguments: the 1st argument must be an instance of- ringand the second one, if any, some format specification.
 - EXAMPLES: - Symmetric components with 2 indices on a 3-dimensional space: - sage: from sage.tensor.modules.comp import CompFullySym, CompWithSym sage: V = VectorSpace(QQ, 3) sage: c = CompFullySym(QQ, V.basis(), 2) sage: c[0,0], c[0,1], c[1,2] = 1, -2, 3 sage: c[:] # note that c[1,0] and c[2,1] have been updated automatically (by symmetry) [ 1 -2 0] [-2 0 3] [ 0 3 0] - >>> from sage.all import * >>> from sage.tensor.modules.comp import CompFullySym, CompWithSym >>> V = VectorSpace(QQ, Integer(3)) >>> c = CompFullySym(QQ, V.basis(), Integer(2)) >>> c[Integer(0),Integer(0)], c[Integer(0),Integer(1)], c[Integer(1),Integer(2)] = Integer(1), -Integer(2), Integer(3) >>> c[:] # note that c[1,0] and c[2,1] have been updated automatically (by symmetry) [ 1 -2 0] [-2 0 3] [ 0 3 0] - Internally, only non-redundant and nonzero components are stored: - sage: c._comp # random output order of the component dictionary {(0, 0): 1, (0, 1): -2, (1, 2): 3} - >>> from sage.all import * >>> c._comp # random output order of the component dictionary {(0, 0): 1, (0, 1): -2, (1, 2): 3} - Same thing, but with the starting index set to 1: - sage: c1 = CompFullySym(QQ, V.basis(), 2, start_index=1) sage: c1[1,1], c1[1,2], c1[2,3] = 1, -2, 3 sage: c1[:] [ 1 -2 0] [-2 0 3] [ 0 3 0] - >>> from sage.all import * >>> c1 = CompFullySym(QQ, V.basis(), Integer(2), start_index=Integer(1)) >>> c1[Integer(1),Integer(1)], c1[Integer(1),Integer(2)], c1[Integer(2),Integer(3)] = Integer(1), -Integer(2), Integer(3) >>> c1[:] [ 1 -2 0] [-2 0 3] [ 0 3 0] - The values stored in - cand- c1are equal:- sage: c1[:] == c[:] True - >>> from sage.all import * >>> c1[:] == c[:] True - but not - cand- c1, since their starting indices differ:- sage: c1 == c False - >>> from sage.all import * >>> c1 == c False - Fully symmetric components with 3 indices on a 3-dimensional space: - sage: a = CompFullySym(QQ, V.basis(), 3) sage: a[0,1,2] = 3 sage: a[:] [[[0, 0, 0], [0, 0, 3], [0, 3, 0]], [[0, 0, 3], [0, 0, 0], [3, 0, 0]], [[0, 3, 0], [3, 0, 0], [0, 0, 0]]] sage: a[0,1,0] = 4 sage: a[:] [[[0, 4, 0], [4, 0, 3], [0, 3, 0]], [[4, 0, 3], [0, 0, 0], [3, 0, 0]], [[0, 3, 0], [3, 0, 0], [0, 0, 0]]] - >>> from sage.all import * >>> a = CompFullySym(QQ, V.basis(), Integer(3)) >>> a[Integer(0),Integer(1),Integer(2)] = Integer(3) >>> a[:] [[[0, 0, 0], [0, 0, 3], [0, 3, 0]], [[0, 0, 3], [0, 0, 0], [3, 0, 0]], [[0, 3, 0], [3, 0, 0], [0, 0, 0]]] >>> a[Integer(0),Integer(1),Integer(0)] = Integer(4) >>> a[:] [[[0, 4, 0], [4, 0, 3], [0, 3, 0]], [[4, 0, 3], [0, 0, 0], [3, 0, 0]], [[0, 3, 0], [3, 0, 0], [0, 0, 0]]] - The full symmetry is preserved by the arithmetics: - sage: b = CompFullySym(QQ, V.basis(), 3) sage: b[0,0,0], b[0,1,0], b[1,0,2], b[1,2,2] = -2, 3, 1, -5 sage: s = a + 2*b ; s Fully symmetric 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: a[:], b[:], s[:] ([[[0, 4, 0], [4, 0, 3], [0, 3, 0]], [[4, 0, 3], [0, 0, 0], [3, 0, 0]], [[0, 3, 0], [3, 0, 0], [0, 0, 0]]], [[[-2, 3, 0], [3, 0, 1], [0, 1, 0]], [[3, 0, 1], [0, 0, 0], [1, 0, -5]], [[0, 1, 0], [1, 0, -5], [0, -5, 0]]], [[[-4, 10, 0], [10, 0, 5], [0, 5, 0]], [[10, 0, 5], [0, 0, 0], [5, 0, -10]], [[0, 5, 0], [5, 0, -10], [0, -10, 0]]]) - >>> from sage.all import * >>> b = CompFullySym(QQ, V.basis(), Integer(3)) >>> b[Integer(0),Integer(0),Integer(0)], b[Integer(0),Integer(1),Integer(0)], b[Integer(1),Integer(0),Integer(2)], b[Integer(1),Integer(2),Integer(2)] = -Integer(2), Integer(3), Integer(1), -Integer(5) >>> s = a + Integer(2)*b ; s Fully symmetric 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> a[:], b[:], s[:] ([[[0, 4, 0], [4, 0, 3], [0, 3, 0]], [[4, 0, 3], [0, 0, 0], [3, 0, 0]], [[0, 3, 0], [3, 0, 0], [0, 0, 0]]], [[[-2, 3, 0], [3, 0, 1], [0, 1, 0]], [[3, 0, 1], [0, 0, 0], [1, 0, -5]], [[0, 1, 0], [1, 0, -5], [0, -5, 0]]], [[[-4, 10, 0], [10, 0, 5], [0, 5, 0]], [[10, 0, 5], [0, 0, 0], [5, 0, -10]], [[0, 5, 0], [5, 0, -10], [0, -10, 0]]]) - It is lost if the added object is not fully symmetric: - sage: b1 = CompWithSym(QQ, V.basis(), 3, sym=(0,1)) # b1 has only symmetry on index positions (0,1) sage: b1[0,0,0], b1[0,1,0], b1[1,0,2], b1[1,2,2] = -2, 3, 1, -5 sage: s = a + 2*b1 ; s # the result has the same symmetry as b1: 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1) sage: a[:], b1[:], s[:] ([[[0, 4, 0], [4, 0, 3], [0, 3, 0]], [[4, 0, 3], [0, 0, 0], [3, 0, 0]], [[0, 3, 0], [3, 0, 0], [0, 0, 0]]], [[[-2, 0, 0], [3, 0, 1], [0, 0, 0]], [[3, 0, 1], [0, 0, 0], [0, 0, -5]], [[0, 0, 0], [0, 0, -5], [0, 0, 0]]], [[[-4, 4, 0], [10, 0, 5], [0, 3, 0]], [[10, 0, 5], [0, 0, 0], [3, 0, -10]], [[0, 3, 0], [3, 0, -10], [0, 0, 0]]]) sage: s = 2*b1 + a ; s 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1) sage: 2*b1 + a == a + 2*b1 True - >>> from sage.all import * >>> b1 = CompWithSym(QQ, V.basis(), Integer(3), sym=(Integer(0),Integer(1))) # b1 has only symmetry on index positions (0,1) >>> b1[Integer(0),Integer(0),Integer(0)], b1[Integer(0),Integer(1),Integer(0)], b1[Integer(1),Integer(0),Integer(2)], b1[Integer(1),Integer(2),Integer(2)] = -Integer(2), Integer(3), Integer(1), -Integer(5) >>> s = a + Integer(2)*b1 ; s # the result has the same symmetry as b1: 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1) >>> a[:], b1[:], s[:] ([[[0, 4, 0], [4, 0, 3], [0, 3, 0]], [[4, 0, 3], [0, 0, 0], [3, 0, 0]], [[0, 3, 0], [3, 0, 0], [0, 0, 0]]], [[[-2, 0, 0], [3, 0, 1], [0, 0, 0]], [[3, 0, 1], [0, 0, 0], [0, 0, -5]], [[0, 0, 0], [0, 0, -5], [0, 0, 0]]], [[[-4, 4, 0], [10, 0, 5], [0, 3, 0]], [[10, 0, 5], [0, 0, 0], [3, 0, -10]], [[0, 3, 0], [3, 0, -10], [0, 0, 0]]]) >>> s = Integer(2)*b1 + a ; s 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1) >>> Integer(2)*b1 + a == a + Integer(2)*b1 True 
- class sage.tensor.modules.comp.CompWithSym(ring, frame, nb_indices, start_index=0, output_formatter=None, sym=None, antisym=None)[source]¶
- Bases: - Components- Indexed set of ring elements forming some components with respect to a given “frame”, with symmetries or antisymmetries regarding permutations of the indices. - The “frame” can be a basis of some vector space or a vector frame on some manifold (i.e. a field of bases). The stored quantities can be tensor components or non-tensorial quantities, such as connection coefficients or structure coefficients. - Subclasses of - CompWithSymare- CompFullySymfor fully symmetric components.
- CompFullyAntiSymfor fully antisymmetric components.
 - INPUT: - ring– commutative ring in which each component takes its value
- frame– frame with respect to which the components are defined; whatever type- frameis, it should have some method- __len__()implemented, so that- len(frame)returns the dimension, i.e. the size of a single index range
- nb_indices– number of indices labeling the components
- start_index– (default: 0) first value of a single index; accordingly a component index i must obey- start_index <= i <= start_index + dim - 1, where- dim = len(frame).
- output_formatter– (default:- None) function or unbound method called to format the output of the component access operator- [...](method __getitem__);- output_formattermust take 1 or 2 arguments: the 1st argument must be an instance of- ringand the second one, if any, some format specification.
- sym– (default:- None) a symmetry or a list of symmetries among the indices: each symmetry is described by a tuple containing the positions of the involved indices, with the convention- position=0for the first slot; for instance:- sym = (0, 1)for a symmetry between the 1st and 2nd indices
- sym = [(0,2), (1,3,4)]for a symmetry between the 1st and 3rd indices and a symmetry between the 2nd, 4th and 5th indices.
 
- antisym– (default:- None) antisymmetry or list of antisymmetries among the indices, with the same convention as for- sym
 - EXAMPLES: - Symmetric components with 2 indices: - sage: from sage.tensor.modules.comp import Components, CompWithSym sage: V = VectorSpace(QQ,3) sage: c = CompWithSym(QQ, V.basis(), 2, sym=(0,1)) # for demonstration only: it is preferable to use CompFullySym in this case sage: c[0,1] = 3 sage: c[:] # note that c[1,0] has been set automatically [0 3 0] [3 0 0] [0 0 0] - >>> from sage.all import * >>> from sage.tensor.modules.comp import Components, CompWithSym >>> V = VectorSpace(QQ,Integer(3)) >>> c = CompWithSym(QQ, V.basis(), Integer(2), sym=(Integer(0),Integer(1))) # for demonstration only: it is preferable to use CompFullySym in this case >>> c[Integer(0),Integer(1)] = Integer(3) >>> c[:] # note that c[1,0] has been set automatically [0 3 0] [3 0 0] [0 0 0] - Antisymmetric components with 2 indices: - sage: c = CompWithSym(QQ, V.basis(), 2, antisym=(0,1)) # for demonstration only: it is preferable to use CompFullyAntiSym in this case sage: c[0,1] = 3 sage: c[:] # note that c[1,0] has been set automatically [ 0 3 0] [-3 0 0] [ 0 0 0] - >>> from sage.all import * >>> c = CompWithSym(QQ, V.basis(), Integer(2), antisym=(Integer(0),Integer(1))) # for demonstration only: it is preferable to use CompFullyAntiSym in this case >>> c[Integer(0),Integer(1)] = Integer(3) >>> c[:] # note that c[1,0] has been set automatically [ 0 3 0] [-3 0 0] [ 0 0 0] - Internally, only non-redundant components are stored: - sage: c._comp {(0, 1): 3} - >>> from sage.all import * >>> c._comp {(0, 1): 3} - Components with 6 indices, symmetric among 3 indices (at position \((0, 1, 5)\)) and antisymmetric among 2 indices (at position \((2, 4)\)): - sage: c = CompWithSym(QQ, V.basis(), 6, sym=(0,1,5), antisym=(2,4)) sage: c[0,1,2,0,1,2] = 3 sage: c[1,0,2,0,1,2] # symmetry between indices in position 0 and 1 3 sage: c[2,1,2,0,1,0] # symmetry between indices in position 0 and 5 3 sage: c[0,2,2,0,1,1] # symmetry between indices in position 1 and 5 3 sage: c[0,1,1,0,2,2] # antisymmetry between indices in position 2 and 4 -3 - >>> from sage.all import * >>> c = CompWithSym(QQ, V.basis(), Integer(6), sym=(Integer(0),Integer(1),Integer(5)), antisym=(Integer(2),Integer(4))) >>> c[Integer(0),Integer(1),Integer(2),Integer(0),Integer(1),Integer(2)] = Integer(3) >>> c[Integer(1),Integer(0),Integer(2),Integer(0),Integer(1),Integer(2)] # symmetry between indices in position 0 and 1 3 >>> c[Integer(2),Integer(1),Integer(2),Integer(0),Integer(1),Integer(0)] # symmetry between indices in position 0 and 5 3 >>> c[Integer(0),Integer(2),Integer(2),Integer(0),Integer(1),Integer(1)] # symmetry between indices in position 1 and 5 3 >>> c[Integer(0),Integer(1),Integer(1),Integer(0),Integer(2),Integer(2)] # antisymmetry between indices in position 2 and 4 -3 - Components with 4 indices, antisymmetric with respect to the first pair of indices as well as with the second pair of indices: - sage: c = CompWithSym(QQ, V.basis(), 4, antisym=[(0,1),(2,3)]) sage: c[0,1,0,1] = 3 sage: c[1,0,0,1] # antisymmetry on the first pair of indices -3 sage: c[0,1,1,0] # antisymmetry on the second pair of indices -3 sage: c[1,0,1,0] # consequence of the above 3 - >>> from sage.all import * >>> c = CompWithSym(QQ, V.basis(), Integer(4), antisym=[(Integer(0),Integer(1)),(Integer(2),Integer(3))]) >>> c[Integer(0),Integer(1),Integer(0),Integer(1)] = Integer(3) >>> c[Integer(1),Integer(0),Integer(0),Integer(1)] # antisymmetry on the first pair of indices -3 >>> c[Integer(0),Integer(1),Integer(1),Integer(0)] # antisymmetry on the second pair of indices -3 >>> c[Integer(1),Integer(0),Integer(1),Integer(0)] # consequence of the above 3 - ARITHMETIC EXAMPLES - Addition of a symmetric set of components with a non-symmetric one: the symmetry is lost: - sage: V = VectorSpace(QQ, 3) sage: a = Components(QQ, V.basis(), 2) sage: a[:] = [[1,-2,3], [4,5,-6], [-7,8,9]] sage: b = CompWithSym(QQ, V.basis(), 2, sym=(0,1)) # for demonstration only: it is preferable to declare b = CompFullySym(QQ, V.basis(), 2) sage: b[0,0], b[0,1], b[0,2] = 1, 2, 3 sage: b[1,1], b[1,2] = 5, 7 sage: b[2,2] = 11 sage: s = a + b ; s 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: a[:], b[:], s[:] ( [ 1 -2 3] [ 1 2 3] [ 2 0 6] [ 4 5 -6] [ 2 5 7] [ 6 10 1] [-7 8 9], [ 3 7 11], [-4 15 20] ) sage: a + b == b + a True - >>> from sage.all import * >>> V = VectorSpace(QQ, Integer(3)) >>> a = Components(QQ, V.basis(), Integer(2)) >>> a[:] = [[Integer(1),-Integer(2),Integer(3)], [Integer(4),Integer(5),-Integer(6)], [-Integer(7),Integer(8),Integer(9)]] >>> b = CompWithSym(QQ, V.basis(), Integer(2), sym=(Integer(0),Integer(1))) # for demonstration only: it is preferable to declare b = CompFullySym(QQ, V.basis(), 2) >>> b[Integer(0),Integer(0)], b[Integer(0),Integer(1)], b[Integer(0),Integer(2)] = Integer(1), Integer(2), Integer(3) >>> b[Integer(1),Integer(1)], b[Integer(1),Integer(2)] = Integer(5), Integer(7) >>> b[Integer(2),Integer(2)] = Integer(11) >>> s = a + b ; s 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> a[:], b[:], s[:] ( [ 1 -2 3] [ 1 2 3] [ 2 0 6] [ 4 5 -6] [ 2 5 7] [ 6 10 1] [-7 8 9], [ 3 7 11], [-4 15 20] ) >>> a + b == b + a True - Addition of two symmetric set of components: the symmetry is preserved: - sage: c = CompWithSym(QQ, V.basis(), 2, sym=(0,1)) # for demonstration only: it is preferable to declare c = CompFullySym(QQ, V.basis(), 2) sage: c[0,0], c[0,1], c[0,2] = -4, 7, -8 sage: c[1,1], c[1,2] = 2, -4 sage: c[2,2] = 2 sage: s = b + c ; s 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1) sage: b[:], c[:], s[:] ( [ 1 2 3] [-4 7 -8] [-3 9 -5] [ 2 5 7] [ 7 2 -4] [ 9 7 3] [ 3 7 11], [-8 -4 2], [-5 3 13] ) sage: b + c == c + b True - >>> from sage.all import * >>> c = CompWithSym(QQ, V.basis(), Integer(2), sym=(Integer(0),Integer(1))) # for demonstration only: it is preferable to declare c = CompFullySym(QQ, V.basis(), 2) >>> c[Integer(0),Integer(0)], c[Integer(0),Integer(1)], c[Integer(0),Integer(2)] = -Integer(4), Integer(7), -Integer(8) >>> c[Integer(1),Integer(1)], c[Integer(1),Integer(2)] = Integer(2), -Integer(4) >>> c[Integer(2),Integer(2)] = Integer(2) >>> s = b + c ; s 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1) >>> b[:], c[:], s[:] ( [ 1 2 3] [-4 7 -8] [-3 9 -5] [ 2 5 7] [ 7 2 -4] [ 9 7 3] [ 3 7 11], [-8 -4 2], [-5 3 13] ) >>> b + c == c + b True - Check of the addition with counterparts not declared symmetric: - sage: bn = Components(QQ, V.basis(), 2) sage: bn[:] = b[:] sage: bn == b True sage: cn = Components(QQ, V.basis(), 2) sage: cn[:] = c[:] sage: cn == c True sage: bn + cn == b + c True - >>> from sage.all import * >>> bn = Components(QQ, V.basis(), Integer(2)) >>> bn[:] = b[:] >>> bn == b True >>> cn = Components(QQ, V.basis(), Integer(2)) >>> cn[:] = c[:] >>> cn == c True >>> bn + cn == b + c True - Addition of an antisymmetric set of components with a non-symmetric one: the antisymmetry is lost: - sage: d = CompWithSym(QQ, V.basis(), 2, antisym=(0,1)) # for demonstration only: it is preferable to declare d = CompFullyAntiSym(QQ, V.basis(), 2) sage: d[0,1], d[0,2], d[1,2] = 4, -1, 3 sage: s = a + d ; s 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: a[:], d[:], s[:] ( [ 1 -2 3] [ 0 4 -1] [ 1 2 2] [ 4 5 -6] [-4 0 3] [ 0 5 -3] [-7 8 9], [ 1 -3 0], [-6 5 9] ) sage: d + a == a + d True - >>> from sage.all import * >>> d = CompWithSym(QQ, V.basis(), Integer(2), antisym=(Integer(0),Integer(1))) # for demonstration only: it is preferable to declare d = CompFullyAntiSym(QQ, V.basis(), 2) >>> d[Integer(0),Integer(1)], d[Integer(0),Integer(2)], d[Integer(1),Integer(2)] = Integer(4), -Integer(1), Integer(3) >>> s = a + d ; s 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> a[:], d[:], s[:] ( [ 1 -2 3] [ 0 4 -1] [ 1 2 2] [ 4 5 -6] [-4 0 3] [ 0 5 -3] [-7 8 9], [ 1 -3 0], [-6 5 9] ) >>> d + a == a + d True - Addition of two antisymmetric set of components: the antisymmetry is preserved: - sage: e = CompWithSym(QQ, V.basis(), 2, antisym=(0,1)) # for demonstration only: it is preferable to declare e = CompFullyAntiSym(QQ, V.basis(), 2) sage: e[0,1], e[0,2], e[1,2] = 2, 3, -1 sage: s = d + e ; s 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 1) sage: d[:], e[:], s[:] ( [ 0 4 -1] [ 0 2 3] [ 0 6 2] [-4 0 3] [-2 0 -1] [-6 0 2] [ 1 -3 0], [-3 1 0], [-2 -2 0] ) sage: e + d == d + e True - >>> from sage.all import * >>> e = CompWithSym(QQ, V.basis(), Integer(2), antisym=(Integer(0),Integer(1))) # for demonstration only: it is preferable to declare e = CompFullyAntiSym(QQ, V.basis(), 2) >>> e[Integer(0),Integer(1)], e[Integer(0),Integer(2)], e[Integer(1),Integer(2)] = Integer(2), Integer(3), -Integer(1) >>> s = d + e ; s 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 1) >>> d[:], e[:], s[:] ( [ 0 4 -1] [ 0 2 3] [ 0 6 2] [-4 0 3] [-2 0 -1] [-6 0 2] [ 1 -3 0], [-3 1 0], [-2 -2 0] ) >>> e + d == d + e True - antisymmetrize(*pos)[source]¶
- Antisymmetrization over the given index positions. - INPUT: - pos– list of index positions involved in the antisymmetrization (with the convention- position=0for the first slot); if none, the antisymmetrization is performed over all the indices
 - OUTPUT: - an instance of - CompWithSymdescribing the antisymmetrized components
 - EXAMPLES: - Antisymmetrization of 3-indices components on a 3-dimensional space: - sage: from sage.tensor.modules.comp import Components, CompWithSym, \ ....: CompFullySym, CompFullyAntiSym sage: V = VectorSpace(QQ, 3) sage: a = Components(QQ, V.basis(), 1) sage: a[:] = (-2,1,3) sage: b = CompFullyAntiSym(QQ, V.basis(), 2) sage: b[0,1], b[0,2], b[1,2] = (4,1,2) sage: c = a*b ; c # tensor product of a by b 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (1, 2) sage: s = c.antisymmetrize() ; s Fully antisymmetric 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: c[:], s[:] ([[[0, -8, -2], [8, 0, -4], [2, 4, 0]], [[0, 4, 1], [-4, 0, 2], [-1, -2, 0]], [[0, 12, 3], [-12, 0, 6], [-3, -6, 0]]], [[[0, 0, 0], [0, 0, 7/3], [0, -7/3, 0]], [[0, 0, -7/3], [0, 0, 0], [7/3, 0, 0]], [[0, 7/3, 0], [-7/3, 0, 0], [0, 0, 0]]]) - >>> from sage.all import * >>> from sage.tensor.modules.comp import Components, CompWithSym, CompFullySym, CompFullyAntiSym >>> V = VectorSpace(QQ, Integer(3)) >>> a = Components(QQ, V.basis(), Integer(1)) >>> a[:] = (-Integer(2),Integer(1),Integer(3)) >>> b = CompFullyAntiSym(QQ, V.basis(), Integer(2)) >>> b[Integer(0),Integer(1)], b[Integer(0),Integer(2)], b[Integer(1),Integer(2)] = (Integer(4),Integer(1),Integer(2)) >>> c = a*b ; c # tensor product of a by b 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (1, 2) >>> s = c.antisymmetrize() ; s Fully antisymmetric 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> c[:], s[:] ([[[0, -8, -2], [8, 0, -4], [2, 4, 0]], [[0, 4, 1], [-4, 0, 2], [-1, -2, 0]], [[0, 12, 3], [-12, 0, 6], [-3, -6, 0]]], [[[0, 0, 0], [0, 0, 7/3], [0, -7/3, 0]], [[0, 0, -7/3], [0, 0, 0], [7/3, 0, 0]], [[0, 7/3, 0], [-7/3, 0, 0], [0, 0, 0]]]) - Check of the antisymmetrization: - sage: all(s[i,j,k] == (c[i,j,k]-c[i,k,j]+c[j,k,i]-c[j,i,k]+c[k,i,j]-c[k,j,i])/6 ....: for i in range(3) for j in range(3) for k in range(3)) True - >>> from sage.all import * >>> all(s[i,j,k] == (c[i,j,k]-c[i,k,j]+c[j,k,i]-c[j,i,k]+c[k,i,j]-c[k,j,i])/Integer(6) ... for i in range(Integer(3)) for j in range(Integer(3)) for k in range(Integer(3))) True - Antisymmetrization over already antisymmetric indices does not change anything: - sage: s1 = s.antisymmetrize(1,2) ; s1 Fully antisymmetric 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: s1 == s True sage: c1 = c.antisymmetrize(1,2) ; c1 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (1, 2) sage: c1 == c True - >>> from sage.all import * >>> s1 = s.antisymmetrize(Integer(1),Integer(2)) ; s1 Fully antisymmetric 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> s1 == s True >>> c1 = c.antisymmetrize(Integer(1),Integer(2)) ; c1 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (1, 2) >>> c1 == c True - But in general, antisymmetrization may alter previous antisymmetries: - sage: c2 = c.antisymmetrize(0,1) ; c2 # the antisymmetry (2,3) is lost: 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 1) sage: c2 == c False sage: c = s*a ; c 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 1, 2) sage: s = c.antisymmetrize(1,3) ; s 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 2), with antisymmetry on the index positions (1, 3) sage: s._antisym # the antisymmetry (0,1,2) has been reduced to (0,2), since 1 is involved in the new antisymmetry (1,3): ((0, 2), (1, 3)) - >>> from sage.all import * >>> c2 = c.antisymmetrize(Integer(0),Integer(1)) ; c2 # the antisymmetry (2,3) is lost: 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 1) >>> c2 == c False >>> c = s*a ; c 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 1, 2) >>> s = c.antisymmetrize(Integer(1),Integer(3)) ; s 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 2), with antisymmetry on the index positions (1, 3) >>> s._antisym # the antisymmetry (0,1,2) has been reduced to (0,2), since 1 is involved in the new antisymmetry (1,3): ((0, 2), (1, 3)) - Partial antisymmetrization of 4-indices components with a symmetry on the first two indices: - sage: a = CompFullySym(QQ, V.basis(), 2) sage: a[:] = [[-2,1,3], [1,0,-5], [3,-5,4]] sage: b = Components(QQ, V.basis(), 2) sage: b[:] = [[1,2,3], [5,7,11], [13,17,19]] sage: c = a*b ; c 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1) sage: s = c.antisymmetrize(2,3) ; s 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1), with antisymmetry on the index positions (2, 3) - >>> from sage.all import * >>> a = CompFullySym(QQ, V.basis(), Integer(2)) >>> a[:] = [[-Integer(2),Integer(1),Integer(3)], [Integer(1),Integer(0),-Integer(5)], [Integer(3),-Integer(5),Integer(4)]] >>> b = Components(QQ, V.basis(), Integer(2)) >>> b[:] = [[Integer(1),Integer(2),Integer(3)], [Integer(5),Integer(7),Integer(11)], [Integer(13),Integer(17),Integer(19)]] >>> c = a*b ; c 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1) >>> s = c.antisymmetrize(Integer(2),Integer(3)) ; s 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1), with antisymmetry on the index positions (2, 3) - Some check of the antisymmetrization: - sage: all(s[2,2,i,j] == (c[2,2,i,j] - c[2,2,j,i])/2 ....: for i in range(3) for j in range(i,3)) True - >>> from sage.all import * >>> all(s[Integer(2),Integer(2),i,j] == (c[Integer(2),Integer(2),i,j] - c[Integer(2),Integer(2),j,i])/Integer(2) ... for i in range(Integer(3)) for j in range(i,Integer(3))) True - The full antisymmetrization results in zero because of the symmetry on the first two indices: - sage: s = c.antisymmetrize() ; s Fully antisymmetric 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: s == 0 True - >>> from sage.all import * >>> s = c.antisymmetrize() ; s Fully antisymmetric 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> s == Integer(0) True - Similarly, the partial antisymmetrization on the first two indices results in zero: - sage: s = c.antisymmetrize(0,1) ; s 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 1) sage: s == 0 True - >>> from sage.all import * >>> s = c.antisymmetrize(Integer(0),Integer(1)) ; s 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 1) >>> s == Integer(0) True - The partial antisymmetrization on the positions \((0, 2)\) destroys the symmetry on \((0, 1)\): - sage: s = c.antisymmetrize(0,2) ; s 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 2) sage: s != 0 True sage: s[0,1,2,1] 27/2 sage: s[1,0,2,1] # the symmetry (0,1) is lost -2 sage: s[2,1,0,1] # the antisymmetry (0,2) holds -27/2 - >>> from sage.all import * >>> s = c.antisymmetrize(Integer(0),Integer(2)) ; s 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 2) >>> s != Integer(0) True >>> s[Integer(0),Integer(1),Integer(2),Integer(1)] 27/2 >>> s[Integer(1),Integer(0),Integer(2),Integer(1)] # the symmetry (0,1) is lost -2 >>> s[Integer(2),Integer(1),Integer(0),Integer(1)] # the antisymmetry (0,2) holds -27/2 
 - non_redundant_index_generator()[source]¶
- Generator of indices, with only ordered indices in case of symmetries, so that only non-redundant indices are generated. - OUTPUT: an iterable index - EXAMPLES: - Indices on a 2-dimensional space: - sage: from sage.tensor.modules.comp import Components, CompWithSym, \ ....: CompFullySym, CompFullyAntiSym sage: V = VectorSpace(QQ, 2) sage: c = CompFullySym(QQ, V.basis(), 2) sage: list(c.non_redundant_index_generator()) [(0, 0), (0, 1), (1, 1)] sage: c = CompFullySym(QQ, V.basis(), 2, start_index=1) sage: list(c.non_redundant_index_generator()) [(1, 1), (1, 2), (2, 2)] sage: c = CompFullyAntiSym(QQ, V.basis(), 2) sage: list(c.non_redundant_index_generator()) [(0, 1)] - >>> from sage.all import * >>> from sage.tensor.modules.comp import Components, CompWithSym, CompFullySym, CompFullyAntiSym >>> V = VectorSpace(QQ, Integer(2)) >>> c = CompFullySym(QQ, V.basis(), Integer(2)) >>> list(c.non_redundant_index_generator()) [(0, 0), (0, 1), (1, 1)] >>> c = CompFullySym(QQ, V.basis(), Integer(2), start_index=Integer(1)) >>> list(c.non_redundant_index_generator()) [(1, 1), (1, 2), (2, 2)] >>> c = CompFullyAntiSym(QQ, V.basis(), Integer(2)) >>> list(c.non_redundant_index_generator()) [(0, 1)] - Indices on a 3-dimensional space: - sage: V = VectorSpace(QQ, 3) sage: c = CompFullySym(QQ, V.basis(), 2) sage: list(c.non_redundant_index_generator()) [(0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2)] sage: c = CompFullySym(QQ, V.basis(), 2, start_index=1) sage: list(c.non_redundant_index_generator()) [(1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)] sage: c = CompFullyAntiSym(QQ, V.basis(), 2) sage: list(c.non_redundant_index_generator()) [(0, 1), (0, 2), (1, 2)] sage: c = CompWithSym(QQ, V.basis(), 3, sym=(1,2)) # symmetry on the last two indices sage: list(c.non_redundant_index_generator()) [(0, 0, 0), (1, 0, 0), (2, 0, 0), (0, 0, 1), (1, 0, 1), (2, 0, 1), (0, 0, 2), (1, 0, 2), (2, 0, 2), (0, 1, 1), (1, 1, 1), (2, 1, 1), (0, 1, 2), (1, 1, 2), (2, 1, 2), (0, 2, 2), (1, 2, 2), (2, 2, 2)] sage: c = CompWithSym(QQ, V.basis(), 3, antisym=(1,2)) # antisymmetry on the last two indices sage: list(c.non_redundant_index_generator()) [(0, 0, 1), (1, 0, 1), (2, 0, 1), (0, 0, 2), (1, 0, 2), (2, 0, 2), (0, 1, 2), (1, 1, 2), (2, 1, 2)] sage: c = CompFullySym(QQ, V.basis(), 3) sage: list(c.non_redundant_index_generator()) [(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 1, 1), (0, 1, 2), (0, 2, 2), (1, 1, 1), (1, 1, 2), (1, 2, 2), (2, 2, 2)] sage: c = CompFullyAntiSym(QQ, V.basis(), 3) sage: list(c.non_redundant_index_generator()) [(0, 1, 2)] - >>> from sage.all import * >>> V = VectorSpace(QQ, Integer(3)) >>> c = CompFullySym(QQ, V.basis(), Integer(2)) >>> list(c.non_redundant_index_generator()) [(0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2)] >>> c = CompFullySym(QQ, V.basis(), Integer(2), start_index=Integer(1)) >>> list(c.non_redundant_index_generator()) [(1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)] >>> c = CompFullyAntiSym(QQ, V.basis(), Integer(2)) >>> list(c.non_redundant_index_generator()) [(0, 1), (0, 2), (1, 2)] >>> c = CompWithSym(QQ, V.basis(), Integer(3), sym=(Integer(1),Integer(2))) # symmetry on the last two indices >>> list(c.non_redundant_index_generator()) [(0, 0, 0), (1, 0, 0), (2, 0, 0), (0, 0, 1), (1, 0, 1), (2, 0, 1), (0, 0, 2), (1, 0, 2), (2, 0, 2), (0, 1, 1), (1, 1, 1), (2, 1, 1), (0, 1, 2), (1, 1, 2), (2, 1, 2), (0, 2, 2), (1, 2, 2), (2, 2, 2)] >>> c = CompWithSym(QQ, V.basis(), Integer(3), antisym=(Integer(1),Integer(2))) # antisymmetry on the last two indices >>> list(c.non_redundant_index_generator()) [(0, 0, 1), (1, 0, 1), (2, 0, 1), (0, 0, 2), (1, 0, 2), (2, 0, 2), (0, 1, 2), (1, 1, 2), (2, 1, 2)] >>> c = CompFullySym(QQ, V.basis(), Integer(3)) >>> list(c.non_redundant_index_generator()) [(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 1, 1), (0, 1, 2), (0, 2, 2), (1, 1, 1), (1, 1, 2), (1, 2, 2), (2, 2, 2)] >>> c = CompFullyAntiSym(QQ, V.basis(), Integer(3)) >>> list(c.non_redundant_index_generator()) [(0, 1, 2)] - Indices on a 4-dimensional space: - sage: V = VectorSpace(QQ, 4) sage: c = Components(QQ, V.basis(), 1) sage: list(c.non_redundant_index_generator()) [(0,), (1,), (2,), (3,)] sage: c = CompFullyAntiSym(QQ, V.basis(), 2) sage: list(c.non_redundant_index_generator()) [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)] sage: c = CompFullyAntiSym(QQ, V.basis(), 3) sage: list(c.non_redundant_index_generator()) [(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)] sage: c = CompFullyAntiSym(QQ, V.basis(), 4) sage: list(c.non_redundant_index_generator()) [(0, 1, 2, 3)] sage: c = CompFullyAntiSym(QQ, V.basis(), 5) sage: list(c.non_redundant_index_generator()) # nothing since c is identically zero in this case (for 5 > 4) [] - >>> from sage.all import * >>> V = VectorSpace(QQ, Integer(4)) >>> c = Components(QQ, V.basis(), Integer(1)) >>> list(c.non_redundant_index_generator()) [(0,), (1,), (2,), (3,)] >>> c = CompFullyAntiSym(QQ, V.basis(), Integer(2)) >>> list(c.non_redundant_index_generator()) [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)] >>> c = CompFullyAntiSym(QQ, V.basis(), Integer(3)) >>> list(c.non_redundant_index_generator()) [(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)] >>> c = CompFullyAntiSym(QQ, V.basis(), Integer(4)) >>> list(c.non_redundant_index_generator()) [(0, 1, 2, 3)] >>> c = CompFullyAntiSym(QQ, V.basis(), Integer(5)) >>> list(c.non_redundant_index_generator()) # nothing since c is identically zero in this case (for 5 > 4) [] 
 - swap_adjacent_indices(pos1, pos2, pos3)[source]¶
- Swap two adjacent sets of indices. - This method is essentially required to reorder the covariant and contravariant indices in the computation of a tensor product. - The symmetries are preserved and the corresponding indices are adjusted consequently. - INPUT: - pos1– position of the first index of set 1 (with the convention position=0 for the first slot)
- pos2– position of the first index of set 2 = 1 + position of the last index of set 1 (since the two sets are adjacent)
- pos3– 1 + position of the last index of set 2
 - OUTPUT: components with index set 1 permuted with index set 2 - EXAMPLES: - Swap of the index in position 0 with the pair of indices in position (1,2) in a set of components antisymmetric with respect to the indices in position (1,2): - sage: from sage.tensor.modules.comp import CompWithSym sage: V = VectorSpace(QQ, 3) sage: c = CompWithSym(QQ, V.basis(), 3, antisym=(1,2)) sage: c[0,0,1], c[0,0,2], c[0,1,2] = (1,2,3) sage: c[1,0,1], c[1,0,2], c[1,1,2] = (4,5,6) sage: c[2,0,1], c[2,0,2], c[2,1,2] = (7,8,9) sage: c[:] [[[0, 1, 2], [-1, 0, 3], [-2, -3, 0]], [[0, 4, 5], [-4, 0, 6], [-5, -6, 0]], [[0, 7, 8], [-7, 0, 9], [-8, -9, 0]]] sage: c1 = c.swap_adjacent_indices(0,1,3) sage: c._antisym # c is antisymmetric with respect to the last pair of indices... ((1, 2),) sage: c1._antisym #...while c1 is antisymmetric with respect to the first pair of indices ((0, 1),) sage: c[0,1,2] 3 sage: c1[1,2,0] 3 sage: c1[2,1,0] -3 - >>> from sage.all import * >>> from sage.tensor.modules.comp import CompWithSym >>> V = VectorSpace(QQ, Integer(3)) >>> c = CompWithSym(QQ, V.basis(), Integer(3), antisym=(Integer(1),Integer(2))) >>> c[Integer(0),Integer(0),Integer(1)], c[Integer(0),Integer(0),Integer(2)], c[Integer(0),Integer(1),Integer(2)] = (Integer(1),Integer(2),Integer(3)) >>> c[Integer(1),Integer(0),Integer(1)], c[Integer(1),Integer(0),Integer(2)], c[Integer(1),Integer(1),Integer(2)] = (Integer(4),Integer(5),Integer(6)) >>> c[Integer(2),Integer(0),Integer(1)], c[Integer(2),Integer(0),Integer(2)], c[Integer(2),Integer(1),Integer(2)] = (Integer(7),Integer(8),Integer(9)) >>> c[:] [[[0, 1, 2], [-1, 0, 3], [-2, -3, 0]], [[0, 4, 5], [-4, 0, 6], [-5, -6, 0]], [[0, 7, 8], [-7, 0, 9], [-8, -9, 0]]] >>> c1 = c.swap_adjacent_indices(Integer(0),Integer(1),Integer(3)) >>> c._antisym # c is antisymmetric with respect to the last pair of indices... ((1, 2),) >>> c1._antisym #...while c1 is antisymmetric with respect to the first pair of indices ((0, 1),) >>> c[Integer(0),Integer(1),Integer(2)] 3 >>> c1[Integer(1),Integer(2),Integer(0)] 3 >>> c1[Integer(2),Integer(1),Integer(0)] -3 
 - symmetrize(*pos)[source]¶
- Symmetrization over the given index positions. - INPUT: - pos– list of index positions involved in the symmetrization (with the convention- position=0for the first slot); if none, the symmetrization is performed over all the indices
 - OUTPUT: - an instance of - CompWithSymdescribing the symmetrized components
 - EXAMPLES: - Symmetrization of 3-indices components on a 3-dimensional space: - sage: from sage.tensor.modules.comp import Components, CompWithSym, \ ....: CompFullySym, CompFullyAntiSym sage: V = VectorSpace(QQ, 3) sage: c = Components(QQ, V.basis(), 3) sage: c[:] = [[[1,2,3], [4,5,6], [7,8,9]], [[10,11,12], [13,14,15], [16,17,18]], [[19,20,21], [22,23,24], [25,26,27]]] sage: cs = c.symmetrize(0,1) ; cs 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1) sage: s = cs.symmetrize() ; s Fully symmetric 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: cs[:], s[:] ([[[1, 2, 3], [7, 8, 9], [13, 14, 15]], [[7, 8, 9], [13, 14, 15], [19, 20, 21]], [[13, 14, 15], [19, 20, 21], [25, 26, 27]]], [[[1, 16/3, 29/3], [16/3, 29/3, 14], [29/3, 14, 55/3]], [[16/3, 29/3, 14], [29/3, 14, 55/3], [14, 55/3, 68/3]], [[29/3, 14, 55/3], [14, 55/3, 68/3], [55/3, 68/3, 27]]]) sage: s == c.symmetrize() # should be true True sage: s1 = cs.symmetrize(0,1) ; s1 # should return a copy of cs 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1) sage: s1 == cs # check that s1 is a copy of cs True - >>> from sage.all import * >>> from sage.tensor.modules.comp import Components, CompWithSym, CompFullySym, CompFullyAntiSym >>> V = VectorSpace(QQ, Integer(3)) >>> c = Components(QQ, V.basis(), Integer(3)) >>> c[:] = [[[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9)]], [[Integer(10),Integer(11),Integer(12)], [Integer(13),Integer(14),Integer(15)], [Integer(16),Integer(17),Integer(18)]], [[Integer(19),Integer(20),Integer(21)], [Integer(22),Integer(23),Integer(24)], [Integer(25),Integer(26),Integer(27)]]] >>> cs = c.symmetrize(Integer(0),Integer(1)) ; cs 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1) >>> s = cs.symmetrize() ; s Fully symmetric 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> cs[:], s[:] ([[[1, 2, 3], [7, 8, 9], [13, 14, 15]], [[7, 8, 9], [13, 14, 15], [19, 20, 21]], [[13, 14, 15], [19, 20, 21], [25, 26, 27]]], [[[1, 16/3, 29/3], [16/3, 29/3, 14], [29/3, 14, 55/3]], [[16/3, 29/3, 14], [29/3, 14, 55/3], [14, 55/3, 68/3]], [[29/3, 14, 55/3], [14, 55/3, 68/3], [55/3, 68/3, 27]]]) >>> s == c.symmetrize() # should be true True >>> s1 = cs.symmetrize(Integer(0),Integer(1)) ; s1 # should return a copy of cs 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1) >>> s1 == cs # check that s1 is a copy of cs True - Let us now start with a symmetry on the last two indices: - sage: cs1 = c.symmetrize(1,2) ; cs1 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (1, 2) sage: s2 = cs1.symmetrize() ; s2 Fully symmetric 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: s2 == c.symmetrize() True - >>> from sage.all import * >>> cs1 = c.symmetrize(Integer(1),Integer(2)) ; cs1 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (1, 2) >>> s2 = cs1.symmetrize() ; s2 Fully symmetric 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> s2 == c.symmetrize() True - Symmetrization alters pre-existing symmetries: let us symmetrize w.r.t. the index positions \((1, 2)\) a set of components that is symmetric w.r.t. the index positions \((0, 1)\): - sage: cs = c.symmetrize(0,1) ; cs 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1) sage: css = cs.symmetrize(1,2) sage: css # the symmetry (0,1) has been lost: 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (1, 2) sage: css[:] [[[1, 9/2, 8], [9/2, 8, 23/2], [8, 23/2, 15]], [[7, 21/2, 14], [21/2, 14, 35/2], [14, 35/2, 21]], [[13, 33/2, 20], [33/2, 20, 47/2], [20, 47/2, 27]]] sage: cs[:] [[[1, 2, 3], [7, 8, 9], [13, 14, 15]], [[7, 8, 9], [13, 14, 15], [19, 20, 21]], [[13, 14, 15], [19, 20, 21], [25, 26, 27]]] sage: css == c.symmetrize() # css differs from the full symmetrized version False sage: css.symmetrize() == c.symmetrize() # one has to symmetrize css over all indices to recover it True - >>> from sage.all import * >>> cs = c.symmetrize(Integer(0),Integer(1)) ; cs 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1) >>> css = cs.symmetrize(Integer(1),Integer(2)) >>> css # the symmetry (0,1) has been lost: 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (1, 2) >>> css[:] [[[1, 9/2, 8], [9/2, 8, 23/2], [8, 23/2, 15]], [[7, 21/2, 14], [21/2, 14, 35/2], [14, 35/2, 21]], [[13, 33/2, 20], [33/2, 20, 47/2], [20, 47/2, 27]]] >>> cs[:] [[[1, 2, 3], [7, 8, 9], [13, 14, 15]], [[7, 8, 9], [13, 14, 15], [19, 20, 21]], [[13, 14, 15], [19, 20, 21], [25, 26, 27]]] >>> css == c.symmetrize() # css differs from the full symmetrized version False >>> css.symmetrize() == c.symmetrize() # one has to symmetrize css over all indices to recover it True - Another example of symmetry alteration: symmetrization over \((0, 1)\) of a 4-indices set of components that is symmetric w.r.t. \((1, 2, 3)\): - sage: v = Components(QQ, V.basis(), 1) sage: v[:] = (-2,1,4) sage: a = v*s ; a 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (1, 2, 3) sage: a1 = a.symmetrize(0,1) ; a1 # the symmetry (1,2,3) has been reduced to (2,3): 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1), with symmetry on the index positions (2, 3) sage: a1._sym # a1 has two distinct symmetries: ((0, 1), (2, 3)) sage: a[0,1,2,0] == a[0,0,2,1] # a is symmetric w.r.t. positions 1 and 3 True sage: a1[0,1,2,0] == a1[0,0,2,1] # a1 is not False sage: a1[0,1,2,0] == a1[1,0,2,0] # but it is symmetric w.r.t. position 0 and 1 True sage: a[0,1,2,0] == a[1,0,2,0] # while a is not False - >>> from sage.all import * >>> v = Components(QQ, V.basis(), Integer(1)) >>> v[:] = (-Integer(2),Integer(1),Integer(4)) >>> a = v*s ; a 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (1, 2, 3) >>> a1 = a.symmetrize(Integer(0),Integer(1)) ; a1 # the symmetry (1,2,3) has been reduced to (2,3): 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1), with symmetry on the index positions (2, 3) >>> a1._sym # a1 has two distinct symmetries: ((0, 1), (2, 3)) >>> a[Integer(0),Integer(1),Integer(2),Integer(0)] == a[Integer(0),Integer(0),Integer(2),Integer(1)] # a is symmetric w.r.t. positions 1 and 3 True >>> a1[Integer(0),Integer(1),Integer(2),Integer(0)] == a1[Integer(0),Integer(0),Integer(2),Integer(1)] # a1 is not False >>> a1[Integer(0),Integer(1),Integer(2),Integer(0)] == a1[Integer(1),Integer(0),Integer(2),Integer(0)] # but it is symmetric w.r.t. position 0 and 1 True >>> a[Integer(0),Integer(1),Integer(2),Integer(0)] == a[Integer(1),Integer(0),Integer(2),Integer(0)] # while a is not False - Partial symmetrization of 4-indices components with an antisymmetry on the last two indices: - sage: a = Components(QQ, V.basis(), 2) sage: a[:] = [[-1,2,3], [4,5,-6], [7,8,9]] sage: b = CompFullyAntiSym(QQ, V.basis(), 2) sage: b[0,1], b[0,2], b[1,2] = (2, 4, 8) sage: c = a*b ; c 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (2, 3) sage: s = c.symmetrize(0,1) ; s # symmetrization on the first two indices 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1), with antisymmetry on the index positions (2, 3) sage: s[0,1,2,1] == (c[0,1,2,1] + c[1,0,2,1]) / 2 # check of the symmetrization True sage: s = c.symmetrize() ; s # symmetrization over all the indices Fully symmetric 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: s == 0 # the full symmetrization results in zero due to the antisymmetry on the last two indices True sage: s = c.symmetrize(2,3) ; s 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (2, 3) sage: s == 0 # must be zero since the symmetrization has been performed on the antisymmetric indices True sage: s = c.symmetrize(0,2) ; s 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 2) sage: s != 0 # s is not zero, but the antisymmetry on (2,3) is lost because the position 2 is involved in the new symmetry True - >>> from sage.all import * >>> a = Components(QQ, V.basis(), Integer(2)) >>> a[:] = [[-Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),-Integer(6)], [Integer(7),Integer(8),Integer(9)]] >>> b = CompFullyAntiSym(QQ, V.basis(), Integer(2)) >>> b[Integer(0),Integer(1)], b[Integer(0),Integer(2)], b[Integer(1),Integer(2)] = (Integer(2), Integer(4), Integer(8)) >>> c = a*b ; c 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (2, 3) >>> s = c.symmetrize(Integer(0),Integer(1)) ; s # symmetrization on the first two indices 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1), with antisymmetry on the index positions (2, 3) >>> s[Integer(0),Integer(1),Integer(2),Integer(1)] == (c[Integer(0),Integer(1),Integer(2),Integer(1)] + c[Integer(1),Integer(0),Integer(2),Integer(1)]) / Integer(2) # check of the symmetrization True >>> s = c.symmetrize() ; s # symmetrization over all the indices Fully symmetric 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> s == Integer(0) # the full symmetrization results in zero due to the antisymmetry on the last two indices True >>> s = c.symmetrize(Integer(2),Integer(3)) ; s 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (2, 3) >>> s == Integer(0) # must be zero since the symmetrization has been performed on the antisymmetric indices True >>> s = c.symmetrize(Integer(0),Integer(2)) ; s 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 2) >>> s != Integer(0) # s is not zero, but the antisymmetry on (2,3) is lost because the position 2 is involved in the new symmetry True - Partial symmetrization of 4-indices components with an antisymmetry on the last three indices: - sage: a = Components(QQ, V.basis(), 1) sage: a[:] = (1, -2, 3) sage: b = CompFullyAntiSym(QQ, V.basis(), 3) sage: b[0,1,2] = 4 sage: c = a*b ; c 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (1, 2, 3) sage: s = c.symmetrize(0,1) ; s 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1), with antisymmetry on the index positions (2, 3) - >>> from sage.all import * >>> a = Components(QQ, V.basis(), Integer(1)) >>> a[:] = (Integer(1), -Integer(2), Integer(3)) >>> b = CompFullyAntiSym(QQ, V.basis(), Integer(3)) >>> b[Integer(0),Integer(1),Integer(2)] = Integer(4) >>> c = a*b ; c 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (1, 2, 3) >>> s = c.symmetrize(Integer(0),Integer(1)) ; s 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1), with antisymmetry on the index positions (2, 3) - Note that the antisymmetry on \((1, 2, 3)\) has been reduced to \((2, 3)\) only: - sage: s = c.symmetrize(1,2) ; s 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (1, 2) sage: s == 0 # because (1,2) are involved in the original antisymmetry True - >>> from sage.all import * >>> s = c.symmetrize(Integer(1),Integer(2)) ; s 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (1, 2) >>> s == Integer(0) # because (1,2) are involved in the original antisymmetry True 
 - trace(pos1, pos2)[source]¶
- Index contraction, taking care of the symmetries. - INPUT: - pos1– position of the first index for the contraction (with the convention position=0 for the first slot)
- pos2– position of the second index for the contraction
 - OUTPUT: - set of components resulting from the (pos1, pos2) contraction 
 - EXAMPLES: - Self-contraction of symmetric 2-indices components: - sage: from sage.tensor.modules.comp import Components, CompWithSym, \ ....: CompFullySym, CompFullyAntiSym sage: V = VectorSpace(QQ, 3) sage: a = CompFullySym(QQ, V.basis(), 2) sage: a[:] = [[1,2,3],[2,4,5],[3,5,6]] sage: a.trace(0,1) 11 sage: a[0,0] + a[1,1] + a[2,2] 11 - >>> from sage.all import * >>> from sage.tensor.modules.comp import Components, CompWithSym, CompFullySym, CompFullyAntiSym >>> V = VectorSpace(QQ, Integer(3)) >>> a = CompFullySym(QQ, V.basis(), Integer(2)) >>> a[:] = [[Integer(1),Integer(2),Integer(3)],[Integer(2),Integer(4),Integer(5)],[Integer(3),Integer(5),Integer(6)]] >>> a.trace(Integer(0),Integer(1)) 11 >>> a[Integer(0),Integer(0)] + a[Integer(1),Integer(1)] + a[Integer(2),Integer(2)] 11 - Self-contraction of antisymmetric 2-indices components: - sage: b = CompFullyAntiSym(QQ, V.basis(), 2) sage: b[0,1], b[0,2], b[1,2] = (3, -2, 1) sage: b.trace(0,1) # must be zero by antisymmetry 0 - >>> from sage.all import * >>> b = CompFullyAntiSym(QQ, V.basis(), Integer(2)) >>> b[Integer(0),Integer(1)], b[Integer(0),Integer(2)], b[Integer(1),Integer(2)] = (Integer(3), -Integer(2), Integer(1)) >>> b.trace(Integer(0),Integer(1)) # must be zero by antisymmetry 0 - Self-contraction of 3-indices components with one symmetry: - sage: v = Components(QQ, V.basis(), 1) sage: v[:] = (-2, 4, -8) sage: c = v*b ; c 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (1, 2) sage: s = c.trace(0,1) ; s 1-index components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: s[:] [-28, 2, 8] sage: [sum(v[k]*b[k,i] for k in range(3)) for i in range(3)] # check [-28, 2, 8] sage: s = c.trace(1,2) ; s 1-index components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: s[:] # is zero by antisymmetry [0, 0, 0] sage: c = b*v ; c 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 1) sage: s = c.trace(0,1) sage: s[:] # is zero by antisymmetry [0, 0, 0] sage: s = c.trace(1,2) ; s[:] [28, -2, -8] sage: [sum(b[i,k]*v[k] for k in range(3)) for i in range(3)] # check [28, -2, -8] - >>> from sage.all import * >>> v = Components(QQ, V.basis(), Integer(1)) >>> v[:] = (-Integer(2), Integer(4), -Integer(8)) >>> c = v*b ; c 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (1, 2) >>> s = c.trace(Integer(0),Integer(1)) ; s 1-index components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> s[:] [-28, 2, 8] >>> [sum(v[k]*b[k,i] for k in range(Integer(3))) for i in range(Integer(3))] # check [-28, 2, 8] >>> s = c.trace(Integer(1),Integer(2)) ; s 1-index components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> s[:] # is zero by antisymmetry [0, 0, 0] >>> c = b*v ; c 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 1) >>> s = c.trace(Integer(0),Integer(1)) >>> s[:] # is zero by antisymmetry [0, 0, 0] >>> s = c.trace(Integer(1),Integer(2)) ; s[:] [28, -2, -8] >>> [sum(b[i,k]*v[k] for k in range(Integer(3))) for i in range(Integer(3))] # check [28, -2, -8] - Self-contraction of 4-indices components with two symmetries: - sage: c = a*b ; c 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1), with antisymmetry on the index positions (2, 3) sage: s = c.trace(0,1) ; s # the symmetry on (0,1) is lost: Fully antisymmetric 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: s[:] [ 0 33 -22] [-33 0 11] [ 22 -11 0] sage: [[sum(c[k,k,i,j] for k in range(3)) for j in range(3)] for i in range(3)] # check [[0, 33, -22], [-33, 0, 11], [22, -11, 0]] sage: s = c.trace(1,2) ; s # both symmetries are lost by this contraction 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: s[:] [ 0 0 0] [-2 1 0] [-3 3 -1] sage: [[sum(c[i,k,k,j] for k in range(3)) for j in range(3)] for i in range(3)] # check [[0, 0, 0], [-2, 1, 0], [-3, 3, -1]] - >>> from sage.all import * >>> c = a*b ; c 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1), with antisymmetry on the index positions (2, 3) >>> s = c.trace(Integer(0),Integer(1)) ; s # the symmetry on (0,1) is lost: Fully antisymmetric 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> s[:] [ 0 33 -22] [-33 0 11] [ 22 -11 0] >>> [[sum(c[k,k,i,j] for k in range(Integer(3))) for j in range(Integer(3))] for i in range(Integer(3))] # check [[0, 33, -22], [-33, 0, 11], [22, -11, 0]] >>> s = c.trace(Integer(1),Integer(2)) ; s # both symmetries are lost by this contraction 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> s[:] [ 0 0 0] [-2 1 0] [-3 3 -1] >>> [[sum(c[i,k,k,j] for k in range(Integer(3))) for j in range(Integer(3))] for i in range(Integer(3))] # check [[0, 0, 0], [-2, 1, 0], [-3, 3, -1]] 
 
- class sage.tensor.modules.comp.Components(ring, frame, nb_indices, start_index=0, output_formatter=None)[source]¶
- Bases: - SageObject- Indexed set of ring elements forming some components with respect to a given “frame”. - The “frame” can be a basis of some vector space or a vector frame on some manifold (i.e. a field of bases). The stored quantities can be tensor components or non-tensorial quantities, such as connection coefficients or structure coefficients. The symmetries over some indices are dealt by subclasses of the class - Components.- INPUT: - ring– commutative ring in which each component takes its value
- frame– frame with respect to which the components are defined; whatever type- frameis, it should have a method- __len__()implemented, so that- len(frame)returns the dimension, i.e. the size of a single index range
- nb_indices– number of integer indices labeling the components
- start_index– (default: 0) first value of a single index; accordingly a component index i must obey- start_index <= i <= start_index + dim - 1, where- dim = len(frame).
- output_formatter– (default:- None) function or unbound method called to format the output of the component access operator- [...](method __getitem__);- output_formattermust take 1 or 2 arguments: the 1st argument must be an element of- ringand the second one, if any, some format specification.
 - EXAMPLES: - Set of components with 2 indices on a 3-dimensional vector space, the frame being some basis of the vector space: - sage: from sage.tensor.modules.comp import Components sage: V = VectorSpace(QQ,3) sage: basis = V.basis() ; basis [(1, 0, 0), (0, 1, 0), (0, 0, 1)] sage: c = Components(QQ, basis, 2) ; c 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] - >>> from sage.all import * >>> from sage.tensor.modules.comp import Components >>> V = VectorSpace(QQ,Integer(3)) >>> basis = V.basis() ; basis [(1, 0, 0), (0, 1, 0), (0, 0, 1)] >>> c = Components(QQ, basis, Integer(2)) ; c 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] - Actually, the frame can be any object that has some length, i.e. on which the function - len()can be called:- sage: basis1 = V.gens() ; basis1 ((1, 0, 0), (0, 1, 0), (0, 0, 1)) sage: c1 = Components(QQ, basis1, 2) ; c1 2-indices components w.r.t. ((1, 0, 0), (0, 1, 0), (0, 0, 1)) sage: basis2 = ['a', 'b' , 'c'] sage: c2 = Components(QQ, basis2, 2) ; c2 2-indices components w.r.t. ['a', 'b', 'c'] - >>> from sage.all import * >>> basis1 = V.gens() ; basis1 ((1, 0, 0), (0, 1, 0), (0, 0, 1)) >>> c1 = Components(QQ, basis1, Integer(2)) ; c1 2-indices components w.r.t. ((1, 0, 0), (0, 1, 0), (0, 0, 1)) >>> basis2 = ['a', 'b' , 'c'] >>> c2 = Components(QQ, basis2, Integer(2)) ; c2 2-indices components w.r.t. ['a', 'b', 'c'] - By default, the indices range from \(0\) to \(n-1\), where \(n\) is the length of the frame. This can be changed via the argument - start_index:- sage: c1 = Components(QQ, basis, 2, start_index=1) sage: c1[0,1] Traceback (most recent call last): ... IndexError: index out of range: 0 not in [1, 3] sage: c[0,1] # for c, the index 0 is OK 0 sage: c[0,1] = -3 sage: c1[:] = c[:] # list copy of all components sage: c1[1,2] # (1,2) = (0,1) shifted by 1 -3 - >>> from sage.all import * >>> c1 = Components(QQ, basis, Integer(2), start_index=Integer(1)) >>> c1[Integer(0),Integer(1)] Traceback (most recent call last): ... IndexError: index out of range: 0 not in [1, 3] >>> c[Integer(0),Integer(1)] # for c, the index 0 is OK 0 >>> c[Integer(0),Integer(1)] = -Integer(3) >>> c1[:] = c[:] # list copy of all components >>> c1[Integer(1),Integer(2)] # (1,2) = (0,1) shifted by 1 -3 - If some formatter function or unbound method is provided via the argument - output_formatter, it is used to change the output of the access operator- [...]:- sage: a = Components(QQ, basis, 2, output_formatter=Rational.numerical_approx) sage: a[1,2] = 1/3 sage: a[1,2] 0.333333333333333 - >>> from sage.all import * >>> a = Components(QQ, basis, Integer(2), output_formatter=Rational.numerical_approx) >>> a[Integer(1),Integer(2)] = Integer(1)/Integer(3) >>> a[Integer(1),Integer(2)] 0.333333333333333 - The format can be passed to the formatter as the last argument of the access operator - [...]:- sage: a[1,2,10] # here the format is 10, for 10 bits of precision 0.33 sage: a[1,2,100] 0.33333333333333333333333333333 - >>> from sage.all import * >>> a[Integer(1),Integer(2),Integer(10)] # here the format is 10, for 10 bits of precision 0.33 >>> a[Integer(1),Integer(2),Integer(100)] 0.33333333333333333333333333333 - The raw (unformatted) components are then accessed by the double bracket operator: - sage: a[[1,2]] 1/3 - >>> from sage.all import * >>> a[[Integer(1),Integer(2)]] 1/3 - For sets of components declared without any output formatter, there is no difference between - [...]and- [[...]]:- sage: c[1,2] = 1/3 sage: c[1,2], c[[1,2]] (1/3, 1/3) - >>> from sage.all import * >>> c[Integer(1),Integer(2)] = Integer(1)/Integer(3) >>> c[Integer(1),Integer(2)], c[[Integer(1),Integer(2)]] (1/3, 1/3) - The formatter is also used for the complete list of components: - sage: a[:] [0.000000000000000 0.000000000000000 0.000000000000000] [0.000000000000000 0.000000000000000 0.333333333333333] [0.000000000000000 0.000000000000000 0.000000000000000] sage: a[:,10] # with a format different from the default one (53 bits) [0.00 0.00 0.00] [0.00 0.00 0.33] [0.00 0.00 0.00] - >>> from sage.all import * >>> a[:] [0.000000000000000 0.000000000000000 0.000000000000000] [0.000000000000000 0.000000000000000 0.333333333333333] [0.000000000000000 0.000000000000000 0.000000000000000] >>> a[:,Integer(10)] # with a format different from the default one (53 bits) [0.00 0.00 0.00] [0.00 0.00 0.33] [0.00 0.00 0.00] - The complete list of components in raw form can be recovered by the double bracket operator, replacing - :by- slice(None)(since- a[[:]]generates a Python syntax error):- sage: a[[slice(None)]] [ 0 0 0] [ 0 0 1/3] [ 0 0 0] - >>> from sage.all import * >>> a[[slice(None)]] [ 0 0 0] [ 0 0 1/3] [ 0 0 0] - Another example of formatter: the Python built-in function - str()to generate string outputs:- sage: b = Components(QQ, V.basis(), 1, output_formatter=str) sage: b[:] = (1, 0, -4) sage: b[:] ['1', '0', '-4'] - >>> from sage.all import * >>> b = Components(QQ, V.basis(), Integer(1), output_formatter=str) >>> b[:] = (Integer(1), Integer(0), -Integer(4)) >>> b[:] ['1', '0', '-4'] - For such a formatter, 2-indices components are no longer displayed as a matrix: - sage: b = Components(QQ, basis, 2, output_formatter=str) sage: b[0,1] = 1/3 sage: b[:] [['0', '1/3', '0'], ['0', '0', '0'], ['0', '0', '0']] - >>> from sage.all import * >>> b = Components(QQ, basis, Integer(2), output_formatter=str) >>> b[Integer(0),Integer(1)] = Integer(1)/Integer(3) >>> b[:] [['0', '1/3', '0'], ['0', '0', '0'], ['0', '0', '0']] - But unformatted outputs still are: - sage: b[[slice(None)]] [ 0 1/3 0] [ 0 0 0] [ 0 0 0] - >>> from sage.all import * >>> b[[slice(None)]] [ 0 1/3 0] [ 0 0 0] [ 0 0 0] - Internally, the components are stored as a dictionary ( - _comp) whose keys are the indices; only the nonzero components are stored:- sage: a[:] [0.000000000000000 0.000000000000000 0.000000000000000] [0.000000000000000 0.000000000000000 0.333333333333333] [0.000000000000000 0.000000000000000 0.000000000000000] sage: a._comp {(1, 2): 1/3} sage: v = Components(QQ, basis, 1) sage: v[:] = (-1, 0, 3) sage: v._comp # random output order of the component dictionary {(0,): -1, (2,): 3} - >>> from sage.all import * >>> a[:] [0.000000000000000 0.000000000000000 0.000000000000000] [0.000000000000000 0.000000000000000 0.333333333333333] [0.000000000000000 0.000000000000000 0.000000000000000] >>> a._comp {(1, 2): 1/3} >>> v = Components(QQ, basis, Integer(1)) >>> v[:] = (-Integer(1), Integer(0), Integer(3)) >>> v._comp # random output order of the component dictionary {(0,): -1, (2,): 3} - ARITHMETIC EXAMPLES: - Unary plus operator: - sage: a = Components(QQ, basis, 1) sage: a[:] = (-1, 0, 3) sage: s = +a ; s[:] [-1, 0, 3] sage: +a == a True - >>> from sage.all import * >>> a = Components(QQ, basis, Integer(1)) >>> a[:] = (-Integer(1), Integer(0), Integer(3)) >>> s = +a ; s[:] [-1, 0, 3] >>> +a == a True - Unary minus operator: - sage: s = -a ; s[:] [1, 0, -3] - >>> from sage.all import * >>> s = -a ; s[:] [1, 0, -3] - Addition: - sage: b = Components(QQ, basis, 1) sage: b[:] = (2, 1, 4) sage: s = a + b ; s[:] [1, 1, 7] sage: a + b == b + a True sage: a + (-a) == 0 True - >>> from sage.all import * >>> b = Components(QQ, basis, Integer(1)) >>> b[:] = (Integer(2), Integer(1), Integer(4)) >>> s = a + b ; s[:] [1, 1, 7] >>> a + b == b + a True >>> a + (-a) == Integer(0) True - Subtraction: - sage: s = a - b ; s[:] [-3, -1, -1] sage: s + b == a True sage: a - b == - (b - a) True - >>> from sage.all import * >>> s = a - b ; s[:] [-3, -1, -1] >>> s + b == a True >>> a - b == - (b - a) True - Multiplication by a scalar: - sage: s = 2*a ; s[:] [-2, 0, 6] - >>> from sage.all import * >>> s = Integer(2)*a ; s[:] [-2, 0, 6] - Division by a scalar: - sage: s = a/2 ; s[:] [-1/2, 0, 3/2] sage: 2*(a/2) == a True - >>> from sage.all import * >>> s = a/Integer(2) ; s[:] [-1/2, 0, 3/2] >>> Integer(2)*(a/Integer(2)) == a True - Tensor product (by means of the operator - *):- sage: c = a*b ; c 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: a[:], b[:] ([-1, 0, 3], [2, 1, 4]) sage: c[:] [-2 -1 -4] [ 0 0 0] [ 6 3 12] sage: d = c*a ; d 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: d[:] [[[2, 0, -6], [1, 0, -3], [4, 0, -12]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[-6, 0, 18], [-3, 0, 9], [-12, 0, 36]]] sage: d[0,1,2] == a[0]*b[1]*a[2] True - >>> from sage.all import * >>> c = a*b ; c 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> a[:], b[:] ([-1, 0, 3], [2, 1, 4]) >>> c[:] [-2 -1 -4] [ 0 0 0] [ 6 3 12] >>> d = c*a ; d 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> d[:] [[[2, 0, -6], [1, 0, -3], [4, 0, -12]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[-6, 0, 18], [-3, 0, 9], [-12, 0, 36]]] >>> d[Integer(0),Integer(1),Integer(2)] == a[Integer(0)]*b[Integer(1)]*a[Integer(2)] True - antisymmetrize(*pos)[source]¶
- Antisymmetrization over the given index positions. - INPUT: - pos– list of index positions involved in the antisymmetrization (with the convention position=0 for the first slot); if none, the antisymmetrization is performed over all the indices
 - OUTPUT: an instance of - CompWithSymdescribing the antisymmetrized components- EXAMPLES: - Antisymmetrization of 2-indices components: - sage: from sage.tensor.modules.comp import Components sage: V = VectorSpace(QQ, 3) sage: c = Components(QQ, V.basis(), 2) sage: c[:] = [[1,2,3], [4,5,6], [7,8,9]] sage: s = c.antisymmetrize() ; s Fully antisymmetric 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: c[:], s[:] ( [1 2 3] [ 0 -1 -2] [4 5 6] [ 1 0 -1] [7 8 9], [ 2 1 0] ) sage: c.antisymmetrize() == c.antisymmetrize(0,1) True - >>> from sage.all import * >>> from sage.tensor.modules.comp import Components >>> V = VectorSpace(QQ, Integer(3)) >>> c = Components(QQ, V.basis(), Integer(2)) >>> c[:] = [[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9)]] >>> s = c.antisymmetrize() ; s Fully antisymmetric 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> c[:], s[:] ( [1 2 3] [ 0 -1 -2] [4 5 6] [ 1 0 -1] [7 8 9], [ 2 1 0] ) >>> c.antisymmetrize() == c.antisymmetrize(Integer(0),Integer(1)) True - Full antisymmetrization of 3-indices components: - sage: c = Components(QQ, V.basis(), 3) sage: c[:] = [[[-1,-2,3], [4,-5,4], [-7,8,9]], [[10,10,12], [13,-14,15], [-16,17,19]], [[-19,20,21], [1,2,3], [-25,26,27]]] sage: s = c.antisymmetrize() ; s Fully antisymmetric 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: c[:], s[:] ([[[-1, -2, 3], [4, -5, 4], [-7, 8, 9]], [[10, 10, 12], [13, -14, 15], [-16, 17, 19]], [[-19, 20, 21], [1, 2, 3], [-25, 26, 27]]], [[[0, 0, 0], [0, 0, -13/6], [0, 13/6, 0]], [[0, 0, 13/6], [0, 0, 0], [-13/6, 0, 0]], [[0, -13/6, 0], [13/6, 0, 0], [0, 0, 0]]]) sage: all(s[i,j,k] == (c[i,j,k]-c[i,k,j]+c[j,k,i]-c[j,i,k]+c[k,i,j]-c[k,j,i])/6 # Check of the result: ....: for i in range(3) for j in range(3) for k in range(3)) True sage: c.symmetrize() == c.symmetrize(0,1,2) True - >>> from sage.all import * >>> c = Components(QQ, V.basis(), Integer(3)) >>> c[:] = [[[-Integer(1),-Integer(2),Integer(3)], [Integer(4),-Integer(5),Integer(4)], [-Integer(7),Integer(8),Integer(9)]], [[Integer(10),Integer(10),Integer(12)], [Integer(13),-Integer(14),Integer(15)], [-Integer(16),Integer(17),Integer(19)]], [[-Integer(19),Integer(20),Integer(21)], [Integer(1),Integer(2),Integer(3)], [-Integer(25),Integer(26),Integer(27)]]] >>> s = c.antisymmetrize() ; s Fully antisymmetric 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> c[:], s[:] ([[[-1, -2, 3], [4, -5, 4], [-7, 8, 9]], [[10, 10, 12], [13, -14, 15], [-16, 17, 19]], [[-19, 20, 21], [1, 2, 3], [-25, 26, 27]]], [[[0, 0, 0], [0, 0, -13/6], [0, 13/6, 0]], [[0, 0, 13/6], [0, 0, 0], [-13/6, 0, 0]], [[0, -13/6, 0], [13/6, 0, 0], [0, 0, 0]]]) >>> all(s[i,j,k] == (c[i,j,k]-c[i,k,j]+c[j,k,i]-c[j,i,k]+c[k,i,j]-c[k,j,i])/Integer(6) # Check of the result: ... for i in range(Integer(3)) for j in range(Integer(3)) for k in range(Integer(3))) True >>> c.symmetrize() == c.symmetrize(Integer(0),Integer(1),Integer(2)) True - Partial antisymmetrization of 3-indices components: - sage: s = c.antisymmetrize(0,1) ; s # antisymmetrization on the first two indices 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 1) sage: c[:], s[:] ([[[-1, -2, 3], [4, -5, 4], [-7, 8, 9]], [[10, 10, 12], [13, -14, 15], [-16, 17, 19]], [[-19, 20, 21], [1, 2, 3], [-25, 26, 27]]], [[[0, 0, 0], [-3, -15/2, -4], [6, -6, -6]], [[3, 15/2, 4], [0, 0, 0], [-17/2, 15/2, 8]], [[-6, 6, 6], [17/2, -15/2, -8], [0, 0, 0]]]) sage: all(s[i,j,k] == (c[i,j,k]-c[j,i,k])/2 # Check of the result: ....: for i in range(3) for j in range(3) for k in range(3)) True sage: s = c.antisymmetrize(1,2) ; s # antisymmetrization on the last two indices 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (1, 2) sage: c[:], s[:] ([[[-1, -2, 3], [4, -5, 4], [-7, 8, 9]], [[10, 10, 12], [13, -14, 15], [-16, 17, 19]], [[-19, 20, 21], [1, 2, 3], [-25, 26, 27]]], [[[0, -3, 5], [3, 0, -2], [-5, 2, 0]], [[0, -3/2, 14], [3/2, 0, -1], [-14, 1, 0]], [[0, 19/2, 23], [-19/2, 0, -23/2], [-23, 23/2, 0]]]) sage: all(s[i,j,k] == (c[i,j,k]-c[i,k,j])/2 # Check of the result: ....: for i in range(3) for j in range(3) for k in range(3)) True sage: s = c.antisymmetrize(0,2) ; s # antisymmetrization on the first and last indices 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 2) sage: c[:], s[:] ([[[-1, -2, 3], [4, -5, 4], [-7, 8, 9]], [[10, 10, 12], [13, -14, 15], [-16, 17, 19]], [[-19, 20, 21], [1, 2, 3], [-25, 26, 27]]], [[[0, -6, 11], [0, -9, 3/2], [0, 12, 17]], [[6, 0, -4], [9, 0, 13/2], [-12, 0, -7/2]], [[-11, 4, 0], [-3/2, -13/2, 0], [-17, 7/2, 0]]]) sage: all(s[i,j,k] == (c[i,j,k]-c[k,j,i])/2 # Check of the result: ....: for i in range(3) for j in range(3) for k in range(3)) True - >>> from sage.all import * >>> s = c.antisymmetrize(Integer(0),Integer(1)) ; s # antisymmetrization on the first two indices 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 1) >>> c[:], s[:] ([[[-1, -2, 3], [4, -5, 4], [-7, 8, 9]], [[10, 10, 12], [13, -14, 15], [-16, 17, 19]], [[-19, 20, 21], [1, 2, 3], [-25, 26, 27]]], [[[0, 0, 0], [-3, -15/2, -4], [6, -6, -6]], [[3, 15/2, 4], [0, 0, 0], [-17/2, 15/2, 8]], [[-6, 6, 6], [17/2, -15/2, -8], [0, 0, 0]]]) >>> all(s[i,j,k] == (c[i,j,k]-c[j,i,k])/Integer(2) # Check of the result: ... for i in range(Integer(3)) for j in range(Integer(3)) for k in range(Integer(3))) True >>> s = c.antisymmetrize(Integer(1),Integer(2)) ; s # antisymmetrization on the last two indices 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (1, 2) >>> c[:], s[:] ([[[-1, -2, 3], [4, -5, 4], [-7, 8, 9]], [[10, 10, 12], [13, -14, 15], [-16, 17, 19]], [[-19, 20, 21], [1, 2, 3], [-25, 26, 27]]], [[[0, -3, 5], [3, 0, -2], [-5, 2, 0]], [[0, -3/2, 14], [3/2, 0, -1], [-14, 1, 0]], [[0, 19/2, 23], [-19/2, 0, -23/2], [-23, 23/2, 0]]]) >>> all(s[i,j,k] == (c[i,j,k]-c[i,k,j])/Integer(2) # Check of the result: ... for i in range(Integer(3)) for j in range(Integer(3)) for k in range(Integer(3))) True >>> s = c.antisymmetrize(Integer(0),Integer(2)) ; s # antisymmetrization on the first and last indices 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with antisymmetry on the index positions (0, 2) >>> c[:], s[:] ([[[-1, -2, 3], [4, -5, 4], [-7, 8, 9]], [[10, 10, 12], [13, -14, 15], [-16, 17, 19]], [[-19, 20, 21], [1, 2, 3], [-25, 26, 27]]], [[[0, -6, 11], [0, -9, 3/2], [0, 12, 17]], [[6, 0, -4], [9, 0, 13/2], [-12, 0, -7/2]], [[-11, 4, 0], [-3/2, -13/2, 0], [-17, 7/2, 0]]]) >>> all(s[i,j,k] == (c[i,j,k]-c[k,j,i])/Integer(2) # Check of the result: ... for i in range(Integer(3)) for j in range(Integer(3)) for k in range(Integer(3))) True - The order of index positions in the argument does not matter: - sage: c.antisymmetrize(1,0) == c.antisymmetrize(0,1) True sage: c.antisymmetrize(2,1) == c.antisymmetrize(1,2) True sage: c.antisymmetrize(2,0) == c.antisymmetrize(0,2) True - >>> from sage.all import * >>> c.antisymmetrize(Integer(1),Integer(0)) == c.antisymmetrize(Integer(0),Integer(1)) True >>> c.antisymmetrize(Integer(2),Integer(1)) == c.antisymmetrize(Integer(1),Integer(2)) True >>> c.antisymmetrize(Integer(2),Integer(0)) == c.antisymmetrize(Integer(0),Integer(2)) True 
 - contract(*args)[source]¶
- Contraction on one or many indices with another instance of - Components.- INPUT: - pos1– positions of the indices in- selfinvolved in the contraction;- pos1must be a sequence of integers, with 0 standing for the first index position, 1 for the second one, etc. If- pos1is not provided, a single contraction on the last index position of- selfis assumed
- other– the set of components to contract with
- pos2– positions of the indices in- otherinvolved in the contraction, with the same conventions as for- pos1. If- pos2is not provided, a single contraction on the first index position of- otheris assumed
 - OUTPUT: set of components resulting from the contraction - EXAMPLES: - Contraction of a 1-index set of components with a 2-index one: - sage: from sage.tensor.modules.comp import Components sage: V = VectorSpace(QQ, 3) sage: a = Components(QQ, V.basis(), 1) sage: a[:] = (-1, 2, 3) sage: b = Components(QQ, V.basis(), 2) sage: b[:] = [[1,2,3], [4,5,6], [7,8,9]] sage: s0 = a.contract(0, b, 0) ; s0 1-index components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: s0[:] [28, 32, 36] sage: s0[:] == [sum(a[j]*b[j,i] for j in range(3)) for i in range(3)] # check True sage: s1 = a.contract(0, b, 1) ; s1[:] [12, 24, 36] sage: s1[:] == [sum(a[j]*b[i,j] for j in range(3)) for i in range(3)] # check True - >>> from sage.all import * >>> from sage.tensor.modules.comp import Components >>> V = VectorSpace(QQ, Integer(3)) >>> a = Components(QQ, V.basis(), Integer(1)) >>> a[:] = (-Integer(1), Integer(2), Integer(3)) >>> b = Components(QQ, V.basis(), Integer(2)) >>> b[:] = [[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9)]] >>> s0 = a.contract(Integer(0), b, Integer(0)) ; s0 1-index components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> s0[:] [28, 32, 36] >>> s0[:] == [sum(a[j]*b[j,i] for j in range(Integer(3))) for i in range(Integer(3))] # check True >>> s1 = a.contract(Integer(0), b, Integer(1)) ; s1[:] [12, 24, 36] >>> s1[:] == [sum(a[j]*b[i,j] for j in range(Integer(3))) for i in range(Integer(3))] # check True - Parallel computations (see - Parallelism):- sage: Parallelism().set('tensor', nproc=2) sage: Parallelism().get('tensor') 2 sage: s0_par = a.contract(0, b, 0) ; s0_par 1-index components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: s0_par[:] [28, 32, 36] sage: s0_par == s0 True sage: s1_par = a.contract(0, b, 1) ; s1_par[:] [12, 24, 36] sage: s1_par == s1 True sage: Parallelism().set('tensor', nproc = 1) # switch off parallelization - >>> from sage.all import * >>> Parallelism().set('tensor', nproc=Integer(2)) >>> Parallelism().get('tensor') 2 >>> s0_par = a.contract(Integer(0), b, Integer(0)) ; s0_par 1-index components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> s0_par[:] [28, 32, 36] >>> s0_par == s0 True >>> s1_par = a.contract(Integer(0), b, Integer(1)) ; s1_par[:] [12, 24, 36] >>> s1_par == s1 True >>> Parallelism().set('tensor', nproc = Integer(1)) # switch off parallelization - Contraction on 2 indices: - sage: c = a*b ; c 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: s = c.contract(1,2, b, 0,1) ; s 1-index components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: s[:] [-285, 570, 855] sage: [sum(sum(c[i,j,k]*b[j,k] for k in range(3)) # check ....: for j in range(3)) for i in range(3)] [-285, 570, 855] - >>> from sage.all import * >>> c = a*b ; c 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> s = c.contract(Integer(1),Integer(2), b, Integer(0),Integer(1)) ; s 1-index components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> s[:] [-285, 570, 855] >>> [sum(sum(c[i,j,k]*b[j,k] for k in range(Integer(3))) # check ... for j in range(Integer(3))) for i in range(Integer(3))] [-285, 570, 855] - Parallel computation: - sage: Parallelism().set('tensor', nproc=2) sage: c_par = a*b ; c_par 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: c_par == c True sage: s_par = c_par.contract(1,2, b, 0,1) ; s_par 1-index components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: s_par[:] [-285, 570, 855] sage: s_par == s True sage: Parallelism().set('tensor', nproc=1) # switch off parallelization - >>> from sage.all import * >>> Parallelism().set('tensor', nproc=Integer(2)) >>> c_par = a*b ; c_par 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> c_par == c True >>> s_par = c_par.contract(Integer(1),Integer(2), b, Integer(0),Integer(1)) ; s_par 1-index components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> s_par[:] [-285, 570, 855] >>> s_par == s True >>> Parallelism().set('tensor', nproc=Integer(1)) # switch off parallelization - Consistency check with - trace():- sage: b = a*a ; b # the tensor product of a with itself Fully symmetric 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: b[:] [ 1 -2 -3] [-2 4 6] [-3 6 9] sage: b.trace(0,1) 14 sage: a.contract(0, a, 0) == b.trace(0,1) True - >>> from sage.all import * >>> b = a*a ; b # the tensor product of a with itself Fully symmetric 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> b[:] [ 1 -2 -3] [-2 4 6] [-3 6 9] >>> b.trace(Integer(0),Integer(1)) 14 >>> a.contract(Integer(0), a, Integer(0)) == b.trace(Integer(0),Integer(1)) True 
 - copy()[source]¶
- Return an exact copy of - self.- EXAMPLES: - Copy of a set of components with a single index: - sage: from sage.tensor.modules.comp import Components sage: V = VectorSpace(QQ,3) sage: a = Components(QQ, V.basis(), 1) sage: a[:] = -2, 1, 5 sage: b = a.copy() ; b 1-index components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: b[:] [-2, 1, 5] sage: b == a True sage: b is a # b is a distinct object False - >>> from sage.all import * >>> from sage.tensor.modules.comp import Components >>> V = VectorSpace(QQ,Integer(3)) >>> a = Components(QQ, V.basis(), Integer(1)) >>> a[:] = -Integer(2), Integer(1), Integer(5) >>> b = a.copy() ; b 1-index components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> b[:] [-2, 1, 5] >>> b == a True >>> b is a # b is a distinct object False 
 - display(symbol, latex_symbol=None, index_positions=None, index_labels=None, index_latex_labels=None, format_spec=None, only_nonzero=True, only_nonredundant=False)[source]¶
- Display all the components, one per line. - The output is either text-formatted (console mode) or LaTeX-formatted (notebook mode). - INPUT: - symbol– string (typically a single letter) specifying the symbol for the components
- latex_symbol– (default:- None) string specifying the LaTeX symbol for the components; if- None,- symbolis used
- index_positions– (default:- None) string of length the number of indices of the components and composed of characters ‘d’ (for “down”) or ‘u’ (for “up”) to specify the position of each index: ‘d’ corresponds to a subscript and ‘u’ to a superscript. If- index_positionsis- None, all indices are printed as subscripts
- index_labels– (default:- None) list of strings representing the labels of each of the individual indices within the index range defined at the construction of the object; if- None, integer labels are used
- index_latex_labels– (default:- None) list of strings representing the LaTeX labels of each of the individual indices within the index range defined at the construction of the object; if- None, integers labels are used
- format_spec– (default:- None) format specification passed to the output formatter declared at the construction of the object
- only_nonzero– boolean (default:- True); if- True, only nonzero components are displayed
- only_nonredundant– boolean (default:- False); if- True, only nonredundant components are displayed in case of symmetries
 - EXAMPLES: - Display of 3-indices components w.r.t. to the canonical basis of the free module \(\ZZ^2\) over the integer ring: - sage: from sage.tensor.modules.comp import Components sage: c = Components(ZZ, (ZZ^2).basis(), 3) sage: c[0,1,0], c[1,0,1], c[1,1,1] = -2, 5, 3 sage: c.display('c') c_010 = -2 c_101 = 5 c_111 = 3 - >>> from sage.all import * >>> from sage.tensor.modules.comp import Components >>> c = Components(ZZ, (ZZ**Integer(2)).basis(), Integer(3)) >>> c[Integer(0),Integer(1),Integer(0)], c[Integer(1),Integer(0),Integer(1)], c[Integer(1),Integer(1),Integer(1)] = -Integer(2), Integer(5), Integer(3) >>> c.display('c') c_010 = -2 c_101 = 5 c_111 = 3 - By default, only nonzero components are shown; to display all the components, it suffices to set the parameter - only_nonzeroto- False:- sage: c.display('c', only_nonzero=False) c_000 = 0 c_001 = 0 c_010 = -2 c_011 = 0 c_100 = 0 c_101 = 5 c_110 = 0 c_111 = 3 - >>> from sage.all import * >>> c.display('c', only_nonzero=False) c_000 = 0 c_001 = 0 c_010 = -2 c_011 = 0 c_100 = 0 c_101 = 5 c_110 = 0 c_111 = 3 - By default, all indices are printed as subscripts, but any index position can be specified: - sage: c.display('c', index_positions='udd') c^0_10 = -2 c^1_01 = 5 c^1_11 = 3 sage: c.display('c', index_positions='udu') c^0_1^0 = -2 c^1_0^1 = 5 c^1_1^1 = 3 sage: c.display('c', index_positions='ddu') c_01^0 = -2 c_10^1 = 5 c_11^1 = 3 - >>> from sage.all import * >>> c.display('c', index_positions='udd') c^0_10 = -2 c^1_01 = 5 c^1_11 = 3 >>> c.display('c', index_positions='udu') c^0_1^0 = -2 c^1_0^1 = 5 c^1_1^1 = 3 >>> c.display('c', index_positions='ddu') c_01^0 = -2 c_10^1 = 5 c_11^1 = 3 - The LaTeX output is performed as an array, with the symbol adjustable if it differs from the text symbol: - sage: latex(c.display('c', latex_symbol=r'\Gamma', index_positions='udd')) \begin{array}{lcl} \Gamma_{\phantom{\, 0}\,1\,0}^{\,0\phantom{\, 1}\phantom{\, 0}} & = & -2 \\ \Gamma_{\phantom{\, 1}\,0\,1}^{\,1\phantom{\, 0}\phantom{\, 1}} & = & 5 \\ \Gamma_{\phantom{\, 1}\,1\,1}^{\,1\phantom{\, 1}\phantom{\, 1}} & = & 3 \end{array} - >>> from sage.all import * >>> latex(c.display('c', latex_symbol=r'\Gamma', index_positions='udd')) \begin{array}{lcl} \Gamma_{\phantom{\, 0}\,1\,0}^{\,0\phantom{\, 1}\phantom{\, 0}} & = & -2 \\ \Gamma_{\phantom{\, 1}\,0\,1}^{\,1\phantom{\, 0}\phantom{\, 1}} & = & 5 \\ \Gamma_{\phantom{\, 1}\,1\,1}^{\,1\phantom{\, 1}\phantom{\, 1}} & = & 3 \end{array} - The index labels can differ from integers: - sage: c.display('c', index_labels=['x','y']) c_xyx = -2 c_yxy = 5 c_yyy = 3 - >>> from sage.all import * >>> c.display('c', index_labels=['x','y']) c_xyx = -2 c_yxy = 5 c_yyy = 3 - If the index labels are longer than a single character, they are separated by a comma: - sage: c.display('c', index_labels=['r', 'th']) c_r,th,r = -2 c_th,r,th = 5 c_th,th,th = 3 - >>> from sage.all import * >>> c.display('c', index_labels=['r', 'th']) c_r,th,r = -2 c_th,r,th = 5 c_th,th,th = 3 - The LaTeX labels for the indices can be specified if they differ from the text ones: - sage: c.display('c', index_labels=['r', 'th'], ....: index_latex_labels=['r', r'\theta']) c_r,th,r = -2 c_th,r,th = 5 c_th,th,th = 3 - >>> from sage.all import * >>> c.display('c', index_labels=['r', 'th'], ... index_latex_labels=['r', r'\theta']) c_r,th,r = -2 c_th,r,th = 5 c_th,th,th = 3 - The display of components with symmetries is governed by the parameter - only_nonredundant:- sage: from sage.tensor.modules.comp import CompWithSym sage: c = CompWithSym(ZZ, (ZZ^2).basis(), 3, sym=(1,2)) ; c 3-indices components w.r.t. [ (1, 0), (0, 1) ], with symmetry on the index positions (1, 2) sage: c[0,0,1] = 2 sage: c.display('c') c_001 = 2 c_010 = 2 sage: c.display('c', only_nonredundant=True) c_001 = 2 - >>> from sage.all import * >>> from sage.tensor.modules.comp import CompWithSym >>> c = CompWithSym(ZZ, (ZZ**Integer(2)).basis(), Integer(3), sym=(Integer(1),Integer(2))) ; c 3-indices components w.r.t. [ (1, 0), (0, 1) ], with symmetry on the index positions (1, 2) >>> c[Integer(0),Integer(0),Integer(1)] = Integer(2) >>> c.display('c') c_001 = 2 c_010 = 2 >>> c.display('c', only_nonredundant=True) c_001 = 2 - If some nontrivial output formatter has been set, the format can be specified by means of the argument - format_spec:- sage: c = Components(QQ, (QQ^3).basis(), 2, ....: output_formatter=Rational.numerical_approx) sage: c[0,1] = 1/3 sage: c[2,1] = 2/7 sage: c.display('C') # default format (53 bits of precision) C_01 = 0.333333333333333 C_21 = 0.285714285714286 sage: c.display('C', format_spec=10) # 10 bits of precision C_01 = 0.33 C_21 = 0.29 - >>> from sage.all import * >>> c = Components(QQ, (QQ**Integer(3)).basis(), Integer(2), ... output_formatter=Rational.numerical_approx) >>> c[Integer(0),Integer(1)] = Integer(1)/Integer(3) >>> c[Integer(2),Integer(1)] = Integer(2)/Integer(7) >>> c.display('C') # default format (53 bits of precision) C_01 = 0.333333333333333 C_21 = 0.285714285714286 >>> c.display('C', format_spec=Integer(10)) # 10 bits of precision C_01 = 0.33 C_21 = 0.29 - Check that the bug reported in Issue #22520 is fixed: - sage: c = Components(SR, [1, 2], 1) # needs sage.symbolic sage: c[0] = SR.var('t', domain='real') # needs sage.symbolic sage: c.display('c') # needs sage.symbolic c_0 = t - >>> from sage.all import * >>> c = Components(SR, [Integer(1), Integer(2)], Integer(1)) # needs sage.symbolic >>> c[Integer(0)] = SR.var('t', domain='real') # needs sage.symbolic >>> c.display('c') # needs sage.symbolic c_0 = t 
 - index_generator()[source]¶
- Generator of indices. - OUTPUT: an iterable index - EXAMPLES: - Indices on a 3-dimensional vector space: - sage: from sage.tensor.modules.comp import Components sage: V = VectorSpace(QQ,3) sage: c = Components(QQ, V.basis(), 1) sage: list(c.index_generator()) [(0,), (1,), (2,)] sage: c = Components(QQ, V.basis(), 1, start_index=1) sage: list(c.index_generator()) [(1,), (2,), (3,)] sage: c = Components(QQ, V.basis(), 2) sage: list(c.index_generator()) [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] - >>> from sage.all import * >>> from sage.tensor.modules.comp import Components >>> V = VectorSpace(QQ,Integer(3)) >>> c = Components(QQ, V.basis(), Integer(1)) >>> list(c.index_generator()) [(0,), (1,), (2,)] >>> c = Components(QQ, V.basis(), Integer(1), start_index=Integer(1)) >>> list(c.index_generator()) [(1,), (2,), (3,)] >>> c = Components(QQ, V.basis(), Integer(2)) >>> list(c.index_generator()) [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] 
 - is_zero()[source]¶
- Return - Trueif all the components are zero and- Falseotherwise.- EXAMPLES: - A just-created set of components is initialized to zero: - sage: from sage.tensor.modules.comp import Components sage: V = VectorSpace(QQ,3) sage: c = Components(QQ, V.basis(), 1) sage: c.is_zero() True sage: c[:] [0, 0, 0] sage: c[0] = 1 ; c[:] [1, 0, 0] sage: c.is_zero() False sage: c[0] = 0 ; c[:] [0, 0, 0] sage: c.is_zero() True - >>> from sage.all import * >>> from sage.tensor.modules.comp import Components >>> V = VectorSpace(QQ,Integer(3)) >>> c = Components(QQ, V.basis(), Integer(1)) >>> c.is_zero() True >>> c[:] [0, 0, 0] >>> c[Integer(0)] = Integer(1) ; c[:] [1, 0, 0] >>> c.is_zero() False >>> c[Integer(0)] = Integer(0) ; c[:] [0, 0, 0] >>> c.is_zero() True - It is equivalent to use the operator == to compare to zero: - sage: c == 0 True sage: c != 0 False - >>> from sage.all import * >>> c == Integer(0) True >>> c != Integer(0) False - Comparing to a nonzero number is meaningless: - sage: c == 1 Traceback (most recent call last): ... TypeError: cannot compare a set of components to a number - >>> from sage.all import * >>> c == Integer(1) Traceback (most recent call last): ... TypeError: cannot compare a set of components to a number 
 - items()[source]¶
- Return an iterable of - (indices, value)elements.- This may (but is not guaranteed to) suppress zero values. - EXAMPLES: - sage: from sage.tensor.modules.comp import Components, CompWithSym sage: c = Components(ZZ, (ZZ^2).basis(), 3) sage: c[0,1,0], c[1,0,1], c[1,1,1] = -2, 5, 3 sage: list(c.items()) [((0, 1, 0), -2), ((1, 0, 1), 5), ((1, 1, 1), 3)] sage: c = CompWithSym(ZZ, (ZZ^2).basis(), 3, sym=((1, 2))) sage: c[0,1,0], c[1,0,1], c[1,1,1] = -2, 5, 3 sage: list(c.items()) [((0, 0, 1), -2), ((0, 1, 0), -2), ((1, 0, 1), 5), ((1, 1, 0), 5), ((1, 1, 1), 3)] - >>> from sage.all import * >>> from sage.tensor.modules.comp import Components, CompWithSym >>> c = Components(ZZ, (ZZ**Integer(2)).basis(), Integer(3)) >>> c[Integer(0),Integer(1),Integer(0)], c[Integer(1),Integer(0),Integer(1)], c[Integer(1),Integer(1),Integer(1)] = -Integer(2), Integer(5), Integer(3) >>> list(c.items()) [((0, 1, 0), -2), ((1, 0, 1), 5), ((1, 1, 1), 3)] >>> c = CompWithSym(ZZ, (ZZ**Integer(2)).basis(), Integer(3), sym=((Integer(1), Integer(2)))) >>> c[Integer(0),Integer(1),Integer(0)], c[Integer(1),Integer(0),Integer(1)], c[Integer(1),Integer(1),Integer(1)] = -Integer(2), Integer(5), Integer(3) >>> list(c.items()) [((0, 0, 1), -2), ((0, 1, 0), -2), ((1, 0, 1), 5), ((1, 1, 0), 5), ((1, 1, 1), 3)] 
 - non_redundant_index_generator()[source]¶
- Generator of non redundant indices. - In the absence of declared symmetries, all possible indices are generated. So this method is equivalent to - index_generator(). Only versions for derived classes with symmetries or antisymmetries are not trivial.- OUTPUT: an iterable index - EXAMPLES: - Indices on a 3-dimensional vector space: - sage: from sage.tensor.modules.comp import Components sage: V = VectorSpace(QQ,3) sage: c = Components(QQ, V.basis(), 2) sage: list(c.non_redundant_index_generator()) [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] sage: c = Components(QQ, V.basis(), 2, start_index=1) sage: list(c.non_redundant_index_generator()) [(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)] - >>> from sage.all import * >>> from sage.tensor.modules.comp import Components >>> V = VectorSpace(QQ,Integer(3)) >>> c = Components(QQ, V.basis(), Integer(2)) >>> list(c.non_redundant_index_generator()) [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] >>> c = Components(QQ, V.basis(), Integer(2), start_index=Integer(1)) >>> list(c.non_redundant_index_generator()) [(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)] 
 - swap_adjacent_indices(pos1, pos2, pos3)[source]¶
- Swap two adjacent sets of indices. - This method is essentially required to reorder the covariant and contravariant indices in the computation of a tensor product. - INPUT: - pos1– position of the first index of set 1 (with the convention- position=0for the first slot)
- pos2– position of the first index of set 2 equals 1 plus the position of the last index of set 1 (since the two sets are adjacent)
- pos3– 1 plus position of the last index of set 2
 - OUTPUT: components with index set 1 permuted with index set 2 - EXAMPLES: - Swap of the two indices of a 2-indices set of components: - sage: from sage.tensor.modules.comp import Components sage: V = VectorSpace(QQ, 3) sage: c = Components(QQ, V.basis(), 2) sage: c[:] = [[1,2,3], [4,5,6], [7,8,9]] sage: c1 = c.swap_adjacent_indices(0,1,2) sage: c[:], c1[:] ( [1 2 3] [1 4 7] [4 5 6] [2 5 8] [7 8 9], [3 6 9] ) - >>> from sage.all import * >>> from sage.tensor.modules.comp import Components >>> V = VectorSpace(QQ, Integer(3)) >>> c = Components(QQ, V.basis(), Integer(2)) >>> c[:] = [[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9)]] >>> c1 = c.swap_adjacent_indices(Integer(0),Integer(1),Integer(2)) >>> c[:], c1[:] ( [1 2 3] [1 4 7] [4 5 6] [2 5 8] [7 8 9], [3 6 9] ) - Swap of two pairs of indices on a 4-indices set of components: - sage: d = c*c1 ; d 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: d1 = d.swap_adjacent_indices(0,2,4) sage: d[0,1,1,2] 16 sage: d1[1,2,0,1] 16 sage: d1[0,1,1,2] 24 sage: d[1,2,0,1] 24 - >>> from sage.all import * >>> d = c*c1 ; d 4-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> d1 = d.swap_adjacent_indices(Integer(0),Integer(2),Integer(4)) >>> d[Integer(0),Integer(1),Integer(1),Integer(2)] 16 >>> d1[Integer(1),Integer(2),Integer(0),Integer(1)] 16 >>> d1[Integer(0),Integer(1),Integer(1),Integer(2)] 24 >>> d[Integer(1),Integer(2),Integer(0),Integer(1)] 24 
 - symmetrize(*pos)[source]¶
- Symmetrization over the given index positions. - INPUT: - pos– list of index positions involved in the symmetrization (with the convention position=0 for the first slot); if none, the symmetrization is performed over all the indices
 - OUTPUT: - an instance of - CompWithSymdescribing the symmetrized components
 - EXAMPLES: - Symmetrization of 2-indices components: - sage: from sage.tensor.modules.comp import Components sage: V = VectorSpace(QQ, 3) sage: c = Components(QQ, V.basis(), 2) sage: c[:] = [[1,2,3], [4,5,6], [7,8,9]] sage: s = c.symmetrize() ; s Fully symmetric 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: c[:], s[:] ( [1 2 3] [1 3 5] [4 5 6] [3 5 7] [7 8 9], [5 7 9] ) sage: c.symmetrize() == c.symmetrize(0,1) True - >>> from sage.all import * >>> from sage.tensor.modules.comp import Components >>> V = VectorSpace(QQ, Integer(3)) >>> c = Components(QQ, V.basis(), Integer(2)) >>> c[:] = [[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9)]] >>> s = c.symmetrize() ; s Fully symmetric 2-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> c[:], s[:] ( [1 2 3] [1 3 5] [4 5 6] [3 5 7] [7 8 9], [5 7 9] ) >>> c.symmetrize() == c.symmetrize(Integer(0),Integer(1)) True - Full symmetrization of 3-indices components: - sage: c = Components(QQ, V.basis(), 3) sage: c[:] = [[[1,2,3], [4,5,6], [7,8,9]], [[10,11,12], [13,14,15], [16,17,18]], [[19,20,21], [22,23,24], [25,26,27]]] sage: s = c.symmetrize() ; s Fully symmetric 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: c[:], s[:] ([[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16, 17, 18]], [[19, 20, 21], [22, 23, 24], [25, 26, 27]]], [[[1, 16/3, 29/3], [16/3, 29/3, 14], [29/3, 14, 55/3]], [[16/3, 29/3, 14], [29/3, 14, 55/3], [14, 55/3, 68/3]], [[29/3, 14, 55/3], [14, 55/3, 68/3], [55/3, 68/3, 27]]]) sage: all(s[i,j,k] == (c[i,j,k]+c[i,k,j]+c[j,k,i]+c[j,i,k]+c[k,i,j]+c[k,j,i])/6 # Check of the result: ....: for i in range(3) for j in range(3) for k in range(3)) True sage: c.symmetrize() == c.symmetrize(0,1,2) True - >>> from sage.all import * >>> c = Components(QQ, V.basis(), Integer(3)) >>> c[:] = [[[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9)]], [[Integer(10),Integer(11),Integer(12)], [Integer(13),Integer(14),Integer(15)], [Integer(16),Integer(17),Integer(18)]], [[Integer(19),Integer(20),Integer(21)], [Integer(22),Integer(23),Integer(24)], [Integer(25),Integer(26),Integer(27)]]] >>> s = c.symmetrize() ; s Fully symmetric 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> c[:], s[:] ([[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16, 17, 18]], [[19, 20, 21], [22, 23, 24], [25, 26, 27]]], [[[1, 16/3, 29/3], [16/3, 29/3, 14], [29/3, 14, 55/3]], [[16/3, 29/3, 14], [29/3, 14, 55/3], [14, 55/3, 68/3]], [[29/3, 14, 55/3], [14, 55/3, 68/3], [55/3, 68/3, 27]]]) >>> all(s[i,j,k] == (c[i,j,k]+c[i,k,j]+c[j,k,i]+c[j,i,k]+c[k,i,j]+c[k,j,i])/Integer(6) # Check of the result: ... for i in range(Integer(3)) for j in range(Integer(3)) for k in range(Integer(3))) True >>> c.symmetrize() == c.symmetrize(Integer(0),Integer(1),Integer(2)) True - Partial symmetrization of 3-indices components: - sage: s = c.symmetrize(0,1) ; s # symmetrization on the first two indices 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1) sage: c[:], s[:] ([[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16, 17, 18]], [[19, 20, 21], [22, 23, 24], [25, 26, 27]]], [[[1, 2, 3], [7, 8, 9], [13, 14, 15]], [[7, 8, 9], [13, 14, 15], [19, 20, 21]], [[13, 14, 15], [19, 20, 21], [25, 26, 27]]]) sage: all(s[i,j,k] == (c[i,j,k]+c[j,i,k])/2 # Check of the result: ....: for i in range(3) for j in range(3) for k in range(3)) True sage: s = c.symmetrize(1,2) ; s # symmetrization on the last two indices 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (1, 2) sage: c[:], s[:] ([[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16, 17, 18]], [[19, 20, 21], [22, 23, 24], [25, 26, 27]]], [[[1, 3, 5], [3, 5, 7], [5, 7, 9]], [[10, 12, 14], [12, 14, 16], [14, 16, 18]], [[19, 21, 23], [21, 23, 25], [23, 25, 27]]]) sage: all(s[i,j,k] == (c[i,j,k]+c[i,k,j])/2 # Check of the result: ....: for i in range(3) for j in range(3) for k in range(3)) True sage: s = c.symmetrize(0,2) ; s # symmetrization on the first and last indices 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 2) sage: c[:], s[:] ([[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16, 17, 18]], [[19, 20, 21], [22, 23, 24], [25, 26, 27]]], [[[1, 6, 11], [4, 9, 14], [7, 12, 17]], [[6, 11, 16], [9, 14, 19], [12, 17, 22]], [[11, 16, 21], [14, 19, 24], [17, 22, 27]]]) sage: all(s[i,j,k] == (c[i,j,k]+c[k,j,i])/2 # Check of the result: ....: for i in range(3) for j in range(3) for k in range(3)) True - >>> from sage.all import * >>> s = c.symmetrize(Integer(0),Integer(1)) ; s # symmetrization on the first two indices 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 1) >>> c[:], s[:] ([[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16, 17, 18]], [[19, 20, 21], [22, 23, 24], [25, 26, 27]]], [[[1, 2, 3], [7, 8, 9], [13, 14, 15]], [[7, 8, 9], [13, 14, 15], [19, 20, 21]], [[13, 14, 15], [19, 20, 21], [25, 26, 27]]]) >>> all(s[i,j,k] == (c[i,j,k]+c[j,i,k])/Integer(2) # Check of the result: ... for i in range(Integer(3)) for j in range(Integer(3)) for k in range(Integer(3))) True >>> s = c.symmetrize(Integer(1),Integer(2)) ; s # symmetrization on the last two indices 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (1, 2) >>> c[:], s[:] ([[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16, 17, 18]], [[19, 20, 21], [22, 23, 24], [25, 26, 27]]], [[[1, 3, 5], [3, 5, 7], [5, 7, 9]], [[10, 12, 14], [12, 14, 16], [14, 16, 18]], [[19, 21, 23], [21, 23, 25], [23, 25, 27]]]) >>> all(s[i,j,k] == (c[i,j,k]+c[i,k,j])/Integer(2) # Check of the result: ... for i in range(Integer(3)) for j in range(Integer(3)) for k in range(Integer(3))) True >>> s = c.symmetrize(Integer(0),Integer(2)) ; s # symmetrization on the first and last indices 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ], with symmetry on the index positions (0, 2) >>> c[:], s[:] ([[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16, 17, 18]], [[19, 20, 21], [22, 23, 24], [25, 26, 27]]], [[[1, 6, 11], [4, 9, 14], [7, 12, 17]], [[6, 11, 16], [9, 14, 19], [12, 17, 22]], [[11, 16, 21], [14, 19, 24], [17, 22, 27]]]) >>> all(s[i,j,k] == (c[i,j,k]+c[k,j,i])/Integer(2) # Check of the result: ... for i in range(Integer(3)) for j in range(Integer(3)) for k in range(Integer(3))) True 
 - trace(pos1, pos2)[source]¶
- Index contraction. - INPUT: - pos1– position of the first index for the contraction (with the convention position=0 for the first slot)
- pos2– position of the second index for the contraction
 - OUTPUT: - set of components resulting from the (pos1, pos2) contraction 
 - EXAMPLES: - Self-contraction of a set of components with 2 indices: - sage: from sage.tensor.modules.comp import Components sage: V = VectorSpace(QQ, 3) sage: c = Components(QQ, V.basis(), 2) sage: c[:] = [[1,2,3], [4,5,6], [7,8,9]] sage: c.trace(0,1) 15 sage: c[0,0] + c[1,1] + c[2,2] # check 15 - >>> from sage.all import * >>> from sage.tensor.modules.comp import Components >>> V = VectorSpace(QQ, Integer(3)) >>> c = Components(QQ, V.basis(), Integer(2)) >>> c[:] = [[Integer(1),Integer(2),Integer(3)], [Integer(4),Integer(5),Integer(6)], [Integer(7),Integer(8),Integer(9)]] >>> c.trace(Integer(0),Integer(1)) 15 >>> c[Integer(0),Integer(0)] + c[Integer(1),Integer(1)] + c[Integer(2),Integer(2)] # check 15 - Three self-contractions of a set of components with 3 indices: - sage: v = Components(QQ, V.basis(), 1) sage: v[:] = (-1,2,3) sage: a = c*v ; a 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: s = a.trace(0,1) ; s # contraction on the first two indices 1-index components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] sage: s[:] [-15, 30, 45] sage: [sum(a[j,j,i] for j in range(3)) for i in range(3)] # check [-15, 30, 45] sage: s = a.trace(0,2) ; s[:] # contraction on the first and last indices [28, 32, 36] sage: [sum(a[j,i,j] for j in range(3)) for i in range(3)] # check [28, 32, 36] sage: s = a.trace(1,2) ; s[:] # contraction on the last two indices [12, 24, 36] sage: [sum(a[i,j,j] for j in range(3)) for i in range(3)] # check [12, 24, 36] - >>> from sage.all import * >>> v = Components(QQ, V.basis(), Integer(1)) >>> v[:] = (-Integer(1),Integer(2),Integer(3)) >>> a = c*v ; a 3-indices components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> s = a.trace(Integer(0),Integer(1)) ; s # contraction on the first two indices 1-index components w.r.t. [ (1, 0, 0), (0, 1, 0), (0, 0, 1) ] >>> s[:] [-15, 30, 45] >>> [sum(a[j,j,i] for j in range(Integer(3))) for i in range(Integer(3))] # check [-15, 30, 45] >>> s = a.trace(Integer(0),Integer(2)) ; s[:] # contraction on the first and last indices [28, 32, 36] >>> [sum(a[j,i,j] for j in range(Integer(3))) for i in range(Integer(3))] # check [28, 32, 36] >>> s = a.trace(Integer(1),Integer(2)) ; s[:] # contraction on the last two indices [12, 24, 36] >>> [sum(a[i,j,j] for j in range(Integer(3))) for i in range(Integer(3))] # check [12, 24, 36] 
 
- class sage.tensor.modules.comp.KroneckerDelta(ring, frame, start_index=0, output_formatter=None)[source]¶
- Bases: - CompFullySym- Kronecker delta \(\delta_{ij}\). - INPUT: - ring– commutative ring in which each component takes its value
- frame– frame with respect to which the components are defined; whatever type- frameis, it should have some method- __len__()implemented, so that- len(frame)returns the dimension, i.e. the size of a single index range
- start_index– (default: 0) first value of a single index; accordingly a component index i must obey- start_index <= i <= start_index + dim - 1, where- dim = len(frame).
- output_formatter– (default:- None) function or unbound method called to format the output of the component access operator- [...](method- __getitem__);- output_formattermust take 1 or 2 arguments: the first argument must be an instance of- ringand the second one, if any, some format specification
 - EXAMPLES: - The Kronecker delta on a 3-dimensional space: - sage: from sage.tensor.modules.comp import KroneckerDelta sage: V = VectorSpace(QQ,3) sage: d = KroneckerDelta(QQ, V.basis()) ; d Kronecker delta of size 3x3 sage: d[:] [1 0 0] [0 1 0] [0 0 1] - >>> from sage.all import * >>> from sage.tensor.modules.comp import KroneckerDelta >>> V = VectorSpace(QQ,Integer(3)) >>> d = KroneckerDelta(QQ, V.basis()) ; d Kronecker delta of size 3x3 >>> d[:] [1 0 0] [0 1 0] [0 0 1] - One can read, but not set, the components of a Kronecker delta: - sage: d[1,1] 1 sage: d[1,1] = 2 Traceback (most recent call last): ... TypeError: the components of a Kronecker delta cannot be changed - >>> from sage.all import * >>> d[Integer(1),Integer(1)] 1 >>> d[Integer(1),Integer(1)] = Integer(2) Traceback (most recent call last): ... TypeError: the components of a Kronecker delta cannot be changed - Examples of use with output formatters: - sage: d = KroneckerDelta(QQ, V.basis(), output_formatter=Rational.numerical_approx) sage: d[:] # default format (53 bits of precision) [ 1.00000000000000 0.000000000000000 0.000000000000000] [0.000000000000000 1.00000000000000 0.000000000000000] [0.000000000000000 0.000000000000000 1.00000000000000] sage: d[:,10] # format = 10 bits of precision [ 1.0 0.00 0.00] [0.00 1.0 0.00] [0.00 0.00 1.0] sage: d = KroneckerDelta(QQ, V.basis(), output_formatter=str) sage: d[:] [['1', '0', '0'], ['0', '1', '0'], ['0', '0', '1']] - >>> from sage.all import * >>> d = KroneckerDelta(QQ, V.basis(), output_formatter=Rational.numerical_approx) >>> d[:] # default format (53 bits of precision) [ 1.00000000000000 0.000000000000000 0.000000000000000] [0.000000000000000 1.00000000000000 0.000000000000000] [0.000000000000000 0.000000000000000 1.00000000000000] >>> d[:,Integer(10)] # format = 10 bits of precision [ 1.0 0.00 0.00] [0.00 1.0 0.00] [0.00 0.00 1.0] >>> d = KroneckerDelta(QQ, V.basis(), output_formatter=str) >>> d[:] [['1', '0', '0'], ['0', '1', '0'], ['0', '0', '1']]