Tensors#

A tensor has the following information associated with it:-

  • A commutative ring \(K\) of coefficients.

  • A valence \({\nu}\) indicating the number of variables to include in its associated multilinear map.

  • A list \([U_{\nu},\dots, U_0]\) of \(K\)-modules called the frame.

  • A function \(U_{\nu}\times \cdots \times U_1\to U_0\) that is \(K\)-linear in each \(U_i\).

Tensors have type TenSpcElt and are formally elements of a tensor space (type TenSpc). By default a tensor’s parent space is a universal tensor space:

\[\hom_K(U_v,\dots,\hom_K(U_1,U_0)\cdots) \cong \hom_K(U_v\otimes_K\cdots \otimes_K U_1,U_0).\]

The left hand module is primarily used because it avoids the need to work with the equivalence classes of a tensor product. Operations such as linear combinations of tensors take place within a tensor space. A tensor space has attributes such as coefficients, valence, and frame.

When necessary, the user may further direct the operations on tensors to appropriate tensor categories (type TenCat). For instance covariant and contravariant variables can be specified and symmetry conditions can be imposed. If no tensor category is prescribed then a default tensor category is selected based on the method of creation.

Creating Tensors#

Black-box Tensors#

A user can specify a tensor by a black-box function that evaluates the required multilinear map.

Tensor(S, F): SeqEnum, UserProgram -> TenSpcElt, List#
Tensor(S, F): List, UserProgram -> TenSpcElt, List#
Tensor(S, F, Cat): SeqEnum, UserProgram, TenCat -> TenSpcElt, List#
Tensor(S, F, Cat): List, UserProgram, TenCat -> TenSpcElt, List#

Returns a tensor \(T\) and a list of maps from the given frame into vector spaces of the returned frame. Note that \(T\) is a tensor over vector spaces—essentially forgetting all other structure. The last entry of \(S\) is assumed to be the codomain of the multilinear map. The user-defined function \(F\) should take as input a tuple of elements of the domain and return an element of the codomain. If no tensor category is provided, then Albert’s homotopism category is used.

Example: BB Tensors Frame (ex-cdbf81)#

We demonstrate the black-box constructions by first constructing the dot product \(\cdot : {\mathbb{Q}}^4\times {\mathbb{Q}}^4\rightarrowtail {\mathbb{Q}}\). The function used to evaluate our black-box tensor, Dot, must take exactly one argument. The argument will be a Tup, an element of the Cartesian product \(U_{\nu}\times \cdots\times U_1\). Note that x[i] is the \(i\)th entry in the tuple and not the \(i\)th coordinate.

> Q := Rationals();
> U := VectorSpace(Q, 4);
> V := VectorSpace(Q, 4);
> W := VectorSpace(Q, 1);  // Vector space, not the field Q
> Dot := func< x | x[1]*Matrix(4, 1, Eltseq(x[2])) >;

Run in calculator

Now we will construct the tensor from the data above. The first object returned is the tensor, and the second is a list of maps, mapping the given frame into the vector space frame. In this example, since the given frame consists of vector spaces, these maps are trivial. Note that the list of maps are not needed to work with the given tensor, we will demonstrate this later.

> Tensor([U, V, W], Dot);
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 4 over Rational Field
U1 : Full Vector space of degree 4 over Rational Field
U0 : Full Vector space of degree 1 over Rational Field
[*
    Mapping from: ModTupFld: U to ModTupFld: U given by a rule,
    Mapping from: ModTupFld: U to ModTupFld: U given by a rule,
    Mapping from: ModTupFld: W to ModTupFld: W given by a rule
*]

Run in calculator

We will provide a tensor category for the dot product tensor, so that the returned tensor is not in the default homotopism category. We will use instead the \(\{2,1\}\)-adjoint category. While the returned tensor prints out the same as above, it does indeed live in a universe, see the section on Tensor Categories (TenCat).

> Cat := AdjointCategory(3, 2, 1);
> Cat;
Tensor category of valence 3 (<-,->,==) ({ 1 },{ 2 },{ 0 })
>
> t := Tensor([U, V, W], Dot, Cat);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 4 over Rational Field
U1 : Full Vector space of degree 4 over Rational Field
U0 : Full Vector space of degree 1 over Rational Field
>
> TensorCategory(t);
Tensor category of valence 3 (<-,->,==) ({ 1 },{ 2 },{ 0 })

Run in calculator

Example: BB Cross Product (ex-82ef8c)#

We will construct the cross product \(\times : {\mathbb{R}}^3\times {\mathbb{R}}^3\rightarrowtail {\mathbb{R}}^3\) and verify that \({\bf i}\times {\bf j} = {\bf k}\). However, to do this test, we will input integer sequences (specifically [RngIntElt]), and we will still be able to evaluate.

> K := RealField(5);
> V := VectorSpace(K, 3);
> CP := function(x)
>   return V![x[1][2]*x[2][3] - x[1][3]*x[2][2],
>     x[1][3]*x[2][1] - x[1][1]*x[2][3],
>     x[1][1]*x[2][2] - x[1][2]*x[2][1] ];
> end function;
> t := Tensor([V, V, V], CP);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 3 over Real field of precision 5
U1 : Full Vector space of degree 3 over Real field of precision 5
U0 : Full Vector space of degree 3 over Real field of precision 5
>
> // test that i x j = k
> <[1,0,0], [0,1,0]> @ t eq V.3;
true

Run in calculator

Tensor(D, C, F): SeqEnum, Any, UserProgram -> TenSpcElt, List#
Tensor(D, C, F): List, Any, UserProgram -> TenSpcElt, List#
Tensor(D, C, F, Cat): SeqEnum, Any, UserProgram, TenCat -> TenSpcElt, List#
Tensor(D, C, F, Cat): List, Any, UserProgram, TenCat -> TenSpcElt, List#

Returns a tensor \(T\) and a list of maps from the given frame into vector spaces of the returned frame. Note that \(T\) is a tensor over vector spaces—essentially forgetting all other structure. The user-defined function \(F\) should take as input a tuple of elements of \(D\) and return an element of \(C\). If no tensor category is provided, then Albert’s homotopism category is used.

Example: BB Triple Product (ex-e475ab)#

Tensors make it easy to create algebras that do not fit into traditional categories, such as algebras with triple products. Here, we create a triple product \(\langle \,\rangle : \rm{Mat}_{2\times 3}(K)\times \rm{Mat}_{2\times 3}(K)\times\rm{Mat}_{2\times 3}(K)\rightarrowtail \rm{Mat}_{2\times 3}(K)\), given by \(\langle A, B, C\rangle = AB^tC\).

> K := GF(541);
> U := KMatrixSpace(K,2,3);
> my_prod := func< x | x[1]*Transpose(x[2])*x[3] >;
> t := Tensor([U,U,U,U], my_prod );
> t;
Tensor of valence 4, U3 x U2 x U1 >-> U0
U3 : Full Vector space of degree 6 over GF(541)
U2 : Full Vector space of degree 6 over GF(541)
U1 : Full Vector space of degree 6 over GF(541)
U0 : Full Vector space of degree 6 over GF(541)

Run in calculator

Notice that the returned tensor is over vector spaces instead of the universe of KMatrixSpace. Tensors can still evaluate elements from the given frame, even though it prints out over vector spaces. However, the returned value form the tensor will be in the codomain of the tensor, so in this case, \(K^6\).

> A := U![1,0,0,0,0,0];
> A;
[  1   0   0]
[  0   0   0]
> <A,A,A>@t;  // A is a generalized idempotent
(  1   0   0   0   0   0)

Run in calculator

We can experiment to see if this triple product is left associative. To do this, we will construct five random matrices \(\{ X_1,\dots,X_5\}\subset \rm{Mat}_{2\times 3}(K)\), and then we test if

\[\langle \langle X_1, X_2, X_3 \rangle, X_4, X_5\rangle = \langle X_1, \langle X_4, X_3, X_2\rangle, X_5\rangle.\]

Observe that the tuples have mixed entries, one from \(K^6\) and two others from \(\rm{Mat}_{2\times 3}(K)\).

> X := [Random(U) : i  in [1..5]];
> X;
[
    [485 378 385]
    [241 505 134],

    [141 531 245]
    [472 484 339],

    [377  85 170]
    [451 522 334],

    [211 340 409]
    [ 95 349 128],

    [264 372 144]
    [205  47 428]
]
>
> A := <X[1],X[2],X[3]> @ t;
> B := <X[4],X[3],X[2]> @ t;
> A, B;
(460 436 181 341 134 404)
(465 420 458 421 291 225)
>
> <A, X[4], X[5]> @ t eq <X[1], B, X[5]> @ t;
true

Run in calculator

To confirm this product is left associative, we can create a new tensor for the left triple-associator and check that its image is \(0\). We will create a \(6\)-tensor

\[\{ \, \} : \prod_{k=1}^5 \rm{Mat}_{2\times 3}(K)\rightarrowtail \rm{Mat}_{2\times 3}(K)\]

where

\[\langle X_1,\dots, X_5\rangle = \langle \langle X_1, X_2, X_3 \rangle, X_4, X_5\rangle - \langle X_1, \langle X_4, X_3, X_2\rangle, X_5\rangle.\]

Therefore, if im\((\langle \, \rangle)=0\), then \(\langle \,\rangle\) is left associative.

> l_asct := func< X | Eltseq(<<X[1], X[2], X[3]> @ t, X[4], X[5]> @ t
>     - <X[1], <X[4], X[3], X[2]> @ t, X[5]> @ t) >;
> Lt := Tensor([* U : i in [0..5] *], l_asct);
> Lt;
Tensor of valence 6, U5 x U4 x U3 x U2 x U1 >-> U0
U5 : Full Vector space of degree 6 over GF(541)
U4 : Full Vector space of degree 6 over GF(541)
U3 : Full Vector space of degree 6 over GF(541)
U2 : Full Vector space of degree 6 over GF(541)
U1 : Full Vector space of degree 6 over GF(541)
U0 : Full Vector space of degree 6 over GF(541)
>
> I := Image(Lt);
> I;
Vector space of degree 6, dimension 0 over GF(541)
Generators:

>
> Dimension(I);
0

Run in calculator

Observe that in lasct the function Eltseq is called. This is because \(t\) returns vectors in \(K^6\) which is not naturally coercible into \(\rm{Mat}_{2\times 3}(K)\). On the other hand, sequences can be coerced into \(\rm{Mat}_{2\times 3}(K)\).

Tensors with Structure Constant Sequences#

Most computations with tensors \(T\) will be carried out using structure constants \(T_{j_{\nu}\cdots j_0}\in K\). Here \(T\) is framed by free \(K\)-modules \([U_{\nu},\dots,U_0]\) with each \(U_i\) having an ordered basis \({\cal B}_i=[e_{i1},\dots,e_{id_i}]\). The interpretation of structure constants is that the associated multilinear function \([x_{\nu},\dots,x_1]\) from \(U_{\nu}\times \cdots \times U_1\) into \(U_0\) is determined on bases \({\cal B}_i\) as follows:

\[[e_{{\nu}j_{\nu}},\dots,e_{1j_1} ] = \sum_{k=1}^{d_0} T_{j_{\nu} \cdots j_0} e_{0k}.\]

Structure constants are input and stored as sequences \(S\) in \(K\) according to the following assignment. Set \(f:{\mathbb{Z}}^{\nu+1}\to {\mathbb{Z}}\) to be:

\[f(j_{\nu},\dots,j_0) = 1+\sum_{s=0}^{\nu} (j_s-1)\prod_{t=0}^{s-1} d_t.\]

So \(S[f(j_{\nu},\dots,j_0)]=T_{j_{\nu}\cdots j_0}\) specifies the structure constants as a sequence.

Notes.

  • Magma does not currently support the notion of a sparse sequence of structure constants. A user can provide this functionality by specifying the multilinear function associated with a tensor by means of a user program rather than by structure constants.

  • Some routines in Magma require structure constant sequences. If they are not provided, Magma may compute and store a structure constant representation with the tensor.

  • Magma does not separate structure constant indices that are contravariant. Instead contravariant variables are signaled by tensor categories. So Ricci-styled tensors \(T_{a_p\cdots a_1}^{b_q\cdots b_1}\) should be input as \(T_{a_{p+q}\cdots a_{1+q} b_q\cdots b_1}\) and the tensor category changed to mark \(\{q,\dots,1\}\) as contravariant. Intrinsics are provided to facilitate this approach. See Section Tensor Categories for more details on tensor categories.

Tensor(D, S): [RngIntElt], SeqEnum -> TenSpcElt#
Tensor(R, D, S): Rng, [RngIntElt], SeqEnum -> TenSpcElt#
Tensor(D, S, Cat): [RngIntElt], SeqEnum, TenCat -> TenSpcElt#
Tensor(R, D, S, Cat): Rng, [RngIntElt], SeqEnum, TenCat -> TenSpcElt#

Let \(R\) be a commutative unital ring and \(D\) a sequence \([d_v, \ldots, d_0]\) giving the dimensions of the \(R\)-modules \(U_{v}, \ldots, U_{0}\). The intrinsic returns the tensor with frame { \(U_{v}, \ldots, U_{1} \rbrace\), codomain \(U_{0}\) and multilinear map defined by the structure constant sequence \(S\). If \(R\) is not specified then the parent ring of the first element of \(S\) is used. The default tensor category \(Cat\) is the homotopism category.

Example: SC Tensors (ex-3135bc)#

We will create structure constants sequence with all 0s and one 1 that occurs in the first entry. First, we will input this along with the dimensions of the tensor we are after, \(2\times 2\times 2\). However, since we did not specify a ring, it is assumed to be the parent ring of the first entry of the structure constants sequence. In this example, the ring is \({\mathbb{Z}}\).

> sc := [ 0 : i in [1..8] ];
> sc[1] := 1;
> Tensor([2, 2, 2], sc);
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full RSpace of degree 2 over Integer Ring
U1 : Full RSpace of degree 2 over Integer Ring
U0 : Full RSpace of degree 2 over Integer Ring

Run in calculator

We do not want the underlying ring to be \({\mathbb{Z}}\), so we will input the ring we want: GF\((64)\).

> K := GF(64);
> t := Tensor(K, [2, 2, 2], sc);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 2 over GF(2^6)
U1 : Full Vector space of degree 2 over GF(2^6)
U0 : Full Vector space of degree 2 over GF(2^6)
>
> Image(t);
Vector space of degree 2, dimension 1 over GF(2^6)
Generators:
(     1      0)
Echelonized basis:
(     1      0)

Run in calculator

We can recover the structure constants by calling StructureConstants or Eltseq. We will also test that the tensor evaluates inputs correctly.

> StructureConstants(t);
[ 1, 0, 0, 0, 0, 0, 0, 0 ]
>
> <[1, 0], [K.1^3, 0]> @ t;
( K.1^3      0)
>
> <[K.1^29, 1], [0, K.1^2]> @ t;
(     0      0)

Run in calculator

StructureConstants(T): TenSpcElt -> SeqEnum#
Eltseq(T): TenSpcElt -> SeqEnum#

Returns the sequence of structure constants of the given tensor \(T\).

Assign(T, ind, k): TenSpcElt, [RngIntElt], Any -> TenSpcElt#
Assign(~T, ind, k): TenSpcElt, [RngIntElt], Any#

Returns the tensor \(T\) where the ind element (viewed as a multi-dimensional array) is replaced with \(k\). For example, replacing the \((a,b,c)\) entry of a \(3\)-tensor, set ind\(\,=[a,b,c]\).

Example: SC From BB Tensors (ex-73e82c)#

We will construct the natural Lie module action for \(\rm{SL}_2\), but we will construct it as a left module. To do this, we construct a function that takes elements from \(\rm{SL}_2\times V\) and returns an element that Magma can coerce into \(V\). We run a quick test to make sure our function runs on the trivial example; this is the only check the intrinsic runs on black-box tensors. Since \(\rm{SL}_2\) and \(V\) are part of different universes in Magma, we must use the List environment when constructing this black-box tensor.

> SL2 := MatrixLieAlgebra("A1", GF(7));
> V := VectorSpace(GF(7), 2);
> left_action := func< x | x[2]*Transpose(Matrix(x[1])) >;
> left_action(<SL2!0, V!0>);
(0 0)
>
> SL2 := MatrixLieAlgebra("A1", GF(7));
> V := VectorSpace(GF(7), 2);
> left_action := func< x | x[2]*Transpose(Matrix(x[1])) >;
> left_action(<SL2!0, V!0>);
(0 0)
>
> t := Tensor([* SL2, V, V *], left_action);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 3 over GF(7)
U1 : Full Vector space of degree 2 over GF(7)
U0 : Full Vector space of degree 2 over GF(7)

Run in calculator

Now we will extract the structure constants from this Lie module action. We will then construct a tensor with these structure constants and compare it with our first tensor above.

> StructureConstants(t);
[ 1, 0, 0, 6, 0, 0, 1, 0, 0, 1, 0, 0 ]
>
> s := Tensor([3, 2, 2], Eltseq(t));
> s;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 3 over GF(7)
U1 : Full Vector space of degree 2 over GF(7)
U0 : Full Vector space of degree 2 over GF(7)
>
> t eq s;
true

Run in calculator

Example: SC Stored (ex-80fd79)#

The structure constants are convenient data structure for nearly all the algorithms using tensors. In fact, most computations require structure constants, so we store the structure constants sequence with the tensor. This means that after the initial structure constant sequence computation, every time StructureConstants or Eltseq is called, Magma retrieves what was previously computed.

We will demonstrate this on a large black-box example, so some time is spent computing the structure constants. Of course, the exact timing will vary by machine. We will construct a product of two subalgebras of \(\rm{Mat}_{20}({\bf F}_{3})\), namely \(* : \rm{SL}_{20}({\bf F}_{3})\times \rm{Mat}_4({\bf F}_{3})\rightarrowtail \rm{Mat}_{20}({\bf F}_{3})\).

> SL20 := MatrixLieAlgebra("A19", GF(3));
> M4 := MatrixAlgebra(GF(3), 4);
> Prod := func< x | Matrix(x[1])*DiagonalJoin(<x[2] : i in [1..5]>) >;
> t := Tensor([* SL20, M4 *], MatrixAlgebra(GF(3), 20), Prod);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 399 over GF(3)
U1 : Full Vector space of degree 16 over GF(3)
U0 : Full Vector space of degree 400 over GF(3)

Run in calculator

We record the time it takes to initially compute the structure constants sequence, and then we record the time when we call the function again.

> time sc := StructureConstants(t);
Time: 58.670
>
> time sc := StructureConstants(t);
Time: 0.000

Run in calculator

Bilinear Tensors#

In the special case of bilinear maps \(U_2\times U_1\rightarrowtail U_0\), the structure constant sequences may be presented as lists \([M_1,\dots, M_a]\) of matrices. This can be considered as a left (resp. right) representation \(U_2\to \hom_K(U_1,U_0)\), (resp.\(U_1\to \hom_K(U_2,U_0)\)). Alternatively, bilinear maps can be treated as systems of bilinear forms \([M_1,\dots,M_a]\) where the matrices are the Gram matrices of bilinear forms \(\phi_i:U_2\times U_1\rightarrowtail K\). Here the associated bilinear map \(U_2\times U_1\rightarrowtail U_0\) is specified by

\[(u_2,u_1) \mapsto ( \phi_1(u_2,u_1),\dots, \phi_a(u_2,u_1)).\]
Tensor(M, s, t): [Mtrx], RngIntElt, RngIntElt -> TenSpcElt#
Tensor(M, s, t, C): [Mtrx], RngIntElt, RngIntElt, TenCat -> TenSpcElt#

Given a sequence of matrices \(M\), the bilinear tensor specified by \(M\) is returned. The interpretation of the matrices as structure constant sequences is determined by the coordinates \(s\) and \(t\) which must be integers from the set \(\{2,1,0\}\). Optionally a tensor category \(C\) can be specified.

Example: Symplectic Form (ex-be1f50)#

We will construct a symplectic bilinear form on \(V=K^8\). It would be cumbersome to construct this tensor as a black-box tensor or by providing the structure constants sequence. Instead, we will provide a (Gram) matrix.

> K := GF(17);
> MS := KMatrixSpace(K, 2, 2);
> J := KroneckerProduct(IdentityMatrix(K, 4), MS![0, 1, -1, 0]);
> J;
[ 0  1  0  0  0  0  0  0]
[16  0  0  0  0  0  0  0]
[ 0  0  0  1  0  0  0  0]
[ 0  0 16  0  0  0  0  0]
[ 0  0  0  0  0  1  0  0]
[ 0  0  0  0 16  0  0  0]
[ 0  0  0  0  0  0  0  1]
[ 0  0  0  0  0  0 16  0]
>
> t := Tensor(J, 2, 1);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 8 over GF(17)
U1 : Full Vector space of degree 8 over GF(17)
U0 : Full Vector space of degree 1 over GF(17)
>
> IsAlternating(t);
true

Run in calculator

Now we will construct the symplectic form using the black-box construction and verify that the two tensors are the same.

> V := VectorSpace(K, 8);
> symp := func< x | x[1]*J*Matrix(8, 1, Eltseq(x[2])) >;
> s := Tensor([V, V], VectorSpace(K, 1), symp);
> s;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 8 over GF(17)
U1 : Full Vector space of degree 8 over GF(17)
U0 : Full Vector space of degree 1 over GF(17)
>
> SystemOfForms(s);
[
    [ 0  1  0  0  0  0  0  0]
    [16  0  0  0  0  0  0  0]
    [ 0  0  0  1  0  0  0  0]
    [ 0  0 16  0  0  0  0  0]
    [ 0  0  0  0  0  1  0  0]
    [ 0  0  0  0 16  0  0  0]
    [ 0  0  0  0  0  0  0  1]
    [ 0  0  0  0  0  0 16  0]
]

Run in calculator

AsMatrices(T, s, t): TenSpcElt, RngIntElt, RngIntElt -> SeqEnum#
SystemOfForms(T): TenSpcElt -> SeqEnum#

For a tensor \(T\) with frame \([K^{d_v},\dots,K^{d_0}]\), a list \([M_1,\dots,M_d]\), \(d=(d_v\cdots d_0)/d_s d_t\), of \((d_s\times d_t)\)-matrices in \(K\) representing the tensor as an element of \(\hom_K(K^{d_s}\otimes_K K^{d_t},K^d)\) is returned. For the intrinsic SystemOfForms, \(T\) must have valence \(2\) and the implied values are \(s=2\) and \(t=1\).

Example: Trilinear As Mats (ex-1d87b3)#

We construct the associator of \(\rm{SL}_2({\mathbb{Q}})\) where

\[\langle \, \rangle : \prod_{k=1}^3\rm{SL}_2\rightarrowtail \rm{SL}_2\]

given by

\[\langle x,y,z \rangle = [[x,y],z] - [x,[y,z]].\]

It can be hard to understand some of the features of this trilinear map by only looking at the structure constants sequence. The function AsMatrices slices the sequence and presents the data as a sequence of matrices.

> K := Rationals();
> L := LieAlgebra("A1", K);
> t := AssociatorTensor(L);
> t;
Tensor of valence 4, U3 x U2 x U1 >-> U0
U3 : Full Vector space of degree 3 over Rational Field
U2 : Full Vector space of degree 3 over Rational Field
U1 : Full Vector space of degree 3 over Rational Field
U0 : Full Vector space of degree 3 over Rational Field
>
> Eltseq(t);
[ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0,
0,-2, 0, 0, 0, 0, 0, 0, 0, 2, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 2, 0, 0, 0,
0, 0, 0, 0, -2, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2,
0, 0, 0, 0, 0, 0 ]

Run in calculator

Calling AsMatrices(t, 3, 1) returns a sequence of nine matrices, but we only show the first four. As explained in the documentation above, this sequence of matrices can be interpreted as the system of bilinear forms for the 3-tensor \(\circ_{31} : V_3 \times V_1 \rightarrowtail \hom_K(V_2,V_0)\) given by

\[x\circ_{31} z = \langle x, -,z \rangle = [[x,-],z] - [x,[-,z]].\]
> AsMatrices(t, 3, 1)[1..4];
[
    [ 0  0  2]
    [ 0  0  0]
    [-2  0  0],

    [ 0  0  0]
    [ 0  0  2]
    [ 0 -2  0],

    [0 0 0]
    [0 0 0]
    [0 0 0],

    [ 0  1  0]
    [-1  0  0]
    [ 0  0  0]
]

Run in calculator

Tensors from Algebraic Objects#

A natural and important source of tensors come from algebraic objects with a distributive property. One main source is from algebras, where \(*:A\times A\rightarrowtail A\) is given by multiplication in \(A\). Like with the previous sections on tensor constructions, all tensors will be constructed over vector spaces. The user can still input elements from the original algebra, but map(s) will also be returned. Furthermore, each tensor is assigned a category relevant to its origin, see the section on tensor categories for more information.

Tensor(A): Alg -> TenSpcElt, Map#

Given an algebra \(A\) with an element product that satisfies an appropriate distributive law, return the bilinear tensor given by the product in \(A\).

Example: D4Lie Algebra (ex-17021d)#

We want to get the Lie bracket from \(D_4(11)\). Tensors created from algebras will have a homotopism category, but with \(U_2=U_1=U_0\). This forces the operators acting to be the same on all the coordinates; in other words, \(\Omega=\rm{End}(U_2)\) instead of \(\Omega=\rm{End}(U_2)\times\rm{End}(U_1)\times\rm{End}(U_0)\).

> L := LieAlgebra("D4", GF(11));
> t := Tensor(L);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 28 over GF(11)
U1 : Full Vector space of degree 28 over GF(11)
U0 : Full Vector space of degree 28 over GF(11)
> IsAlternating(t);
true
> TensorCategory(t);
Tensor category of valence 3 (->,->,->) ({ 0, 1, 2 })

Run in calculator

If we compute the derivation algebra of \(L\), our operators will act in the same way on each coordinate. This is the standard definition of the derivation algebra of a ring.

> D := DerivationAlgebra(t);
> Dimension(D);
28
> SemisimpleType(D);
D4

Run in calculator

Now we will change the category to the standard homotopism category, where we do not fuse \(U_2\), \(U_1\), and \(U_0\).

> ChangeTensorCategory(~t, HomotopismCategory(3));
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 28 over GF(11)
U1 : Full Vector space of degree 28 over GF(11)
U0 : Full Vector space of degree 28 over GF(11)
> TensorCategory(t);
Tensor category of valence 3 (->,->,->) ({ 1 },{ 2 },{ 0 })

Run in calculator

We compare the same computation of derivation algebra. This time, the theory tells us that there will be a solvable radical. In this example, Rad\((D)=K^2\).

> D := DerivationAlgebra(t);
> Dimension(D);
30
> R := SolvableRadical(D);
> SemisimpleType(D/R);
D4

Run in calculator

Tensor(Q): RngUPolRes -> TenSpcElt, Map#

Returns the bilinear tensor given by the product in quotient polynomial ring \(Q\).

Example: Witt Algebra (ex-3ead54)#

The Witt algebra, over a finite field of characteristic \(p\), is isomorphic to the derivation algebra of \(K[x]/(x^p)\). The Witt algebra is a simple Lie algebra with dimension \(p\) and a trivial Killing form. First, we will construct the tensor from the ring \({\bf F}_{5}[x]/(x^5)\). Note that, like with algebras, the tensor category will fuse \(U_2\), \(U_1\), and \(U_0\), so that the operators act the same way on every coordinate.

> p := 5;
> R<x> := PolynomialRing(GF(p));
> I := ideal< R | x^p >;
> Q := quo< R | I >;
> Q;
Univariate Quotient Polynomial Algebra in $.1 over Finite field of size
5 with modulus $.1^5
> t := Tensor(Q);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 5 over GF(5)
U1 : Full Vector space of degree 5 over GF(5)
U0 : Full Vector space of degree 5 over GF(5)
> TensorCategory(t);
Tensor category of valence 3 (->,->,->) ({ 0, 1, 2 })

Run in calculator

Now we will construct a Lie representation of the Witt algebra from the tensor \(t\).

> D := DerivationAlgebra(t);
> IsSimple(D);
true
> Dimension(D);
5
> KillingForm(D);
[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]

Run in calculator

CommutatorTensor(A): Alg -> TenSpcElt, Map#
AnticommutatorTensor(A): Alg -> TenSpcElt, Map#

Given an algebra \(A\) return the tensor corresponding to the bilinear commutator map \([a,b]=ab-ba\) or the anticommutator map \(\langle a,b\rangle = ab+ba\) of the algebra \(A\). This should not be used to get the tensor given by the Lie or Jordan product in a Lie or Jordan algebra; instead use Tensor.

Example: Commutator From Algebra (ex-ad0163)#

We will construct the commutator tensor from \(\rm{Mat}_4({\mathbb{Q}})\).

> A := MatrixAlgebra(Rationals(), 4);
> t := CommutatorTensor(A);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 16 over Rational Field
U1 : Full Vector space of degree 16 over Rational Field
U0 : Full Vector space of degree 16 over Rational Field
> IsAlternating(t); // [X, X] = 0?
true

Run in calculator

With this tensor, we will compute the dimension of the centralizer of the diagonal matrix \(M\) with diagonal entries \((1,1,-1,-1)\) in \(\rm{Mat}_4({\mathbb{Q}})\). To do this, we will subtract the dimension of the image of \([M, A]\) from the dimension of \(A\).

> M := A![1,0,0,0,0,1,0,0,0,0,-1,0,0,0,0,-1];
> M;
[ 1  0  0  0]
[ 0  1  0  0]
[ 0  0 -1  0]
[ 0  0  0 -1]
> Dimension(A) - Dimension(<M, A> @ t);
8

Run in calculator

Example: Matrix Jordan Algebra (ex-b964df)#

This time, we will obtain a Jordan product from \(\rm{Mat}_4({\mathbb{Q}})\). That is, we will construct the bilinear map \(* : \rm{Mat}_4({\mathbb{Q}})\times \rm{Mat}_4({\mathbb{Q}})\rightarrowtail \rm{Mat}_4({\mathbb{Q}})\) where \(A*B = (AB+BA)/2\).

> A := MatrixAlgebra(Rationals(), 4);
> t := AnticommutatorTensor(A);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 16 over Rational Field
U1 : Full Vector space of degree 16 over Rational Field
U0 : Full Vector space of degree 16 over Rational Field
> SystemOfForms(t)[1];
[2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0]
[0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
> A.1*t*A.1;
(2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)

Run in calculator

From the documentation on AnticommutatorTensor, we have to scale our tensor above \(t\) by \(1/2\) to get what we want. Of course this won’t affect the proceeding tests though.

> s := (1/2)*t;
> A.1*s*A.1;
(1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)

Run in calculator

Now we will confirm that \(s\) is a Jordan product. First, we check that \(s\) is commutative, and then we check that it satisfies the Jordan identity: \((xy)(xx)=x(y(xx))\).

> IsSymmetric(s);
true
> JordanID := func< x, y | (x*s*y)*s*(x*s*x) - x*s*(y*s*(x*s*x)) >;
> forall{ <x,y> : x in Basis(A), y in Basis(A) |
>     JordanID(x, y) eq Codomain(s)!0 };
true

Run in calculator

AssociatorTensor(A): Alg -> TenSpcElt, Map#

Given an algebra \(A\) return the tensor corresponding to the trilinear associator map \([a,b,c]=(ab)c-a(bc)\) on the algebra \(A\).

Example: Associator From Algebra (ex-4acc3b)#

Do three random octonions satisfy the associate law? Hardly ever.

> O := OctonionAlgebra ( GF (1223) , -1 , -1 , -1);
> t := AssociatorTensor ( O );
> t;
Tensor of valence 4, U3 x U2 x U1 >-> U0
U3 : Full Vector space of degree 8 over GF(1223)
U2 : Full Vector space of degree 8 over GF(1223)
U1 : Full Vector space of degree 8 over GF(1223)
U0 : Full Vector space of degree 8 over GF(1223)
> <Random(O),Random(O),Random(O)> @ t eq O!0;
false

Run in calculator

However, for all \(a,b\in O\), \((aa)b=a(ab)\) as octonions are alternative algebras.

> a := Random ( O );
> b := Random ( O );
> <a, a, b> @ t eq O!0;
true
> IsAlternating ( t );
true

Run in calculator

pCentralTensor(G, p, s, t): Grp, RngIntElt, RngIntElt, RngIntElt -> TenSpcElt, List#
pCentralTensor(G, s, t): GrpPC, RngIntElt, RngIntElt -> TenSpcElt, List#
pCentralTensor(G, s, t): Grp, RngIntElt, RngIntElt -> TenSpcElt, List#
pCentralTensor(G): Grp -> TenSpcElt, List#

Returns the bilinear map of commutation from the associated graded Lie algebra of the lower exponent-\(p\) central series \(\eta\) of \(G\). The bilinear map pairs \(\eta_s/\eta_{s+1}\) with \(\eta_{t}/\eta_{t+1}\) into \(\eta_{s+t}/\eta_{s+t+1}\). If \(s=t\) the tensor category is set to force \(U_2=U_1\); otherwise it is the general homotopism category. In addition, maps from the subgroups into the vector spaces are returned as a list. If \(p\), \(s\), and \(t\) are not given, it is assumed \(G\) is a \(p\)-group and \(s=t=1\).

Example: Tensor P Group (ex-94b48f)#

Groups have a single binary operation. So even when groups are built from rings it can be difficult to recover the ring from the group operations. Tensors supply one approach for that task. We will get the \(p\)-central tensor of \(G=\rm{SL}(3,125)\); however, we will lose the fact that there is a field \({\bf F}_{125}\). The tensor we will get back is \([,] : K^6\times K^6 \rightarrowtail K^3\), where \(K={\bf F}_{5}\).

> P := ClassicalSylow(SL(3,125), 5);
> Q := PCGroup(P);     // The group Q won't have explicit knowledge of GF(125).
> Q;
GrpPC : Q of order 1953125 = 5^9
PC-Relations:
    Q.4^Q.1 = Q.4 * Q.7^4,
    Q.4^Q.2 = Q.4 * Q.8^4,
    Q.4^Q.3 = Q.4 * Q.9^4,
    Q.5^Q.1 = Q.5 * Q.8^4,
    Q.5^Q.2 = Q.5 * Q.9^4,
    Q.5^Q.3 = Q.5 * Q.7^3 * Q.8^3,
    Q.6^Q.1 = Q.6 * Q.9^4,
    Q.6^Q.2 = Q.6 * Q.7^3 * Q.8^3,
    Q.6^Q.3 = Q.6 * Q.8^3 * Q.9^3
> t := pCentralTensor(Q);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 6 over GF(5)
U1 : Full Vector space of degree 6 over GF(5)
U0 : Full Vector space of degree 3 over GF(5)

Run in calculator

Knowing that \(G\) is defined over \({\bf F}_{125}\), we know that the commutator is really just the alternating form \(\cdot : {\bf F}_{125}^2\times {\bf F}_{125}^2\rightarrowtail {\bf F}_{125}\). This information can be extracted from the centroid of \(t\) above, and we can rewrite \(t\) over the field \({\bf F}_{125}\).

> F := Centroid(t);  // Recover GF(125)
> Dimension(F);
3
> IsSimple(F);
true
> IsCommutative(F);
true
> s := TensorOverCentroid(t);
> s;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 2 over GF(5^3)
U1 : Full Vector space of degree 2 over GF(5^3)
U0 : Full Vector space of degree 1 over GF(5^3)

Run in calculator

MatrixTensor(K, S): Fld, [RngIntElt] -> TenSpcElt, List#

Given a field \(K\) and a sequence of positive integers \(S=[s_1,\dots, s_{\nu}]\), return the tensor

\[\rm{Mat}_{s_1\times s_2}(K) \times \cdots \times \rm{Mat}_{s_{\nu-1}\times s_{\nu}}(K)\rightarrowtail \rm{Mat}_{s_1\times s_{\nu}}(K),\]

given by matrix multiplication. A list of maps from the matrix spaces to the vector spaces is given as well even though the given tensor will evaluate matrices as well.

Polarisation(f): MPolElt -> TenSpcElt, MPolElt#
Polarisation(f): RngUPolElt -> TenSpcElt#
Polarization(f): MPolElt -> TenSpcElt, MPolElt#
Polarization(f): RngUPolElt -> TenSpcElt#

Returns the polarization of the homogeneous multivariate polynomial \(f\) as a tensor and as a multivariate polynomial. Note that the intrinsic does not normalize by \(1/d!\), where \(d\) is the degree of \(f\).

Example: Tensor Polarization (ex-794950)#

The polarization intrinsic is applied to the polynomial \(f(x, y) = x^2 y\). Because \(f\) is homogeneous of degree 3 with 2 variables, it is expected that the polarization will have 6 variables and that the corresponding multilinear form will be \(K^2\times K^2\times K^2\rightarrowtail K\). The polarization of \(f\) is given by \(P(x_1,x_2,y_1,y_2,z_1,z_2 ) = 2 (x_1y_1z_2 + x_1y_2z_1 + x_2y_1z_1)\).

> R<x,y> := PolynomialRing(Rationals(), 2);
> T, p := Polarization(x^2*y);
> p;
2*$.1*$.3*$.6 + 2*$.1*$.4*$.5 + 2*$.2*$.3*$.5
> T;
Tensor of valence 4, U3 x U2 x U1 >-> U0
U3 : Full Vector space of degree 2 over Rational Field
U2 : Full Vector space of degree 2 over Rational Field
U1 : Full Vector space of degree 2 over Rational Field
U0 : Full Vector space of degree 1 over Rational Field
> <[1,0],[1,0],[1,0]> @ T;
(0)
> <[1,0],[1,0],[0,1]> @ T;
(2)

Run in calculator

New Tensors from Old#

A number of new tensors may be constructed from a given tensor.

AlternatingTensor(T): TenSpcElt -> TenSpcElt#

Returns the alternating tensor induced by the given tensor \(T\). If the tensor is already alternating, then the given tensor is returned.

AntisymmetricTensor(T): TenSpcElt -> TenSpcElt#

Returns the antisymmetric tensor induced by the given tensor \(T\). If the tensor is already antisymmetric, then the given tensor is returned.

SymmetricTensor(T): TenSpcElt -> TenSpcElt#

Returns the symmetric tensor induced by the given tensor \(T\). If the tensor is already symmetric, then the given tensor is returned.

Example: Alternating Tensor (ex-3641e3)#

Tensors coming from Lie algebras are alternating. If we call AlternatingTensor on a tensor from a Lie algebra, nothing will be changed.

> L := LieAlgebra("A3", GF(3));
> t := Tensor(L);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 15 over GF(3)
U1 : Full Vector space of degree 15 over GF(3)
U0 : Full Vector space of degree 15 over GF(3)
> AlternatingTensor(t) eq t;
true

Run in calculator

Example: Make Symmetric (ex-73d5eb)#

We will make the tensor coming from the product in \(\rm{Mat}_3({\mathbb{Q}})\) symmetric.

> A := MatrixAlgebra(Rationals(), 3);
> t := Tensor(A);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 9 over Rational Field
U1 : Full Vector space of degree 9 over Rational Field
U0 : Full Vector space of degree 9 over Rational Field
> SystemOfForms(t)[1];
[1 0 0 0 0 0 0 0 0]
[0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 0 1 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0]

Run in calculator

The first matrix in the sequence of bilinear forms of \(t\) is not symmetric, so \(t\) is not symmetric (of course matrix multiplication is not commutative also). We will construct a symmetric version of \(t\) and inspect the first matrix of the bilinear forms.

> s := SymmetricTensor(t);
> s;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 9 over Rational Field
U1 : Full Vector space of degree 9 over Rational Field
U0 : Full Vector space of degree 9 over Rational Field
> SystemOfForms(s)[1];
[2 0 0 0 0 0 0 0 0]
[0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 0 1 0 0]
[0 1 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 1 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0]

Run in calculator

Shuffle(T, g): TenSpcElt, GrpPermElt -> TenSpcElt#
Shuffle(T, g): TenSpcElt, SeqEnum -> TenSpcElt#

Given a tensor \(T\) in \(\hom(U_{\nu},\dots,\hom(U_1,U_0)\cdots)\), this intrinsic generates the representation of \(T\) in

\[\hom(U_{{\nu}^g},\dots,\hom(U_{1^g},U_{0^g})\dots),\]

where \(g\) is a permutation of \(\{0,\dots,\nu \}\). The permutation \(g\) may be given as an element of a permutation group or as a sequence. Both the image and pre-image of \(0\) under \(g\) will be replaced by their \(K\)-dual space. For cotensors, \(g\) must permute \(\{1,\dots,\nu \}\). Sequences \([a_1,\dots,a_{\nu+1}]\) will be interpreted as a permutation in one-line notation.

Example: Shuffle To Transpose (ex-e67343)#

We will shuffle the alternating form \({\mathbb{Q}}^2\times{\mathbb{Q}}^2\rightarrowtail {\mathbb{Q}}\) as a means of performing a transpose on the Gram matrix. To do this, we need to shuffle by the transposition \((1, 2)\) in Sym\((\{0,1,2\})\).

> t := Tensor(Rationals(), [2, 2, 1], [0, 1, -1, 0]);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 2 over Rational Field
U1 : Full Vector space of degree 2 over Rational Field
U0 : Full Vector space of degree 1 over Rational Field
> SystemOfForms(t);
[
    [ 0  1]
    [-1  0]
]
>
> s := Shuffle(t, [0,2,1]);
> s;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 2 over Rational Field
U1 : Full Vector space of degree 2 over Rational Field
U0 : Full Vector space of degree 1 over Rational Field
> SystemOfForms(s);
[
    [ 0 -1]
    [ 1  0]
]

Run in calculator

Example: Shuffling (ex-ae928f)#

We will generate a random 5-tensor and shuffle it with \((0,2,4,1,3)\).

> t := RandomTensor(GF(2), [5,4,3,2,1]);
> t;
Tensor of valence 5, U4 x U3 x U2 x U1 >-> U0
U4 : Full Vector space of degree 5 over GF(2)
U3 : Full Vector space of degree 4 over GF(2)
U2 : Full Vector space of degree 3 over GF(2)
U1 : Full Vector space of degree 2 over GF(2)
U0 : Full Vector space of degree 1 over GF(2)
>
> G := Sym({0..4});
> g := G![2, 3, 4, 0, 1];
> g;
(0, 2, 4, 1, 3)
>
> s := Shuffle(t, g);
> s;
Tensor of valence 5, U4 x U3 x U2 x U1 >-> U0
U4 : Full Vector space of degree 2 over GF(2)
U3 : Full Vector space of degree 1 over GF(2)
U2 : Full Vector space of degree 5 over GF(2)
U1 : Full Vector space of degree 4 over GF(2)
U0 : Full Vector space of degree 3 over GF(2)

Run in calculator

TensorProduct(t, s): TenSpcElt, TenSpcElt -> TenSpcElt#

Given \(K\)-tensors \(t:U_{\nu}\times \cdots \times U_1\rightarrowtail U_0\) and \(s:V_{\nu}\times \cdots \times V_1\rightarrowtail V_0\), returns the tensor \(t\otimes s : U_{\nu}\otimes V_{\nu}\times \cdots \times U_1\otimes V_1\rightarrowtail U_0\otimes V_0\). This is like a generalized Kronecker product.

Operations with Tensors#

Magma supports two perspectives for operations with tensors. Firstly, tensors determine multilinear maps and so behave as functions. Secondly, tensors are elements of a tensor space and so behave as elements of a module.

Elementary Operations#

Treating the tensor space as a \(K\)-module, we have the standard operations.

S + T: TenSpcElt, TenSpcElt -> TenSpcElt#
S - T: TenSpcElt, TenSpcElt -> TenSpcElt#
k * T: RngElt, TenSpcElt -> TenSpcElt#
-T: TenSpcElt -> TenSpcElt#

Given tensors \(S\) and \(T\) belonging to the same tensor space \(V\), and an element \(k\) belonging to the coefficient ring \(K\), these intrinsics return the sum, difference, scalar multiple or additive inverse of \(S\) and \(T\) as elements of \(V\). The corresponding multilinear maps are the sum, difference, scalar multiple or additive inverse of the multilinear maps.

Example: Module Operations (ex-ce9931)#

As tensors are elements of a tensor space, it inherits module operations. We will demonstrate them all here. First, here are the tensors we will operate with.

> K := Rationals();
> t := Tensor(K, [2, 2, 2], [1..8]);
> s := Tensor(K, [2, 2, 2], &cat[[2, -1] : i in [1..4]]);
> SystemOfForms(t);
[
    [1 3]
    [5 7],

    [2 4]
    [6 8]
]
> SystemOfForms(s);
[
    [2 2]
    [2 2],

    [-1 -1]
    [-1 -1]
]

Run in calculator

Now we perform the module operations.

> SystemOfForms(-t);
[
    [-1 -3]
    [-5 -7],

    [-2 -4]
    [-6 -8]
]
> SystemOfForms((1/3)*s);
[
    [2/3 2/3]
    [2/3 2/3],

    [-1/3 -1/3]
    [-1/3 -1/3]
]
> SystemOfForms(t+s);
[
    [3 5]
    [7 9],

    [1 3]
    [5 7]
]
> SystemOfForms(t-2*s);
[
    [-3 -1]
    [ 1  3],

    [ 4  6]
    [ 8 10]
]

Run in calculator

AssociatedForm(T): TenSpcElt -> TenSpcElt#

For a tensor \(T\) with frame \(U_{\nu}\times \cdots \times U_1\rightarrowtail U_0\), this intrinsic creates the associated multilinear form \(U_{\nu}\times\cdots\times U_1\times U_0^*\rightarrowtail K\). The valence is increased by \(1\).

Compress(T): TenSpcElt -> TenSpcElt#
Compress(~T): TenSpcElt#

Returns the compression of the tensor \(T\). This removes all 1-dimensional spaces in the domain.

Example: Compress Assoc Form (ex-9d2ed1)#

We will construct the associated form of the tensor from the Lie algebra \(B_3(5)\). The codomain of the original tensor gets moved (and dualed) to the domain.

> L := LieAlgebra("B3", GF(5));
> t := Tensor(L);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 21 over GF(5)
U1 : Full Vector space of degree 21 over GF(5)
U0 : Full Vector space of degree 21 over GF(5)
> s := AssociatedForm(t);
> s;
Tensor of valence 4, U3 x U2 x U1 >-> U0
U3 : Full Vector space of degree 21 over GF(5)
U2 : Full Vector space of degree 21 over GF(5)
U1 : Full Vector space of degree 21 over GF(5)
U0 : Full Vector space of degree 1 over GF(5)
> <L.2, L.11> @ t;
(0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
> <L.2, L.11, L.2> @ s;
(4)
> <L.2, L.11, L> @ s;
Full Vector space of degree 1 over GF(5)
Generators:
(4)

Run in calculator

We shuffle the associated form by the permutation \((0,3)\) and compress it. The result is just the shuffle of the original bilinear map \(t\) by \((0,2,1)\).

> shf := Shuffle(s, [3,1,2,0]);
> shf;
Tensor of valence 4, U3 x U2 x U1 >-> U0
U3 : Full Vector space of degree 1 over GF(5)
U2 : Full Vector space of degree 21 over GF(5)
U1 : Full Vector space of degree 21 over GF(5)
U0 : Full Vector space of degree 21 over GF(5)
> cmp := Compress(shf);
> cmp;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 21 over GF(5)
U1 : Full Vector space of degree 21 over GF(5)
U0 : Full Vector space of degree 21 over GF(5)
> cmp eq Shuffle(t, [2, 0, 1]);
true

Run in calculator

General Properties#

We provide basic intrinsics to retrieve data stored in the TenSpcElt object in Magma. Most of these functions are already stored as attributes. The ones that are not initially stored at construction are stored immediately after the initial computation, such as Image.

Parent(T): TenSpcElt -> TenSpc#

Returns the tensor space that contains the tensor \(T\). The default space is the universal tensor space.

Domain(T): TenSpcElt -> List#

Returns the domain of the tensor \(T\) as a list of modules.

Codomain(T): TenSpcElt -> Any#

Returns the codomain of the tensor \(T\).

Valence(T): TenSpcElt -> RngIntElt#

Returns the valence of the tensor \(T\).

Frame(T): TenSpcElt -> List#

Returns the modules in the frame of the tensor \(T\) in the form of a list containing the domain modules and the codomain.

BaseRing(T): TenSpcElt -> Rng#
BaseField(T): TenSpcElt -> Fld#

Returns the base ring or field of the tensor \(T\).

Example: Basic Props (ex-7020de)#

We demonstrate how to get basic properties of a tensor and what to expect as an output. We will construct a tensor \(*:\rm{Mat}_{2\times 3}({\mathbb{Q}})\times {\mathbb{Q}}^3\rightarrowtail {\mathbb{Q}}^2\) given by multiplication. Nearly all of this information is displayed when printing a tensor.

> K := Rationals();
> U2 := KMatrixSpace(K, 2, 3);
> U1 := VectorSpace(K, 3);
> U0 := VectorSpace(K, 2);
> mult := func< x | Eltseq(x[1]*Matrix(3,1,Eltseq(x[2]))) >;
> t := Tensor([* U2, U1, U0 *], mult);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 6 over Rational Field
U1 : Full Vector space of degree 3 over Rational Field
U0 : Full Vector space of degree 2 over Rational Field
>
> Parent(t);
Tensor space of dimension 36 over Rational Field with valence 3
U2 : Full Vector space of degree 6 over Rational Field
U1 : Full Vector space of degree 3 over Rational Field
U0 : Full Vector space of degree 2 over Rational Field
>
> Domain(t);
[*
    Full Vector space of degree 6 over Rational Field,

    Full Vector space of degree 3 over Rational Field
*]
>
> Codomain(t);
Full Vector space of degree 2 over Rational Field
>
> Valence(t);
3
>
> Frame(t);
[*
    Full Vector space of degree 6 over Rational Field,

    Full Vector space of degree 3 over Rational Field,

    Full Vector space of degree 2 over Rational Field
*]
> BaseRing(t);
Rational Field

Run in calculator

TensorCategory(T): TenSpcElt -> TenCat#

Returns the underlying tensor category of tensor \(T\).

ChangeTensorCategory(T, C): TenSpcElt, TenCat -> TenSpcElt#
ChangeTensorCategory(~T, C): TenSpcElt, TenCat#

Returns the tensor \(T\) with the given category.

IsCovariant(T): TenSpcElt -> BoolElt#
IsContravariant(T): TenSpcElt -> BoolElt#

Returns true if the underlying category of the tensor \(T\) is covariant or contravariant.

Example: Tensor Cat Props (ex-bef887)#

We will construct a tensor from a right module, \(*:{\mathbb{Q}}^2 \times \rm{Mat}_{2\times 2}({\mathbb{Q}})\rightarrowtail {\mathbb{Q}}^2\).

> K := Rationals();
> U := KMatrixSpace(K, 2, 2);
> V := VectorSpace(K, 2);
> mult := func< x | x[1]*x[2] >;
> t := Tensor([* V, U, V *], mult);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 2 over Rational Field
U1 : Full Vector space of degree 4 over Rational Field
U0 : Full Vector space of degree 2 over Rational Field

Run in calculator

Because this tensor comes from a module, we want the tensor category to reflect this. Currently, the tensor category is the default homotopism category. We will keep everything about the category the same, except we will fuse coordinates 2 and 0. These changes could easily go unnoticed if no operators are constructed.

> TensorCategory(t);
Tensor category of valence 3 (->,->,->) ({ 1 },{ 2 },{ 0 })
> Cat := TensorCategory([1, 1, 1], {{2,0},{1}});
> Cat;
Tensor category of valence 3 (->,->,->) ({ 1 },{ 0, 2 })
> ChangeTensorCategory(~t, Cat);
> TensorCategory(t);
Tensor category of valence 3 (->,->,->) ({ 1 },{ 0, 2 })
> IsCovariant(t);
true

Run in calculator

NondegenerateTensor(T): TenSpcElt -> TenSpcElt, Hmtp#

Returns the nondegenerate tensor associated to \(T\) along with a homotopism from the given tensor to the returned nondegenerate tensor.

IsNondegenerate(T): TenSpcElt -> BoolElt#
IsDegenerate(T): TenSpcElt -> BoolElt#

Returns true if \(T\) is a degenerate or nondegenerate multilinear map.

Example: Nondegeneracy (ex-f6f9ff)#

An important property for tensors is nondegeneracy: all radicals are trivial. First we create a tensor with degeneracy.

> K := GF(541);
> V := VectorSpace(K, 10);
> U := VectorSpace(K, 5);
> mult := function(x)
>   M := Matrix(3, 3, Eltseq(x[1])[2..10]);
>   v := VectorSpace(K, 3)!(Eltseq(x[2])[[1,3,5]]);
>   return Eltseq(v*M) cat [0,0];
> end function;
> t := Tensor([V, U, U], mult);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 10 over GF(541)
U1 : Full Vector space of degree 5 over GF(541)
U0 : Full Vector space of degree 5 over GF(541)

Run in calculator

In this example, both \(U_{\widehat{2}}^\perp\) and \(U_{\widehat{1}}^\perp\) are nontrivial. We will construct the associated nondegenerate tensor \(s\), which is given by \(U_2/U_{\widehat{2}}^\perp \times U_1/U_{\widehat{1}}^\perp \rightarrowtail U_0\).

> IsNondegenerate(t);
false
> s, H := NondegenerateTensor(t);
> s;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 9 over GF(541)
U1 : Full Vector space of degree 3 over GF(541)
U0 : Full Vector space of degree 5 over GF(541)
> H;
Maps from U2 x U1 >-> U0 to V2 x V1 >-> V0.
U2 -> V2: Mapping from: Full Vector space of degree 10 over GF(541) to
Full Vector space of degree 9 over GF(541)
U1 -> V1: Mapping from: Full Vector space of degree 5 over GF(541) to
Full Vector space of degree 3 over GF(541)
U0 -> V0: Mapping from: Full Vector space of degree 5 over GF(541) to
Full Vector space of degree 5 over GF(541)

Run in calculator

Image(T): TenSpcElt -> ModTupRng#

Returns the image of the tensor \(T\).

FullyNondegenerateTensor(T): TenSpcElt -> TenSpcElt, Hmtp#

Returns the fully nondegenerate multilinear map associated to tensor \(T\) along with a cohomotopism from the given tensor to the returned tensor.

IsFullyNondegenerate(T): TenSpcElt -> BoolElt#

Returns true if the tensor \(T\) is a fully nondegenerate multilinear map.

Example: Fully Nondegenerate (ex-f9b7b8)#

We use the same tensor as the previous example illustrating the use of NondegenerateTensor.

> K := GF(541);
> V := VectorSpace(K, 10);
> U := VectorSpace(K, 5);
> mult := function(x)
>   M := Matrix(3, 3, Eltseq(x[1])[2..10]);
>   v := VectorSpace(K, 3)!(Eltseq(x[2])[[1,3,5]]);
>   return Eltseq(v*M) cat [0,0];
> end function;
> t := Tensor([V, U, U], mult);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 10 over GF(541)
U1 : Full Vector space of degree 5 over GF(541)
U0 : Full Vector space of degree 5 over GF(541)

Run in calculator

Here, we want to construct a fully nondegenerate tensor. Of course, the tensor form the previous example is not fully nondegenerate as it is not degenerate, but we check that the image is not isomorphic to the codomain.

> IsFullyNondegenerate(t);
false
> Image(t);
Vector space of degree 5, dimension 3 over GF(541)
Generators:
(  1   0   0   0   0)
(  0   1   0   0   0)
(  0   0   1   0   0)
Echelonized basis:
(  1   0   0   0   0)
(  0   1   0   0   0)
(  0   0   1   0   0)

Run in calculator

Now we will construct the associated fully nondegenerate tensor: \(U_2/U_{\widehat{2}}^\perp\times U_1/U_{\widehat{1}}^\perp\rightarrowtail U_2*U_1\). Notice that the morphism between the original tensor and the fully nondegenerate tensor is a cohomotopism.

> s, H := FullyNondegenerateTensor(t);
> s;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 9 over GF(541)
U1 : Full Vector space of degree 3 over GF(541)
U0 : Vector space of degree 5, dimension 3 over GF(541)
Generators:
(  1   0   0   0   0)
(  0   1   0   0   0)
(  0   0   1   0   0)
Echelonized basis:
(  1   0   0   0   0)
(  0   1   0   0   0)
(  0   0   1   0   0)
> H;
Maps from U2 x U1 >-> U0 to V2 x V1 >-> V0.
U2 -> V2: Mapping from: Full Vector space of degree 10 over GF(541) to
Full Vector space of degree 9 over GF(541)
U1 -> V1: Mapping from: Full Vector space of degree 5 over GF(541) to
Full Vector space of degree 3 over GF(541)
U0 <- V0: Mapping from: Full Vector space of degree 5 over GF(541) to
Full Vector space of degree 5 over GF(541)
Composition of Mapping from: Full Vector space of degree 5 over GF(541)
to Full Vector space of degree 5 over GF(541) and
Mapping from: Vector space of degree 5, dimension 3 over GF(541) to Full
Vector space of degree 5 over GF(541)

Run in calculator

IsAlternating(T): TenSpcElt -> BoolElt#

Returns true if the tensor \(T\) is an alternating tensor.

IsAntisymmetric(T): TenSpcElt -> BoolElt#

Returns true if the tensor \(T\) is an antisymmetric tensor.

IsSymmetric(T): TenSpcElt -> BoolElt#

Returns true if the tensor \(T\) is a symmetric tensor.

Example: Symmetric Polar (ex-6f9baa)#

We will construct the multilinear form given by polarizing the homogeneous polynomial \(f(x,y,z)=x^3+y^3+z^3+xyz\). Since \(f\) is a symmetric polynomial, its multilinear form is also symmetric.

> K := Rationals();
> R<x,y,z> := PolynomialRing(K, 3);
> f := x^3 + y^3 + z^3 + x*y*z;
> t, p := Polarization(f);
> p;
6*$.1*$.4*$.7 + $.1*$.5*$.9 + $.1*$.6*$.8 + $.2*$.4*$.9 +
    6*$.2*$.5*$.8 + $.2*$.6*$.7 + $.3*$.4*$.8 + $.3*$.5*$.7 +
    6*$.3*$.6*$.9
> t;
Tensor of valence 4, U3 x U2 x U1 >-> U0
U3 : Full Vector space of degree 3 over Rational Field
U2 : Full Vector space of degree 3 over Rational Field
U1 : Full Vector space of degree 3 over Rational Field
U0 : Full Vector space of degree 1 over Rational Field

Run in calculator

The resulting homogeneous polynomial from polarizing is

\[p(x_1,x_2,x_3,y_1,y_2,y_3,z_1,z_2,z_3) =\sum_{\sigma\in S_3} (x_{1^\sigma}y_{2^\sigma}z_{3^\sigma} + 3x_{1^\sigma}y_{1^\sigma}z_{1^\sigma}).\]
> IsSymmetric(t);
true
> AsMatrices(t, 3, 1) eq AsMatrices(t, 2, 1);
true
> AsMatrices(t, 3, 1) eq AsMatrices(t, 3, 2);
true
> AsMatrices(t, 3, 1);
[
    [6 0 0]
    [0 0 1]
    [0 1 0],

    [0 0 1]
    [0 6 0]
    [1 0 0],

    [0 1 0]
    [1 0 0]
    [0 0 6]
]

Run in calculator

Because the underlying field is \({\mathbb{Q}}\) and because \(t\) is symmetric, we know that \(t\) is not alternating nor antisymmetric.

> IsAlternating(t);
false
> IsAntisymmetric(t);
false

Run in calculator

Tensors As Multilinear Maps#

Regarding tensors as multilinear maps makes it possible to define the operations of composition and evaluation for tensors.

x @ T: Tup, TenSpcElt -> Any#

Evaluates the tensor \(T\) at \(x\in U_{\nu}\times \cdots \times U_1\). The entries can be elements from the vector space \(U_i\) or sequences that Magma can naturally coerce into the vector space \(U_i\). In some circumstances, tensors come from algebraic objects (e.g. algebras), and in these cases the entries of \(x\) can be contained in the original algebraic object as well.

Example: Multi Map Eval (ex-be5d59)#

Here we create the 4-tensor \(\langle \,\rangle\) of an algebra \(A\) given by the Jacobi identity:

\[(x,y,z)\mapsto (xy)z + (yz)x + (zx)y.\]

Therefore, the algebra satisfies the Jacobi identity if \(\langle A, A, A \rangle = 0\). We will also change the tensor category so that all the coordinates are fused together.

> A := MatrixAlgebra(GF(3), 3);
> JacobiID := func< x | x[1]*x[2]*x[3]+x[2]*x[3]*x[1]+x[3]*x[1]*x[2] >;
> Cat := TensorCategory([1 : i in [0..3]], {{0..3}});
> t, maps := Tensor([A : i in [0..3]], JacobiID, Cat);
> t;
Tensor of valence 4, U3 x U2 x U1 >-> U0
U3 : Full Vector space of degree 9 over GF(3)
U2 : Full Vector space of degree 9 over GF(3)
U1 : Full Vector space of degree 9 over GF(3)
U0 : Full Vector space of degree 9 over GF(3)
> TensorCategory(t);
Tensor category of valence 4 (->,->,->,->) ({ 0 .. 3 })

Run in calculator

Even though our tensor originated over the algebra \(A=\rm{Mat}_{3}({\bf F}_{3})\), the returned tensor is over vector spaces \({\bf F}_{3}^9\). However, the tensor \(t\) can still evaluate elements from \(\rm{Mat}_3({\bf F}_{3})\) as well as \({\bf F}_{3}^9\). Observe that the out of \(t\) will be a vector regardless of the input. The second output at construction, the List of maps, can be used to map the vectors to \(\rm{Mat}_3({\bf F}_{3})\).

> x := <A.1, A.2, A.2^2>;
> x;
<
    [1 0 0]
    [0 0 0]
    [0 0 0],

    [0 1 0]
    [0 0 1]
    [1 0 0],

    [0 0 1]
    [1 0 0]
    [0 1 0]
>
> x @ t;
(2 0 0 0 1 0 0 0 0)
>
> phi := maps[1];
> x := <A.1 @ phi, A.2 @ phi, (A.2^2) @ phi>;
> x;
<(1 0 0 0 0 0 0 0 0), (0 1 0 0 0 1 1 0 0), (0 0 1 1 0 0 0 1 0)>
> x @ t;
(2 0 0 0 1 0 0 0 0)

Run in calculator

Because @ takes Tup as input, \(t\) can evaluate mixed tuples as well: where some entries are contained in \(\rm{Mat}_3({\bf F}_{3})\) and other entries are contained in \({\bf F}_{3}^9\).

> x := <A.1, A.2 @ phi, Eltseq(A.2^2)>;
> x;
<
    [1 0 0]
    [0 0 0]
    [0 0 0],

    (0 1 0 0 0 1 1 0 0),

    [ 0, 0, 1, 1, 0, 0, 0, 1, 0 ]
>
> <Type(i) : i in x>;
<AlgMatElt, ModTupFldElt, SeqEnum>
> x @ t;
(2 0 0 0 1 0 0 0 0)

Run in calculator

T * f: TenSpcElt, Map -> TenSpcElt#
t * s: TenSpcElt, TenSpcElt -> TenSpcElt#

The tensor formed by composing the tensor \(T\) with the map \(f\) is constructed. If a tensor \(s\) is used instead of a Map, \(s\) must have valence \(\leq 1\).

S eq T: TenSpcElt, TenSpcElt -> BoolElt#

Returns true if the tensors \(S\) and \(T\) are the same. Two tensors are equivalent if, and only if, they have the same tensor category, base ring, frame, and structure constants.

Example: Tensor Comp (ex-0a17aa)#

We start with the same tensor as the previous example: the tensor given by the Jacobi identity on the algebra \(A=\rm{Mat}_3({\bf F}_{3})\).

> A := MatrixAlgebra(GF(3), 3);
> JacobiID := func< x | x[1]*x[2]*x[3]+x[2]*x[3]*x[1]+x[3]*x[1]*x[2] >;
> Cat := TensorCategory([1 : i in [0..3]], {{0..3}});
> t, maps := Tensor([A : i in [0..3]], JacobiID, Cat);
> t;
Tensor of valence 4, U3 x U2 x U1 >-> U0
U3 : Full Vector space of degree 9 over GF(3)
U2 : Full Vector space of degree 9 over GF(3)
U1 : Full Vector space of degree 9 over GF(3)
U0 : Full Vector space of degree 9 over GF(3)
> TensorCategory(t);
Tensor category of valence 4 (->,->,->,->) ({ 0 .. 3 })

Run in calculator

The maps in Maps are vector space isomorphisms and map \(A\) to \(V\). Suppose \(\phi: A\rightarrow V\) is a vector space isomorphism. If we compose \(t\) with \(\phi^{-1}\), the returned tensor is still over vector spaces. The codomain is not \(A\); this is because all tensors are over vector spaces. In fact, the returned tensor is exactly the same as \(t\).

> phi := maps[1];
> t * (phi^-1);
Tensor of valence 4, U3 x U2 x U1 >-> U0
U3 : Full Vector space of degree 9 over GF(3)
U2 : Full Vector space of degree 9 over GF(3)
U1 : Full Vector space of degree 9 over GF(3)
U0 : Full Vector space of degree 9 over GF(3)
> t * (phi^-1) eq t;
true

Run in calculator

Let \({\cal E}\subset A\) be an orthogonal frame—a set of primitive, orthogonal, idempotents. We will compose \(t\) with the linear transformation

\[a \mapsto \sum_{e\in{\cal E}} eae.\]

Because the codomain of \(t\) is a vector space, we will precompose this map by \(\phi^{-1}\).

> E := [A.1, A.2^-1*A.1*A.2, A.2^-2*A.1*A.2^2];
> E;
[
    [1 0 0]
    [0 0 0]
    [0 0 0],

    [0 0 0]
    [0 1 0]
    [0 0 0],

    [0 0 0]
    [0 0 0]
    [0 0 1]
]
> f := map< A -> A | x :-> &+[ E[i]*x*E[i] : i in [1..3] ] >;
> f;
Mapping from: AlgMat: A to AlgMat: A given by a rule [no inverse]
> s := t*(phi^-1*f);
> s;
Tensor of valence 4, U3 x U2 x U1 >-> U0
U3 : Full Vector space of degree 9 over GF(3)
U2 : Full Vector space of degree 9 over GF(3)
U1 : Full Vector space of degree 9 over GF(3)
U0 : Full Vector space of degree 9 over GF(3)
> s eq t;
false

Run in calculator

We can also wrap \(f\) as a 2-tensor and compose it with \(t\).

> g := Tensor([A, A], func< x | x[1]@f >);
> g;
Tensor of valence 2, U1 >-> U0
U1 : Full Vector space of degree 9 over GF(3)
U0 : Full Vector space of degree 9 over GF(3)
> t * g eq s;
true

Run in calculator

Operations with Bilinear Maps#

Tensors of valence \(3\), also known as bilinear tensors, or as bilinear maps, are commonly described as distributive products. Examples include the product of two elements of an algebra, the action of a ring on a module, or an inner product. Magma supports these interpretations in two ways: by permitting an infix \(x*t*y\) notation for a 3-tensor \(t\), and a product \(x*y\) notation for the evaluation of bilinear tensors. For the latter, this is achieved by creating special types BmpU[Elt], BmpV[Elt], and BmpW[Elt] for the terms of the frame of a bilinear tensor. For bilinear maps, we refer to the modules in the frame as \(U\times V\rightarrowtail W\).

x * T: Any, TenSpcElt -> Any#
T * y: TenSpcElt, Any -> Any#

Given a bilinear tensor \(T\) framed by \([U, V, W]\), \(x*t\) returns the action on the right as a linear map \(L : V\rightarrow W\) given by \(vL = x* v\) if \(x\) is an element of \(U\). If \(x\) is a subspace of \(U\), then this returns a subspace of the tensor space \(T\) with frame \(V\rightarrowtail W\). For the left action use \(T*y\) instead. If \(T\) is valence 1, then the image of either \(x\) or \(y\) is returned. Therefore, the possible outputs are a tensor space TenSpc, a tensor TenSpcElt, or a vector ModTupFld.

Related to this intrinsic is the following: using tensor spaces with the infix notation.

x * T: Any, TenSpc -> Any#
T * y: TenSpc, Any -> Any#

Given a subspace of bilinear tensors, return the subspace generated by all \(x*t\), for \(t\in T\). This is either a tensor space or a vector space.

Example: Bimap Infix (ex-4ade75)#

We demonstrate the infix notation by constructing the tensor in \(A=\rm{Mat}_2({\mathbb{Q}})\) given by multiplication.

> A := MatrixAlgebra(Rationals(), 2);
> t := Tensor(A);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 4 over Rational Field
U1 : Full Vector space of degree 4 over Rational Field
U0 : Full Vector space of degree 4 over Rational Field

Run in calculator

Like tensor evaluation, the infix notation will accept elements of a vector space (or objects that Magma can easily coerce into a vector space) or elements from the original algebraic object. We will use the infix notation to construct the 2-tensor \(* : A\rightarrowtail A\), where \(X\mapsto MX\), for some matrix \(M\).

> M := A![0, 1, 0, 0];
> M;
[0 1]
[0 0]
> s := M*t;
> s;
Tensor of valence 2, U1 >-> U0
U1 : Full Vector space of degree 4 over Rational Field
U0 : Full Vector space of degree 4 over Rational Field
> AsMatrices(s, 1, 0);
[
    [0 0 0 0]
    [0 0 0 0]
    [1 0 0 0]
    [0 1 0 0]
]

Run in calculator

From the structure constants above, evaluating M*t at V.3 should output W.1. Furthermore, the image of M*t is 2-dimensional in \(W\).

> M*t*[0, 0, 1, 0];
(1 0 0 0)
> M*t*VectorSpace(Rationals(), 4);
Vector space of degree 4, dimension 2 over Rational Field
Generators:
(1 0 0 0)
(0 1 0 0)
Echelonized basis:
(1 0 0 0)
(0 1 0 0)

Run in calculator

If we switch the order and multiply \(t\) by \(U\) on the left first, we will get a tensor space \(T\). Because that tensor space came from \(t\), which originally came from algebraic objects, we can use the returned tensor space to evaluate \(M\). An arbitrary tensor space, however, would not evaluate \(M\) unless it is an appropriate vector.

> T := VectorSpace(Rationals(), 4)*t;
> T;
Tensor space of dimension 4 over Rational Field with valence 2
U1 : Full Vector space of degree 4 over Rational Field
U0 : Full Vector space of degree 4 over Rational Field
> T*M;
Vector space of degree 4, dimension 2 over Rational Field
Generators:
(0 1 0 0)
(0 0 0 1)
Echelonized basis:
(0 1 0 0)
(0 0 0 1)

Run in calculator

The next style of notation we support is the product notation, \(x*y\). In order to use this style, the user needs to coerce both \(x\) and \(y\) into the LeftDomain and RightDomain respectively.

x * y: BmpUElt, BmpVElt -> Any#
x * y: BmpU, BmpV -> Any#
x * y: BmpUElt, BmpV -> Any#
x * y: BmpU, BmpVElt -> Any#

If \(x\) and \(y\) are associated to the bilinear map \(B\), these operations return <x,y> @ B.

LeftDomain(B): TenSpcElt -> BmpU#

The left domain \(U\) of the bilinear map \(B\) with frame \([U,V,W]\) is returned. This operation is used when enabling the use of infix notation.

RightDomain(B): TenSpcElt -> BmpV#

The right domain \(U\) of the bilinear map \(B\) with frame \([U,V,W]\) is returned. This operation is used when enabling the use of infix notation.

IsCoercible(U, x): BmpU, Any -> BoolElt, BmpUElt#
IsCoercible(V, x): BmpV, Any -> BoolElt, BmpVElt#
U ! x: BmpU, Any -> BmpUElt#
V ! x: BmpV, Any -> BmpVElt#

Returns true if \(x\) can be coerced into the left domain (right domain) \(U\) (\(V\)) of a bilinear map. If successful it returns the coerced element.

Example: Bimap Product (ex-90f3f7)#

We demonstrate the product notation for tensors of valence 3 using a tensor derived from a \(p\)-group. Suppose \(G\) is a \(p\)-group and \([,] : U\times V\rightarrowtail W\) is the tensor given by commutation where \(U=V=G/\eta_2\) and \(W=\eta_2/\eta_3\), where \(\eta_i\) denotes the \(i\)th term of the exponent-\(p\) central series of \(G\).

> G := SmallGroup(512, 10^6);
> t := pCentralTensor(G);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 5 over GF(2)
U1 : Full Vector space of degree 5 over GF(2)
U0 : Full Vector space of degree 4 over GF(2)
> U := LeftDomain(t);
> V := RightDomain(t);
> U;
Bimap space U: Full Vector space of degree 5 over GF(2)
> V;
Bimap space V: Full Vector space of degree 5 over GF(2)

Run in calculator

Like with the other styles of notation (infix and tuple), users can evaluate elements from the original algebraic object, vectors from the vector spaces, and even sequences that Magma can easily coerce into vector spaces. To use the product notation, coerce elements into the LeftDomain and RightDomain.

> x := U!(G.1*G.2*G.4);
> y := V![1,0,0,0,0];
> x;
Bimap element of U: (1 1 0 1 0)
> y;
Bimap element of V: (1 0 0 0 0)
> x*y;
(1 0 0 1)

Run in calculator

We can take this further and evaluate subspaces of \(U\) or \(V\).

> H := sub< G | G.2,G.4 >;
> U!H * V!G.1;
Vector space of degree 4, dimension 2 over GF(2)
Generators:
(0 0 0 1)
(1 0 0 0)
Echelonized basis:
(1 0 0 0)
(0 0 0 1)
> U!H * V;
Vector space of degree 4, dimension 3 over GF(2)
Generators:
(1 0 0 0)
(0 0 1 0)
(0 0 0 1)
(1 0 0 0)
(1 0 0 0)
Echelonized basis:
(1 0 0 0)
(0 0 1 0)
(0 0 0 1)

Run in calculator

Parent(x): BmpUElt -> BmpU#
Parent(x): BmpVElt -> BmpV#

The parent space of the bilinear map element \(x\) is returned.

Parent(X): BmpU -> TenSpcElt#
Parent(X): BmpV -> TenSpcElt#

The original bilinear map from which the space \(X\) originated is returned.

u1 eq u2: BmpUElt, BmpUElt -> BoolElt#

Returns true if the elements \(u1\) and \(u2\) from the left domain of a bilinear map are equal.

v1 eq v2: BmpUElt, BmpUElt -> BoolElt#

Returns true if the elements \(v1\) and \(v2\) from the right domain of a bilinear map are equal.

U1 eq U2: BmpU, BmpU -> BoolElt#

Returns true if the subspaces \(U1\) and \(U2\) of the left domain of a bilinear map are equal.

V1 eq V2: BmpV, BmpV -> BoolElt#

Returns true if the subspaces \(V1\) and \(V2\) of the right domain of a bilinear map are equal.

Example: Bimap Product2 (ex-77d198)#

We will construct the same tensor as the previous example.

> G := SmallGroup(512, 10^6);
> t := pCentralTensor(G);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 5 over GF(2)
U1 : Full Vector space of degree 5 over GF(2)
U0 : Full Vector space of degree 4 over GF(2)
> U := LeftDomain(t);
> V := RightDomain(t);
> U;
Bimap space U: Full Vector space of degree 5 over GF(2)
> V;
Bimap space V: Full Vector space of degree 5 over GF(2)

Run in calculator

The product notation has some basic functions for comparing objects and retrieving information.

> V!G.1 eq V![1,0,0,0,0];
true
> Parent(U);
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 5 over GF(2)
U1 : Full Vector space of degree 5 over GF(2)
U0 : Full Vector space of degree 4 over GF(2)
> Parent(U) eq t;
true

Run in calculator

Manipulating Tensor Data#

The data associated with a tensor can be accessed in different ways. In the case of tensors given by structure constants this access is the multidimensional analog of choosing a row or column of a matrix. Other operations are a generalization of the transpose of a matrix. Magma does these operations with a degree of efficiency, that is, it may not physically move the values in a structure constant sequence but instead permute the lookup coordinates of the values.

Slice(T, grid): TenSpcElt, [SetEnum] -> SeqEnum#
InducedTensor(T, grid): TenSpcElt, [SetEnum] -> TenSpcElt#

Returns the slice of the structure constants running through the given grid. For a tensor \(T\) framed by free modules \([U_{\nu},\dots,U_0]\) with \(d_i=\dim U_i\), a grid is a sequence \([G_{\nu},\dots,G_0]\) of subsets \(G_i\subseteq \{1,\dots, d_i\}\cup \{-d_i,\dots, -1\}\). If an entry \(g\in G_i\) is negative, it will be taken to mean \(d_i+g+1\), so \(-1\) would be equivalent to \(d_i\). The slice is the list of entries in the structure constants of the tensor indexed by \(G_{\nu}\times \cdots \times G_0\). The intrinsic Slice returns the structure constants whereas InducedTensor produces a tensor with these structure constants.

Example: Tensor Slicing (ex-ff7268)#

We will construct a tensor \(*: {\mathbb{Q}}^4\times {\mathbb{Q}}^3\rightarrowtail {\mathbb{Q}}^2\) with a structure constants sequence equal to \([1,\dots,24]\). If every \(G_i=\{1,\dots, d_i\}\), then the result is the same as Eltseq.

> U := VectorSpace(Rationals(),4);
> V := VectorSpace(Rationals(),3);
> W := VectorSpace(Rationals(),2);
> T := TensorSpace([U, V, W]);
> t := T![1..24];
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 4 over Rational Field
U1 : Full Vector space of degree 3 over Rational Field
U0 : Full Vector space of degree 2 over Rational Field
> Slice(t, [{1..4},{1..3},{1..2}]) eq Eltseq(t);
true

Run in calculator

Now we will slice with the following grid \([\{1,\dots,4\}, \{2\}, \{1\}]\). Compare this with the product \(U*v_2\).

> [ U.i*t*V.2 : i in [1..4]];
[
    (3 4),
    ( 9 10),
    (15 16),
    (21 22)
]
> Slice(t, [{1..4},{2},{1}]);
[ 3, 9, 15, 21 ]

Run in calculator

If, instead, we slice \(W\) at its last basis vector, we get the following.

> Slice(t, [{1..4},{2},{-1}]);
[ 4, 10, 16, 22 ]

Run in calculator

Notice that if we use \(-1\) and \(2\) in the last set of the grid we get the same output we got above.

> Slice(t, [{1..4},{2},{-1,2}]);
[ 4, 10, 16, 22 ]

Run in calculator

Now we will compare Slice and InducedTensor. InducedTensor is basically a Tensor wrapping the Slice function.

> s := InducedTensor(t, [{1..4}, {2}, {1,2}]);
> s;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 4 over Rational Field
U1 : Full Vector space of degree 1 over Rational Field
U0 : Full Vector space of degree 2 over Rational Field
> s2 := Tensor([4, 1, 2], Slice(t, [{1..4}, {2}, {1,2}]));
> s2;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 4 over Rational Field
U1 : Full Vector space of degree 1 over Rational Field
U0 : Full Vector space of degree 2 over Rational Field
>
> s eq s2;
true
> Eltseq(s);
[ 3, 4, 9, 10, 15, 16, 21, 22 ]

Run in calculator

SliceAsMatrices(T, grid, a, b): TenSpcElt, [SetEnum], RngIntElt, RngIntElt -> SeqEnum#

Given a tensor \(T\), a set and integers \(a\) and \(b\), returns a sequence of matrices whose output is equivalent to composing InducedTensor and AsMatrices. This intrinsic will be slightly faster than actually composing those two functions together as a tensor is not constructed with SliceAsMatrices.

Example: Slice As Matrices (ex-436f03)#

We will create the same tensor as the previous example.

> t := Tensor(Rationals(), [4,3,2], [1..24]);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 4 over Rational Field
U1 : Full Vector space of degree 3 over Rational Field
U0 : Full Vector space of degree 2 over Rational Field
> AsMatrices(t, 1, 0);
[
    [1 2]
    [3 4]
    [5 6],

    [ 7  8]
    [ 9 10]
    [11 12],

    [13 14]
    [15 16]
    [17 18],

    [19 20]
    [21 22]
    [23 24]
]

Run in calculator

Now we will slice up this sequence of matrices. We will remove the second row and the second and third matrix from the sequence above.

> SliceAsMatrices(t, [{1,-1}, {1,-1}, {1,2}], 1, 0);
[
    [1 2]
    [5 6],

    [19 20]
    [23 24]
]

Run in calculator

Foliation(T, i): TenSpcElt, RngIntElt -> Mtrx#

If \(T\) is a tensor with frame \(\hom(U_{\nu}\otimes \cdots \otimes U_1,U_0)\), and \(i\) is the index of some term of the frame of \(T\), this intrinsic returns the matrix representing the linear map \(U_i\rightarrow \hom(\bigotimes_{j\ne i}U_i,U_0)\) using the bases of each \(U_j\). If \(i=0\), then the returned matrix is given by the representation \(U_0^*\rightarrow \hom(\bigotimes U_i,K)\).

Example: Exfoliate Foliation (ex-c6ce4b)#

We will, again, construct the same tensor, \(*:{\mathbb{Q}}^4\times{\mathbb{Q}}^3\rightarrowtail {\mathbb{Q}}^2\), from the previous two examples whose structure constants sequence is \([1,\dots,24]\).

> K := Rationals();
> Forms := [Matrix(K, 3, 2, [6*i+1..6*(i+1)]) : i in [0..3]];
> t := Tensor(Forms, 1, 0);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 4 over Rational Field
U1 : Full Vector space of degree 3 over Rational Field
U0 : Full Vector space of degree 2 over Rational Field

Run in calculator

We will use Foliation to compute the 2-radical of \(t\). (This is essentially what Radical does in Magma.) That is, we will compute the subspace \(U_{\hat{2}}^\perp\leq {\mathbb{Q}}^4\) such that \(U_{\hat{2}}^\perp*{\mathbb{Q}}^3=0\). This computation can be regarded as a nullspace computation.

> F2 := Foliation(t, 2);
> F2;
[ 1  2  3  4  5  6]
[ 7  8  9 10 11 12]
[13 14 15 16 17 18]
[19 20 21 22 23 24]
> R := Nullspace(F2);
> R;
Vector space of degree 4, dimension 2 over Rational Field
Echelonized basis:
( 1  0 -3  2)
( 0  1 -2  1)

Run in calculator

We claim this is the 2-radical of \(t\). Our claim is verified if R*t is a 0-dimensional subspace of the tensor space \(T\) with frame \({\mathbb{Q}}^3\rightarrowtail{\mathbb{Q}}^2\). In other words, R*t is the trivial 2-tensor.

> R*t;
Tensor space of dimension 0 over Rational Field with valence 2
U1 : Full Vector space of degree 3 over Rational Field
U0 : Full Vector space of degree 2 over Rational Field
> Dimension(R*t);
0

Run in calculator

AsTensorSpace(T, i): TenSpcElt, RngIntElt -> TenSpc, Mtrx#

If \(T\) is a tensor contained in \(\hom(U_v\otimes \cdots \otimes U_1,U_0)\), and \(i\) is the index of some term of the frame of \(T\), this intrinsic returns the associated tensor space of \(T\) at \(i>0\) together with a matrix given by the foliation of \(T\) at \(i\). The returned tensor space is framed by \(U_v\times \cdots \times U_{i+1}\times U_{i-1}\times \cdots \times U_1\rightarrowtail U_0\) and is generated by the tensors \(T_u\) for each \(u\) in the basis of \(U_i\). For \(i=0\), use AsCotensorSpace.

AsCotensorSpace(T): TenSpcElt -> TenSpc, Mtrx#

Given a tensor \(T\), this intrinsic returns the associated cotensor space of \(T\) together with a matrix given by the foliation of \(T\) at \(0\). The returned cotensor space has frame \(U_{\nu}\times \cdots \times U_1\rightarrowtail K\) and is generated by the tensors \(T_f\) for each \(f\) in the basis of \(U_0^*\). In the case that \(T\) is a bilinear map, this is equivalent to the cotensor space generated by the SystemOfForms.

Example: Tensors To Spaces (ex-8523ef)#

We begin by creating a 4-tensor and constructing the associated tensor space at the third coordinate. AsCotensorSpace works similarly but when \(a=0\).

> t := Tensor(Rationals(), [5,4,3,2], [1..120]);
> t;
Tensor of valence 4, U3 x U2 x U1 >-> U0
U3 : Full Vector space of degree 5 over Rational Field
U2 : Full Vector space of degree 4 over Rational Field
U1 : Full Vector space of degree 3 over Rational Field
U0 : Full Vector space of degree 2 over Rational Field
> T := AsTensorSpace(t, 3);
> T;
Tensor space of dimension 2 over Rational Field with valence 3
U2 : Full Vector space of degree 4 over Rational Field
U1 : Full Vector space of degree 3 over Rational Field
U0 : Full Vector space of degree 2 over Rational Field

Run in calculator

The dimension of \(T\) cannot be larger than 5 because that is the dimension of \(U_3\). However, \(T\) is 2-dimensional. Slicing \(t\) as a sequence of matrices will illuminate why \(T\) is 2-dimensional.

> F := [SliceAsMatrices(t, [{k},{1..4},{1..3},{1,2}], 2, 1) :
>     k in [1..5]];

Run in calculator

Here, \(F\) is a sequence of a system of forms for \(t\), one for each basis vector in \(U_3\). If \(T\) were 5-dimensional, the systems of forms in \(F\) would be linearly independent. However, it is not, and evidently, three of the five systems of forms are linear combinations two systems of forms. We will determine the linear combinations. The first two systems of forms are independent.

> F[1];
[
    [ 1  3  5]
    [ 7  9 11]
    [13 15 17]
    [19 21 23],

    [ 2  4  6]
    [ 8 10 12]
    [14 16 18]
    [20 22 24]
]
> F[2];
[
    [25 27 29]
    [31 33 35]
    [37 39 41]
    [43 45 47],

    [26 28 30]
    [32 34 36]
    [38 40 42]
    [44 46 48]
]

Run in calculator

So F[3] is 2*F[2]-F[1], and the rest of the linear combinations are filled in.

> F[3];
[
    [49 51 53]
    [55 57 59]
    [61 63 65]
    [67 69 71],

    [50 52 54]
    [56 58 60]
    [62 64 66]
    [68 70 72]
]
> Tensor(F[3], 2, 1) eq 2*Tensor(F[2], 2, 1) - Tensor(F[1], 2, 1);
true
> Tensor(F[4], 2, 1) eq 3*Tensor(F[2], 2, 1) - 2*Tensor(F[1], 2, 1);
true
> Tensor(F[5], 2, 1) eq 4*Tensor(F[2], 2, 1) - 3*Tensor(F[1], 2, 1);
true

Run in calculator

So, indeed, \(T\) is the tensor space generated by the tensors in F. Note that the dimension of the 3-radical of \(t\) is 3.

> SystemOfForms(T.1) eq F[1];
true
> SystemOfForms(T.2) eq F[2];
true
> Radical(t, 3);
Vector space of degree 5, dimension 3 over Rational Field
Echelonized basis:
( 1  0  0 -4  3)
( 0  1  0 -3  2)
( 0  0  1 -2  1)

[ 0  0  0  0  1]
[ 0  0  0  1  0]
[ 0  0  1 -2  1]
[ 0  1  0 -3  2]
[ 1  0  0 -4  3]

Run in calculator

AsTensor(S): TenSpc -> TenSpcElt#

Given a tensor space \(S\), this intrinsic returns a tensor belonging to \(S\). If \(S\) is contravariant, then the returned tensor has the frame \(U_{\nu}\times \cdots \times U_1\rightarrowtail S\), where \(S\) is thought of as a free \(K\)-module.. If \(S\) is covariant, then the returned tensor has the frame \(S\times U_{\nu}\times \cdots \times U_1\rightarrowtail U_0\). Note that AsTensor is “inverse” to AsCotensorSpace and AsTensorSpace when \(i={\nu}\).

Example: Spaces To Tensors (ex-a38c03)#

We will construct the same tensor as the previous example and turn it into a tensor space at the third coordinate.

> t := Tensor(Rationals(), [5,4,3,2], [1..120]);
> t;
Tensor of valence 4, U3 x U2 x U1 >-> U0
U3 : Full Vector space of degree 5 over Rational Field
U2 : Full Vector space of degree 4 over Rational Field
U1 : Full Vector space of degree 3 over Rational Field
U0 : Full Vector space of degree 2 over Rational Field
> T := AsTensorSpace(t, 3);
> T;
Tensor space of dimension 2 over Rational Field with valence 3
U2 : Full Vector space of degree 4 over Rational Field
U1 : Full Vector space of degree 3 over Rational Field
U0 : Full Vector space of degree 2 over Rational Field

Run in calculator

Now we are going to “recover” \(t\) by creating a tensor from \(T\). However, it is not equal to \(t\) because the 3-radical of the new tensor is trivial.

> s := AsTensor(T);
> s;
Tensor of valence 4, U3 x U2 x U1 >-> U0
U3 : Full Vector space of degree 2 over Rational Field
U2 : Full Vector space of degree 4 over Rational Field
U1 : Full Vector space of degree 3 over Rational Field
U0 : Full Vector space of degree 2 over Rational Field
> Radical(s, 3);
Vector space of degree 2, dimension 0 over Rational Field

[0 1]
[1 0]

Run in calculator

We can even see the same sequences of matrices in \(s\).

> AsMatrices(s, 2, 1);
[
    [ 1  3  5]
    [ 7  9 11]
    [13 15 17]
    [19 21 23],

    [ 2  4  6]
    [ 8 10 12]
    [14 16 18]
    [20 22 24],

    [25 27 29]
    [31 33 35]
    [37 39 41]
    [43 45 47],

    [26 28 30]
    [32 34 36]
    [38 40 42]
    [44 46 48]
]

Run in calculator

Invariants of Tensors#

In this subsection, we detail functions to construct invariants of tensors. To access the projections or the objects acting on a specific factor \(U_i\), the following function(s) should be used.

Induce(X, i): AlgMat, RngIntElt -> Map, AlgMat#
Induce(X, i): AlgMatLie, RngIntElt -> Map, AlgMatLie#
Induce(X, i): GrpMat, RngIntElt -> Map, GrpMat#

Returns the projection from the given object to the induced sub-object on the \(i\)th coordinate and the induced sub-object of the associated tensor.

Example: Inducing (ex-4be7ac)#

To demonstrate how to Induce, we construct the 2-dimensional symplectic form on \(K =\) GF\((3)\).

> t := Tensor(GF(3), [2, 2, 1], [0, 1, 2, 0]);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 2 over GF(3)
U1 : Full Vector space of degree 2 over GF(3)
U0 : Full Vector space of degree 1 over GF(3)
> IsAlternating(t);
true

Run in calculator

This tensor has a nontrivial derivation algebra, isomorphic to \(K^2\oplus \rm{SL}_2(3)\). However, \(\rm{Der}(t)\) is represented in \(\rm{End}(U_2)\times\rm{End}(U_1)\times \rm{End}(U_0)\). We will induce the action on the \(1\)st coordinate.

> D := DerivationAlgebra(t);
> D.1;
[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 2]
> D.2;
[1 0 0 0 0]
[2 0 0 0 0]
[0 0 2 0 0]
[0 0 2 1 0]
[0 0 0 0 2]
> pi, D1 := Induce(D, 1);
> D1;
Matrix Lie Algebra of degree 2 over Finite field of size 3
> pi;
Mapping from: AlgMatLie: D to AlgMatLie: D1 given by a rule [no inverse]

Run in calculator

Now we can see that have the action of \(D\) on \(U_1\).

> D1.1;
[1 0]
[0 1]
> D1.2;
[2 0]
[2 1]

Run in calculator

We include a partner intrinsic to Include and that is the following procedure.

DerivedFrom(~X, t, C, RC : parameters): Any, TenSpcElt, {RngIntElt}, {RngIntElt}#
Fused: BoolElt                    Default: true

Includes the following tensor data in the matrix object \(X\): the tensor \(t\), the relevant coordinates which are in the set \(C\subseteq \{0,\dots,\nu\}\), and the coordinates \(RC\subseteq C\) for which the object is represented on. The reason for the subset \(C\) is so that we know the coordinates which can be induced on, see Induce. Currently, this only works for objects of type AlgMat, AlgMatLie, GrpMat, and ModMatFld. It is assumed that \(X\) is block diagonal, whose blocks starting from the top left go in decreasing order in the coordinates—in the same way the coordinates of the frame decrease from left to right for a tensor.

Standard Invariants#

We integrate the invariant theory associated to bilinear and multilinear maps into the realm of tensors.

Radical(T, s): TenSpcElt, RngIntElt -> ModTupRng#

Returns the \(s\)th-radical of \(T\) as a subspace of \(U_s\) and a matrix that splits the radical in \(V_s\). This is the subspace

\[U_{\bar{s}}^\perp = \left\{ u_s \in U_s : \forall \left| u_{\bar{s}}\right\rangle,\; \left\langle T | u\right\rangle =0\right\}.\]
Radical(T): TenSpcElt -> Tup#

Returns the tuple of all the \(s\)-radicals for each \(s\in \{1,\dots,\nu\}\).

Coradical(T): TenSpcElt -> ModTupRng, Map#

Returns the coradical of \(T\) and a surjection from the codomain to the coradical. This is the quotient \(U_0 / \langle T | U_{\nu}, \dots, U_1\rangle\).

Example: Radicals (ex-fef917)#

We will construct the tensor for multiplication in \(\rm{GL}_3({\mathbb{Q}})\), or equivalently, the commutator tensor of \(\rm{Mat}_3({\mathbb{Q}})\). Because \(\rm{GL}_3({\mathbb{Q}})\) contains the center of \(\rm{Mat}_3({\mathbb{Q}})\), there will be a 2- and 1-radical.

> K := Rationals();
> A := MatrixAlgebra(K, 3);
> t, phi := CommutatorTensor(A);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 9 over Rational Field
U1 : Full Vector space of degree 9 over Rational Field
U0 : Full Vector space of degree 9 over Rational Field
>
> R2 := Radical(t, 2);
> R2.1 @@ phi;
[1 0 0]
[0 1 0]
[0 0 1]
> Radical(t);
<
    Vector space of degree 9, dimension 1 over Rational Field
    Echelonized basis:
    (1 0 0 0 1 0 0 0 1),

    Vector space of degree 9, dimension 1 over Rational Field
    Echelonized basis:
    (1 0 0 0 1 0 0 0 1)
>

Run in calculator

Similarly, the image of \(t\) will be 8-dimensional in \({\mathbb{Q}}^9\), so the coradical is \({\mathbb{Q}}\).

> Image(t);
Vector space of degree 9, dimension 8 over Rational Field
Generators:
( 1  0  0  0  0  0  0  0 -1)
( 0  1  0  0  0  0  0  0  0)
( 0  0  1  0  0  0  0  0  0)
( 0  0  0  1  0  0  0  0  0)
( 0  0  0  0  1  0  0  0 -1)
( 0  0  0  0  0  1  0  0  0)
( 0  0  0  0  0  0  1  0  0)
( 0  0  0  0  0  0  0  1  0)
Echelonized basis:
( 1  0  0  0  0  0  0  0 -1)
( 0  1  0  0  0  0  0  0  0)
( 0  0  1  0  0  0  0  0  0)
( 0  0  0  1  0  0  0  0  0)
( 0  0  0  0  1  0  0  0 -1)
( 0  0  0  0  0  1  0  0  0)
( 0  0  0  0  0  0  1  0  0)
( 0  0  0  0  0  0  0  1  0)
> Coradical(t);
Full Vector space of degree 1 over Rational Field
Mapping from: Full Vector space of degree 9 over Rational Field to Full
Vector space of degree 1 over Rational Field

Run in calculator

We include some well-known polynomial invariants for bilinear maps.

Discriminant(B): TenSpcElt -> RngMPolElt#

Returns the discriminant of the bilinear map.

Example: Discriminating Octonions (ex-8de961)#

We will compute the discriminant of the tensor \(\cdot : O \times O \rightarrowtail O\). The discriminant of this tensor is homogeneous of degree 8 with 330 terms.

> A := OctonionAlgebra(GF(7), -1, -1, -1);
> t := Tensor(A);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 8 over GF(7)
U1 : Full Vector space of degree 8 over GF(7)
U0 : Full Vector space of degree 8 over GF(7)
> R<a,b,c,d,e,f,g,h> := PolynomialRing(GF(7), 8);
> disc := R!Discriminant(t);
> Degree(disc);
8
> IsHomogeneous(disc);
true
> #Terms(disc);
330

Run in calculator

However, if we factor the discriminant, then we can see that \({\tt disc} = \left(x_1^2 + \cdots x_8^2\right)^4\).

> Factorization(disc);
[
    <a^2 + b^2 + c^2 + d^2 + e^2 + f^2 + g^2 + h^2, 4>
]

Run in calculator

Pfaffian(B): TenSpcElt -> RngMPolElt#

Returns the Pfaffian of the antisymmetric bilinear map.

Example: Genus2Pfaff (ex-4cc2d2)#

In this demonstration, we pull from [Brooksbank et al., 2017]. A \(p\)-group \(G\) has genus 2, if the image of the exponent-\(p\) central tensor of \(G\) is 2-dimensional over the centroid. One of the algorithms in [Brooksbank et al., 2017] to decide isomorphism of such groups depends on the Pfaffian of the tensor.

First, we create two \(3\)-groups with genus 2. The first group we create as a quotient of the Sylow 3-subgroup of \(\rm{GL}(3,\rm{GF}(3^5))\).

> P := ClassicalSylow(GL(3, 3^5), 3);
> P := PCPresentation(UnipotentMatrixGroup(P));
> Z := Center(P);
> N := sub< Z | [Random(Z) : i in [1..3]] >;
> G := P/N;

Run in calculator

The second group we create will be a quotient of the Sylow 3-subgroup of the of \(\rm{GL}(3, \rm{GF}(9))\times\rm{GL}(3, \rm{GF}(27))\).

> A := ClassicalSylow(GL(3, 9), 3);
> B := ClassicalSylow(GL(3, 27), 3);
> A := PCPresentation(UnipotentMatrixGroup(A));
> B := PCPresentation(UnipotentMatrixGroup(B));
> Q, inc := DirectProduct(A, B);
> ZA := Center(A);
> ZB := Center(B);
> gens := [(ZA.i@inc[1])*(ZB.i@inc[2])^-1 : i in [1..2]]
>     cat [ZB.3@inc[2]];
> M := sub< Q | gens >;
> H := Q/M;

Run in calculator

Now we will construct the exponent-\(p\) central tensors of \(G\) and \(H\). From the way we have created the groups, \(G\cong H\) if, and only if, their tensors are pseudo-isometric.

> t := pCentralTensor(G);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 10 over GF(3)
U1 : Full Vector space of degree 10 over GF(3)
U0 : Full Vector space of degree 2 over GF(3)
>
> s := pCentralTensor(H);
> s;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 10 over GF(3)
U1 : Full Vector space of degree 10 over GF(3)
U0 : Full Vector space of degree 2 over GF(3)

Run in calculator

An implication of the main algorithm in [Brooksbank et al., 2017] is that if the splitting behavior of the Pfaffians are different, then the groups are not isomorphic. Therefore, because the Pfaffian of \(G\) has a different splitting behavior from the Pfaffian of \(H\), we conclude that \(G\not\cong H\).

> R<x,y> := PolynomialRing(GF(3), 2);
> f := R!Pfaffian(t);
> g := R!Pfaffian(s);
> f;
x^5 + x^3*y^2 + 2*x^2*y^3 + 2*x*y^4 + y^5
> g;
x^5 + 2*x^4*y + x^3*y^2 + 2*x^2*y^3 + x*y^4 + y^5
> Factorization(f), Factorization(g);
[
    <x^5 + x^3*y^2 + 2*x^2*y^3 + 2*x*y^4 + y^5, 1>
]
[
    <x^2 + x*y + 2*y^2, 1>,
    <x^3 + x^2*y + x*y^2 + 2*y^3, 1>
]

Run in calculator

Exporting Tensors#

In the previous sections, we used groups, rings, and algebras to define tensors, but tensors can be used to define algebraic structures as well. In this section, we describe ways to build groups and algebras from tensors. Currently, all intrinsics in this section only support 3-tensors.

HeisenbergAlgebra(T): TenSpcElt -> AlgGen#

Returns the Heisenberg algebra \(A\) induced by the bilinear tensor \(T: U\times V\rightarrowtail W\). The algebra \(A\) depends on the tensor category of \(T\). If the tensor category forces equality between \(U\), \(V\), and \(W\), then \(A\cong U\) as vector spaces and is a nonassociative algebra (i.e. not necessarily associative). If the tensor category forces equality between \(U\) and \(V\), then \(A\cong U\oplus W\) as vector spaces and is a nilpotent algebra where \(C(A)\geq W\) and \(A^2\leq W\). Otherwise, \(A\cong U\oplus V\oplus W\) as vector spaces, and using \(*\) for \(T\),

\[(u,v,w)\cdot (u',v',w') = (0,0,u*v').\]
Example: Crafting Algebras (ex-182a22)#

We will demonstrate some of the nuances of HeisenbergAlgebra and how it interacts with the tensor category of the given tensor. We will use the same tensor throughout but changing the categories. The frame of the tensor is \({\mathbb{Q}}^3\times{\mathbb{Q}}^3\rightarrowtail{\mathbb{Q}}^3\).

> t := Tensor(Rationals(), [3, 3, 3], [i : i in [1..27]]);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 3 over Rational Field
U1 : Full Vector space of degree 3 over Rational Field
U0 : Full Vector space of degree 3 over Rational Field
> SystemOfForms(t);
[
    [ 1  4  7]
    [10 13 16]
    [19 22 25],

    [ 2  5  8]
    [11 14 17]
    [20 23 26],

    [ 3  6  9]
    [12 15 18]
    [21 24 27]
]
> Radical(t);
<
    Vector space of degree 3, dimension 1 over Rational Field
    Echelonized basis:
    ( 1 -2  1),

    Vector space of degree 3, dimension 1 over Rational Field
    Echelonized basis:
    ( 1 -2  1)
>
> Image(t);
Vector space of degree 3, dimension 2 over Rational Field
Generators:
( 1  0 -1)
( 0  1  2)
Echelonized basis:
( 1  0 -1)
( 0  1  2)

Run in calculator

The default tensor category of \(t\) above is the homotopism category where none of the modules are fused together. Therefore, if we construct the Heisenberg algebra of \(t\), the resulting algebra will be 9-dimensional. Looking at the system of forms, the first 6 matrices will be zero, and the last 3 matrices will contain the above system of forms as a \(3\times 3\) block, starting at the \((1,4)\) entry.

> A := HeisenbergAlgebra(t);
> A;
Algebra of dimension 9 with base ring Rational Field
> Center(A);
Algebra of dimension 5 with base ring Rational Field
> SystemOfForms(Tensor(A))[7..9];
[
    [ 0  0  0  1  4  7  0  0  0]
    [ 0  0  0 10 13 16  0  0  0]
    [ 0  0  0 19 22 25  0  0  0]
    [ 0  0  0  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0  0],

    [ 0  0  0  2  5  8  0  0  0]
    [ 0  0  0 11 14 17  0  0  0]
    [ 0  0  0 20 23 26  0  0  0]
    [ 0  0  0  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0  0],

    [ 0  0  0  3  6  9  0  0  0]
    [ 0  0  0 12 15 18  0  0  0]
    [ 0  0  0 21 24 27  0  0  0]
    [ 0  0  0  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0  0]
]

Run in calculator

Now we will fuse \(U\) and \(V\) together with a new category. The resulting algebra will then be 6-dimensional. We will also look at the system of forms of \(A\) to see the structure constants of \(A\).

> NilCat := TensorCategory([1, 1, 1], {{2,1},{0}});
> NilCat;
Tensor category of valence 3 (->,->,->) ({ 0 },{ 1, 2 })
> ChangeTensorCategory(~t, NilCat);
> A := HeisenbergAlgebra(t);
> A;
Algebra of dimension 6 with base ring Rational Field
> Center(A);
Algebra of dimension 4 with base ring Rational Field
> A^2;
Algebra of dimension 2 with base ring Rational Field
> SystemOfForms(Tensor(A))[4..6];
[
    [ 1  4  7  0  0  0]
    [10 13 16  0  0  0]
    [19 22 25  0  0  0]
    [ 0  0  0  0  0  0]
    [ 0  0  0  0  0  0]
    [ 0  0  0  0  0  0],

    [ 2  5  8  0  0  0]
    [11 14 17  0  0  0]
    [20 23 26  0  0  0]
    [ 0  0  0  0  0  0]
    [ 0  0  0  0  0  0]
    [ 0  0  0  0  0  0],

    [ 3  6  9  0  0  0]
    [12 15 18  0  0  0]
    [21 24 27  0  0  0]
    [ 0  0  0  0  0  0]
    [ 0  0  0  0  0  0]
    [ 0  0  0  0  0  0]
]

Run in calculator

Finally, we will put a tensor category on \(t\) where \(U\), \(V\) and \(W\) are all fused together. The Heisenberg algebra from this tensor is 3-dimensional, and the product is exactly the tensor \(t\).

> AlgCat := TensorCategory([1, 1, 1], {{2,1,0}});
> AlgCat;
Tensor category of valence 3 (->,->,->) ({ 0, 1, 2 })
> ChangeTensorCategory(~t, AlgCat);
> A := HeisenbergAlgebra(t);
> A;
Algebra of dimension 3 with base ring Rational Field
> SystemOfForms(Tensor(A));
[
    [ 1  4  7]
    [10 13 16]
    [19 22 25],

    [ 2  5  8]
    [11 14 17]
    [20 23 26],

    [ 3  6  9]
    [12 15 18]
    [21 24 27]
]

Run in calculator

HeisenbergLieAlgebra(T): TenSpcElt -> AlgLie#

Returns the Heisenberg Lie algebra \(L\) with Lie bracket given by the 3-tensor \(T:U\times V\rightarrowtail W\). If the tensor category of \(T\) forces equality only between \(U\) and \(V\) and \(T\) is alternating, then the Heisenberg Lie algebra will have structure constants equal to \(T\). In this case, \(L\cong U\oplus W\) as vector spaces. Otherwise, \(L\cong U\oplus V\oplus W\) as vector spaces, and, using \(*\) in place for \(T\), the product in \(L\) is given by

\[(u,v,w) * (u',v',w') = (0,0,uv'-u'v).\]
Example: Crafting Lie Algberas (ex-19a3f6)#

We will construct an alternating tensor with frame \({\mathbb{Q}}^3\times{\mathbb{Q}}^3\rightarrowtail {\mathbb{Q}}^2\).

> t := Tensor(Rationals(), [3, 3, 2], &cat[[1,-1,0] : i in [1..6]]);
> t := AlternatingTensor(t);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 3 over Rational Field
U1 : Full Vector space of degree 3 over Rational Field
U0 : Full Vector space of degree 2 over Rational Field
> SystemOfForms(t);
[
    [ 0 -1 -2]
    [ 1  0 -1]
    [ 2  1  0],

    [ 0  2  1]
    [-2  0 -1]
    [-1  1  0]
]

Run in calculator

First, we will just construct the Heisenberg Lie algebra from \(t\) as is. Because the tensor category of \(t\) does not fuse together \(U\), \(V\), and \(W\), the Lie algebra will be 8-dimensional.

> L := HeisenbergLieAlgebra(t);
> L;
Lie Algebra of dimension 8 with base ring Rational Field
> SystemOfForms(Tensor(L))[7..8];
[
    [ 0  0  0  0 -1 -2  0  0]
    [ 0  0  0  1  0 -1  0  0]
    [ 0  0  0  2  1  0  0  0]
    [ 0 -1 -2  0  0  0  0  0]
    [ 1  0 -1  0  0  0  0  0]
    [ 2  1  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0],

    [ 0  0  0  0  2  1  0  0]
    [ 0  0  0 -2  0 -1  0  0]
    [ 0  0  0 -1  1  0  0  0]
    [ 0  2  1  0  0  0  0  0]
    [-2  0 -1  0  0  0  0  0]
    [-1  1  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0]
    [ 0  0  0  0  0  0  0  0]
]

Run in calculator

Now if we fuse \(U\) and \(V\) together, the resulting Lie algebra will be 5-dimensional, and the Lie bracket will essentially be equal to \(t\).

> NilCat := TensorCategory([1, 1, 1], {{2,1},{0}});
> NilCat;
Tensor category of valence 3 (->,->,->) ({ 0 },{ 1, 2 })
> ChangeTensorCategory(~t, NilCat);
> L := HeisenbergLieAlgebra(t);
> L;
Lie Algebra of dimension 5 with base ring Rational Field
> SystemOfForms(Tensor(L))[4..5];
[
    [ 0 -1 -2  0  0]
    [ 1  0 -1  0  0]
    [ 2  1  0  0  0]
    [ 0  0  0  0  0]
    [ 0  0  0  0  0],

    [ 0  2  1  0  0]
    [-2  0 -1  0  0]
    [-1  1  0  0  0]
    [ 0  0  0  0  0]
    [ 0  0  0  0  0]
]

Run in calculator

HeisenbergGroup(T): TenSpcElt -> GrpMat#
HeisenbergGroupPC(T): TenSpcElt -> GrpPC#

Returns the class 2, exponent \(p\), Heisenberg \(p\)-group with commutator given by the bilinear tensor \(T: U \times V \rightarrowtail W\) over a finite field. If \(T\) is alternating and the tensor category of \(T\) forces equality between \(U\) and \(V\), then the group returned is an extension of \(V\) by \(W\), so \(|G| = |V|\cdot |W|\). Otherwise, the group returned is an extension of \(U\oplus V\) by \(W\), so \(|G| = |U|\cdot |V| \cdot |W|\). If \(T\) is not full, then \(G\) is an extension of \(U\oplus V\oplus W/\rm{im}(T)\) (or \(V\oplus W/\rm{im}(T)\)) by \(\rm{im}(T)\).

Example: Crafting P Groups (ex-3bc793)#

Here we demonstrate how to export a group from a tensor. We will start with a tensor that is alternating and compare the different outputs based on the category of the tensor.

> t := KTensorSpace(GF(5), [5, 5, 4])!0;
> for i in [1..4] do
>   Assign(~t, [i, i+1, i], 1);   // 1s above diag
>   Assign(~t, [i+1, i, i], -1);  // 4s below diag
> end for;
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 5 over GF(5)
U1 : Full Vector space of degree 5 over GF(5)
U0 : Full Vector space of degree 4 over GF(5)
> IsAlternating(t);
true

Run in calculator

In this example, we will focus on the more straight-forward case, when \(t\) is full. The next example demonstrates a tensor that is not full.

> SystemOfForms(t);
[
    [0 1 0 0 0]
    [4 0 0 0 0]
    [0 0 0 0 0]
    [0 0 0 0 0]
    [0 0 0 0 0],

    [0 0 0 0 0]
    [0 0 1 0 0]
    [0 4 0 0 0]
    [0 0 0 0 0]
    [0 0 0 0 0],

    [0 0 0 0 0]
    [0 0 0 0 0]
    [0 0 0 1 0]
    [0 0 4 0 0]
    [0 0 0 0 0],

    [0 0 0 0 0]
    [0 0 0 0 0]
    [0 0 0 0 0]
    [0 0 0 0 1]
    [0 0 0 4 0]
]
> IsFullyNondegenerate(t);
true

Run in calculator

Even though \(t\) is alternating, the category does not fuse together \(U\) and \(V\). Therefore, the Heisenberg group \(H\) is an extension of \(U\oplus V\) by \(W\), and hence, \(|H|=5^{5+5+4}\).

> H := HeisenbergGroup(t);
> LMGOrder(LMGCenter(H)) eq 5^4;
true
> s := pCentralTensor(H, 5, 1, 1);
> s;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 10 over GF(5)
U1 : Full Vector space of degree 10 over GF(5)
U0 : Full Vector space of degree 4 over GF(5)

Run in calculator

Now we will fuse the 2 and 1 coordinate, so that \(|H|=5^{5+4}\).

> PgrpCat := TensorCategory([1, 1, 1], {{2,1},{0}});
> PgrpCat;
Tensor category of valence 3 (->,->,->) ({ 0 },{ 1, 2 })
> ChangeTensorCategory(~t, PgrpCat);
> H := HeisenbergGroup(t);
> LMGOrder(LMGCenter(H)) eq 5^4;
true
> s := pCentralTensor(H, 5, 1, 1);
> s;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 5 over GF(5)
U1 : Full Vector space of degree 5 over GF(5)
U0 : Full Vector space of degree 4 over GF(5)

Run in calculator

Note that \(t\) and \(s\) are not the same tensor. However, they are pseudo-isometric (isotopic in the category with \(U_2=U_1\)). This effect is exaggerated with HeisenbergGroupPC because of how PC-generators are organized.

> SystemOfForms(s);
[
    [0 0 0 0 0]
    [0 0 0 0 1]
    [0 0 0 0 0]
    [0 0 0 0 0]
    [0 4 0 0 0],

    [0 0 0 0 0]
    [0 0 0 0 0]
    [0 0 0 0 4]
    [0 0 0 0 0]
    [0 0 1 0 0],

    [0 0 0 0 0]
    [0 0 0 0 0]
    [0 0 0 1 0]
    [0 0 4 0 0]
    [0 0 0 0 0],

    [0 0 0 4 0]
    [0 0 0 0 0]
    [0 0 0 0 0]
    [1 0 0 0 0]
    [0 0 0 0 0]
]

Run in calculator

Example: P Groups Half Full (ex-ce8a17)#

We will start with an alternating tensor that is not full with the frame \({\bf F}_{3}^4\times{\bf F}_{3}^4\rightarrowtail {\bf F}_{3}^3\).

> t := Tensor(GF(3), [4, 4, 3], &cat[[1,0,0,1] : i in [1..12]]);
> t := AlternatingTensor(t);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 4 over GF(3)
U1 : Full Vector space of degree 4 over GF(3)
U0 : Full Vector space of degree 3 over GF(3)
> Radical(t);
<
    Vector space of degree 4, dimension 1 over GF(3)
    Echelonized basis:
    (1 2 1 2),

    Vector space of degree 4, dimension 1 over GF(3)
    Echelonized basis:
    (1 2 1 2)
>
> Image(t);
Vector space of degree 3, dimension 2 over GF(3)
Generators:
(1 0 2)
(0 1 0)
Echelonized basis:
(1 0 2)
(0 1 0)
> SystemOfForms(t);
[
    [0 0 2 2]
    [0 0 2 2]
    [1 1 0 0]
    [1 1 0 0],

    [0 1 1 0]
    [2 0 0 2]
    [2 0 0 2]
    [0 1 1 0],

    [0 0 1 1]
    [0 0 1 1]
    [2 2 0 0]
    [2 2 0 0]
]

Run in calculator

Because the tensor category of \(t\) does not force equality between \(U\) and \(V\), the group \(H\) created from \(t\) will have order \(3^{11}\) and be 8-generated. Furthermore, the tensor has a 2-dimensional image, so the tensor from the exponent-\(p\) central series of \(H\) will have frame \({\bf F}_{3}^{4+4+1}\times {\bf F}_{3}^{4+4+1}\rightarrowtail{\bf F}_{3}^2\). We display the system of forms of the exponent-\(p\) central tensor of \(H\) to show how different it looks compared to the original.

> G := HeisenbergGroup(t);
> LMGOrder(G) eq 3^11;
true
> s := pCentralTensor(G);
> s;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 9 over GF(3)
U1 : Full Vector space of degree 9 over GF(3)
U0 : Full Vector space of degree 2 over GF(3)
> SystemOfForms(s);
[
    [0 0 0 0 0 0 0 0 1]
    [0 0 0 0 0 0 2 2 0]
    [0 0 0 0 0 0 0 0 1]
    [0 0 0 0 0 0 1 1 2]
    [0 0 0 0 0 0 0 0 0]
    [0 0 0 0 0 0 0 0 0]
    [0 1 0 2 0 0 0 0 0]
    [0 1 0 2 0 0 0 0 0]
    [2 0 2 1 0 0 0 0 0],

    [0 0 0 0 0 0 1 0 0]
    [0 0 0 0 0 0 1 0 0]
    [0 0 0 0 0 0 0 2 2]
    [0 0 0 0 0 0 0 2 2]
    [0 0 0 0 0 0 0 0 0]
    [0 0 0 0 0 0 0 0 0]
    [2 2 0 0 0 0 0 0 0]
    [0 0 1 1 0 0 0 0 0]
    [0 0 1 1 0 0 0 0 0]
]

Run in calculator