Tensors

A tensor has the following information associated with it:-

*
A commutative ring K of coefficients.
*
A valence (ν) indicating the number of variables to include in its associated multilinear map.
*
A list [Uν, ..., U0] of K-modules called the frame.
*
A function Uν x ... x U1to U0 that is K-linear in each Ui.

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: homK(Uv, ..., homK(U1, U0) ... ) isomorphic to homK(Uv tensor K ... tensor K U1, U0). 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.

Contents

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 Multilinear_BBTensorsFrame (H62E3)

We demonstrate the black-box constructions by first constructing the dot product .: Q4 x Q4 ↣ 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ν x ... x U1. Note that x[i] is the ith entry in the tuple and not the ith 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])) >;

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
*]

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 })

Example Multilinear_BBCrossProduct (H62E4)

We will construct the cross product x : R3 x R3 ↣ R3 and verify that (i) x (j) = (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
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 Multilinear_BBTripleProduct (H62E5)

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 < > : (Mat)2 x 3(K) x (Mat)2 x 3(K) x (Mat)2 x 3(K) ↣ (Mat)2 x 3(K), given by < A, B, C > = ABtC.
> 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)

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, K6.

> 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)
We can experiment to see if this triple product is left associative. To do this, we will construct five random matrices { X1, ..., X5}⊂(Mat)2 x 3(K), and then we test if

< < X1, X2, X3 >, X4, X5 > = < X1, < X4, X3, X2 >, X5 >.

Observe that the tuples have mixed entries, one from K6 and two others from (Mat)2 x 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
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

{ } : ∏k=15 (Mat)2 x 3(K) ↣ (Mat)2 x 3(K)

where

< X1, ..., X5 > = < < X1, X2, X3 >, X4, X5 > - < X1, < X4, X3, X2 >, X5 >.

Therefore, if im(< >)=0, then < > 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

Observe that in lasct the function Eltseq is called. This is because t returns vectors in K6 which is not naturally coercible into (Mat)2 x 3(K). On the other hand, sequences can be coerced into (Mat)2 x 3(K).

Tensors with Structure Constant Sequences

Most computations with tensors T will be carried out using structure constants T_(jν ... j0)∈K. Here T is framed by free K-modules [Uν, ..., U0] with each Ui having an ordered basis (B)i=[ei1, ..., eidi]. The interpretation of structure constants is that the associated multilinear function [xν, ..., x1] from Uν x ... x U1 into U0 is determined on bases (B)i as follows: [e_((ν)jν), ..., e1j1 ] = ∑k=1d0 T_(jν ... j0) e0k. Structure constants are input and stored as sequences S in K according to the following assignment. Set f:Zν + 1to Z to be: f(jν, ..., j0) = 1 + ∑s=0ν (js - 1)∏t=0s - 1 dt. So S[f(jν, ..., j0)]=T_(jν ... j0) 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 Tap ... a1bq ... b1 should be input as T_(ap + q ... a1 + q bq ... b1) and the tensor category changed to mark {q, ..., 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 [dv, ..., d0] giving the dimensions of the R-modules Uv, ..., U0. The intrinsic returns the tensor with frame { Uv, ..., U1 }, codomain U0 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 Multilinear_SCTensors (H62E6)

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 x 2 x 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 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

We do not want the underlying ring to be 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)

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)
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 Multilinear_SCFromBBTensors (H62E7)

We will construct the natural Lie module action for (SL)2, but we will construct it as a left module. To do this, we construct a function that takes elements from (SL)2 x 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 (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)

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

Example Multilinear_SCStored (H62E8)

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 (Mat)20(GF(3)), namely * : (SL)20(GF(3)) x (Mat)4(GF(3)) ↣ (Mat)20(GF(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)

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
Bilinear Tensors

In the special case of bilinear maps U2 x U1 ↣ U0, the structure constant sequences may be presented as lists [M1, ..., Ma] of matrices. This can be considered as a left (resp. right) representation U2to homK(U1, U0), (resp.U1to homK(U2, U0)). Alternatively, bilinear maps can be treated as systems of bilinear forms [M1, ..., Ma] where the matrices are the Gram matrices of bilinear forms φi:U2 x U1 ↣ K. Here the associated bilinear map U2 x U1 ↣ U0 is specified by (u2, u1) |-> ( φ1(u2, u1), ..., φa(u2, u1)).

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 Multilinear_SymplecticForm (H62E9)

We will construct a symplectic bilinear form on V=K8. 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

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]
]
AsMatrices(T, s, t) : TenSpcElt, RngIntElt, RngIntElt -> SeqEnum
SystemOfForms(T) : TenSpcElt -> SeqEnum
For a tensor T with frame [Kdv, ..., Kd0], a list [M1, ..., Md], d=(dv ... d0)/ds dt, of (ds x dt)-matrices in K representing the tensor as an element of homK(Kds tensor K Kdt, Kd) is returned. For the intrinsic SystemOfForms, T must have valence 2 and the implied values are s=2 and t=1.

Example Multilinear_TrilinearAsMats (H62E10)

We construct the associator of (SL)2(Q) where < > : ∏k=13(SL)2 ↣ (SL)2 given by < x, y, z > = [[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 ]

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 31 : V3 x V1 ↣ homK(V2, V0) given by x31 z = < x, - , z > = [[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]
]
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 x A ↣ 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 Multilinear_D4LieAlgebra (H62E11)

We want to get the Lie bracket from D4(11). Tensors created from algebras will have a homotopism category, but with U2=U1=U0. This forces the operators acting to be the same on all the coordinates; in other words, Ω=(End)(U2) instead of Ω=(End)(U2) x (End)(U1) x (End)(U0).

> 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 })

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

Now we will change the category to the standard homotopism category, where we do not fuse U2, U1, and U0.

> 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 })

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)=K2.

> D := DerivationAlgebra(t);
> Dimension(D);
30
> R := SolvableRadical(D);
> SemisimpleType(D/R);
D4
Tensor(Q) : RngUPolRes -> TenSpcElt, Map
Returns the bilinear tensor given by the product in quotient polynomial ring Q.

Example Multilinear_WittAlgebra (H62E12)

The Witt algebra, over a finite field of characteristic p, is isomorphic to the derivation algebra of K[x]/(xp). 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 GF(5)[x]/(x5). Note that, like with algebras, the tensor category will fuse U2, U1, and U0, 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 })

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]
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 < a, b > = 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 Multilinear_CommutatorFromAlgebra (H62E13)

We will construct the commutator tensor from (Mat)4(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

With this tensor, we will compute the dimension of the centralizer of the diagonal matrix M with diagonal entries (1, 1, - 1, - 1) in (Mat)4(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

Example Multilinear_MatrixJordanAlgebra (H62E14)

This time, we will obtain a Jordan product from (Mat)4(Q). That is, we will construct the bilinear map * : (Mat)4(Q) x (Mat)4(Q) ↣ (Mat)4(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)

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)

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
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 Multilinear_AssociatorFromAlgebra (H62E15)

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

However, for all a, b∈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
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 η of G. The bilinear map pairs ηss + 1 with ηtt + 1 into ηs + ts + t + 1. If s=t the tensor category is set to force U2=U1; 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 Multilinear_TensorPGroup (H62E16)

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=(SL)(3, 125); however, we will lose the fact that there is a field GF(125). The tensor we will get back is [, ] : K6 x K6 ↣ K3, where K=GF(5).
> P := ClassicalSylow(SL(3,125), 5);
> Q := PCGroup(P);	// The group Q wont 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)

Knowing that G is defined over GF(125), we know that the commutator is really just the alternating form .: GF(125)2 x GF(125)2 ↣ GF(125). This information can be extracted from the centroid of t above, and we can rewrite t over the field GF(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)
MatrixTensor(K, S) : Fld, [RngIntElt] -> TenSpcElt, List
Given a field K and a sequence of positive integers S=[s1, ..., sν], return the tensor (Mat)s1 x s2(K) x ... x (Mat)_(sν - 1 x sν)(K) ↣ (Mat)_(s1 x sν)(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 Multilinear_TensorPolarization (H62E17)

The polarization intrinsic is applied to the polynomial f(x, y) = x2 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 K2 x K2 x K2 ↣ K. The polarization of f is given by P(x1, x2, y1, y2, z1, z2 ) = 2 (x1y1z2 + x1y2z1 + x2y1z1).
> 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)
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 Multilinear_AlternatingTensor (H62E18)

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

Example Multilinear_MakeSymmetric (H62E19)

We will make the tensor coming from the product in (Mat)3(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]

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]
Shuffle(T, g) : TenSpcElt, GrpPermElt -> TenSpcElt
Shuffle(T, g) : TenSpcElt, SeqEnum -> TenSpcElt
Given a tensor T in hom(Uν, ..., hom(U1, U0) ... ), this intrinsic generates the representation of T in hom(U_((ν)g), ..., hom(U1g, U0g) ... ), where g is a permutation of {0, ..., ν }. 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, ..., ν }. Sequences [a1, ..., aν + 1] will be interpreted as a permutation in one-line notation.

Example Multilinear_ShuffleToTranspose (H62E20)

We will shuffle the alternating form Q2 x Q2 ↣ 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]
]

Example Multilinear_Shuffling (H62E21)

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)
TensorProduct(t, s) : TenSpcElt, TenSpcElt -> TenSpcElt
Given K-tensors t:Uν x ... x U1 ↣ U0 and s:Vν x ... x V1 ↣ V0, returns the tensor t tensor s : Uν tensor Vν x ... x U1 tensor V1 ↣ U0 tensor V0. 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 Multilinear_ModuleOperations (H62E22)

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]
]

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]
]
AssociatedForm(T) : TenSpcElt -> TenSpcElt
For a tensor T with frame Uν x ... x U1 ↣ U0, this intrinsic creates the associated multilinear form Uν x ... x U1 x U0 * ↣ 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 Multilinear_CompressAssocForm (H62E23)

We will construct the associated form of the tensor from the Lie algebra B3(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)

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
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 Multilinear_BasicProps (H62E24)

We demonstrate how to get basic properties of a tensor and what to expect as an output. We will construct a tensor *:(Mat)2 x 3(Q) x Q3 ↣ Q2 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
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 Multilinear_TensorCatProps (H62E25)

We will construct a tensor from a right module, *:Q2 x (Mat)2 x 2(Q) ↣ Q2.

> 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

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
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 Multilinear_Nondegeneracy (H62E26)

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)

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 U2/U_(widehat(2))perp x U1/U_(widehat(1))perp ↣ U0.

> 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)
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 Multilinear_FullyNondegenerate (H62E27)

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)

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)

Now we will construct the associated fully nondegenerate tensor: U2/U_(widehat(2))perp x U1/U_(widehat(1))perp ↣ U2 * U1. 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)
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 Multilinear_SymmetricPolar (H62E28)

We will construct the multilinear form given by polarizing the homogeneous polynomial f(x, y, z)=x3 + y3 + z3 + 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

The resulting homogeneous polynomial from polarizing is p(x1, x2, x3, y1, y2, y3, z1, z2, z3) =∑σ∈S3 (x1σy2σz3σ + 3x1σy1σz1σ).

> 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]
]

Because the underlying field is Q and because t is symmetric, we know that t is not alternating nor antisymmetric.

> IsAlternating(t);
false
> IsAntisymmetric(t);
false
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∈Uν x ... x U1. The entries can be elements from the vector space Ui or sequences that Magma can naturally coerce into the vector space Ui. 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 Multilinear_MultiMapEval (H62E29)

Here we create the 4-tensor < > of an algebra A given by the Jacobi identity: (x, y, z) |-> (xy)z + (yz)x + (zx)y. Therefore, the algebra satisfies the Jacobi identity if < A, A, A > = 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 })

Even though our tensor originated over the algebra A=(Mat)3(GF(3)), the returned tensor is over vector spaces GF(3)9. However, the tensor t can still evaluate elements from (Mat)3(GF(3)) as well as GF(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 (Mat)3(GF(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)
Because @ takes Tup as input, t can evaluate mixed tuples as well: where some entries are contained in (Mat)3(GF(3)) and other entries are contained in GF(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)
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 ≤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 Multilinear_TensorComp (H62E30)

We start with the same tensor as the previous example: the tensor given by the Jacobi identity on the algebra A=(Mat)3(GF(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 })

The maps in Maps are vector space isomorphisms and map A to V. Suppose φ: A -> V is a vector space isomorphism. If we compose t with φ - 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

Let (E)⊂A be an orthogonal frame---a set of primitive, orthogonal, idempotents. We will compose t with the linear transformation a |-> ∑_(e∈(E)) eae. Because the codomain of t is a vector space, we will precompose this map by φ - 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
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
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 x V ↣ W.

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 * 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 -> 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 ↣ 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∈T. This is either a tensor space or a vector space.

Example Multilinear_BimapInfix (H62E31)

We demonstrate the infix notation by constructing the tensor in A=(Mat)2(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

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 ↣ A, where X |-> 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]
]

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)

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)
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 Multilinear_BimapProduct (H62E32)

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 x V ↣ W is the tensor given by commutation where U=V=G/η2 and W=η23, where ηi denotes the ith 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)

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)

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)
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 Multilinear_BimapProduct2 (H62E33)

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)

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
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ν, ..., U0] with di=dim Ui, a grid is a sequence [Gν, ..., G0] of subsets Gi⊆{1, ..., di}∪{-di, ..., - 1}. If an entry g∈Gi is negative, it will be taken to mean di + g + 1, so -1 would be equivalent to di. The slice is the list of entries in the structure constants of the tensor indexed by Gν x ... x G0. The intrinsic Slice returns the structure constants whereas InducedTensor produces a tensor with these structure constants.

Example Multilinear_TensorSlicing (H62E34)

We will construct a tensor *: Q4 x Q3 ↣ Q2 with a structure constants sequence equal to [1, ..., 24]. If every Gi={1, ..., di}, 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

Now we will slice with the following grid [{1, ..., 4}, {2}, {1}]. Compare this with the product U * v2.

> [ 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 ]

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

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

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 ]

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 ]
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 Multilinear_SliceAsMatrices (H62E35)

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]
]

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]
]
Foliation(T, i) : TenSpcElt, RngIntElt -> Mtrx
If T is a tensor with frame hom(Uν tensor ... tensor U1, U0), and i is the index of some term of the frame of T, this intrinsic returns the matrix representing the linear map Ui -> hom(bigotimesj≠iUi, U0) using the bases of each Uj. If i=0, then the returned matrix is given by the representation U0 * -> hom(bigotimes Ui, K).

Example Multilinear_ExfoliateFoliation (H62E36)

We will, again, construct the same tensor, *:Q4 x Q3 ↣ Q2, from the previous two examples whose structure constants sequence is [1, ..., 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

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≤Q4 such that U_(hat(2))perp * Q3=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)

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 Q3 ↣ Q2. 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
AsTensorSpace(T, i) : TenSpcElt, RngIntElt -> TenSpc, Mtrx
If T is a tensor contained in hom(Uv tensor ... tensor U1, U0), 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 Uv x ... x Ui + 1 x Ui - 1 x ... x U1 ↣ U0 and is generated by the tensors Tu for each u in the basis of Ui. 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ν x ... x U1 ↣ K and is generated by the tensors Tf for each f in the basis of U0 * . In the case that T is a bilinear map, this is equivalent to the cotensor space generated by the SystemOfForms.

Example Multilinear_TensorsToSpaces (H62E37)

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

The dimension of T cannot be larger than 5 because that is the dimension of U3. 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]];

Here, F is a sequence of a system of forms for t, one for each basis vector in U3. 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]
]
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

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]
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ν x ... x U1 ↣ S, where S is thought of as a free K-module.. If S is covariant, then the returned tensor has the frame S x Uν x ... x U1 ↣ U0. Note that AsTensor is "inverse" to AsCotensorSpace and AsTensorSpace when i=(ν).

Example Multilinear_SpacesToTensors (H62E38)

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

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]

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]
]

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 Ui, the following function(s) should be used.

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

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 ith coordinate and the induced sub-object of the associated tensor.

Example Multilinear_Inducing (H62E39)

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

This tensor has a nontrivial derivation algebra, isomorphic to K2 direct-sum (SL)2(3). However, (Der)(t) is represented in (End)(U2) x (End)(U1) x (End)(U0). We will induce the action on the 1st 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]

Now we can see that have the action of D on U1.

> D1.1;
[1 0]
[0 1]
> D1.2;
[2 0]
[2 1]
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⊆{0, ..., ν}, and the coordinates RC⊆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.

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

Radical(T, s) : TenSpcElt, RngIntElt -> ModTupRng
Returns the sth-radical of T as a subspace of Us and a matrix that splits the radical in Vs. This is the subspace U_(bar(s))perp = { us ∈Us : forall | u_(bar(s)) >, < T | u > =0}.
Radical(T) : TenSpcElt -> Tup
Returns the tuple of all the s-radicals for each s∈{1, ..., ν}.
Coradical(T) : TenSpcElt -> ModTupRng, Map
Returns the coradical of T and a surjection from the codomain to the coradical. This is the quotient U0 / < T | Uν, ..., U1 >.

Example Multilinear_Radicals (H62E40)

We will construct the tensor for multiplication in (GL)3(Q), or equivalently, the commutator tensor of (Mat)3(Q). Because (GL)3(Q) contains the center of (Mat)3(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)
>

Similarly, the image of t will be 8-dimensional in Q9, so the coradical is 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
Discriminant(B) : TenSpcElt -> RngMPolElt
Returns the discriminant of the bilinear map.

Example Multilinear_DiscriminatingOctonions (H62E41)

We will compute the discriminant of the tensor .: O x O ↣ 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

However, if we factor the discriminant, then we can see that (disc) = (x12 + ... x82)4.

> Factorization(disc);
[
    <a^2 + b^2 + c^2 + d^2 + e^2 + f^2 + g^2 + h^2, 4>
]
Pfaffian(B) : TenSpcElt -> RngMPolElt
Returns the Pfaffian of the antisymmetric bilinear map.

Example Multilinear_Genus2Pfaff (H62E42)

In this demonstration, we pull from [BMW17]. 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 [BMW17] 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 (GL)(3, (GF)(35)).

> 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;

The second group we create will be a quotient of the Sylow 3-subgroup of the of (GL)(3, (GF)(9)) x (GL)(3, (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;

Now we will construct the exponent-p central tensors of G and H. From the way we have created the groups, G isomorphic to 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)

An implication of the main algorithm in [BMW17] 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 isomorphic to 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>
]

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 x V ↣ W. The algebra A depends on the tensor category of T. If the tensor category forces equality between U, V, and W, then A isomorphic to 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 isomorphic to U direct-sum W as vector spaces and is a nilpotent algebra where C(A)≥W and A2≤W. Otherwise, A isomorphic to U direct-sum V direct-sum W as vector spaces, and using * for T, (u, v, w).(u', v', w') = (0, 0, u * v').

Example Multilinear_CraftingAlgebras (H62E43)

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 Q3 x Q3 ↣ Q3.

> 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)

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 x 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]
]

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]
]

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]
]
HeisenbergLieAlgebra(T) : TenSpcElt -> AlgLie
Returns the Heisenberg Lie algebra L with Lie bracket given by the 3-tensor T:U x V ↣ 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 isomorphic to U direct-sum W as vector spaces. Otherwise, L isomorphic to U direct-sum V direct-sum 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 Multilinear_CraftingLieAlgberas (H62E44)

We will construct an alternating tensor with frame Q3 x Q3 ↣ Q2.

> 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]
]

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]
]
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]
]
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 x V ↣ 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|.|W|. Otherwise, the group returned is an extension of U direct-sum V by W, so |G| = |U|.|V| .|W|. If T is not full, then G is an extension of U direct-sum V direct-sum W/(im)(T) (or V direct-sum W/(im)(T)) by (im)(T).

Example Multilinear_CraftingPGroups (H62E45)

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

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
Even though t is alternating, the category does not fuse together U and V. Therefore, the Heisenberg group H is an extension of U direct-sum V by W, and hence, |H|=55 + 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)

Now we will fuse the 2 and 1 coordinate, so that |H|=55 + 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)

Note that t and s are not the same tensor. However, they are pseudo-isometric (isotopic in the category with U2=U1). 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]
]

Example Multilinear_PGroupsHalfFull (H62E46)

We will start with an alternating tensor that is not full with the frame GF(3)4 x GF(3)4 ↣ GF(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]
]

Because the tensor category of t does not force equality between U and V, the group H created from t will have order 311 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 GF(3)4 + 4 + 1 x GF(3)4 + 4 + 1 ↣ GF(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]
]
V2.28, 13 July 2023