In Magma a tensor space is a parent type for tensors.  It behaves as a module
but also maintains an interpretation of its elements as a multilinear map.  Each
tensor space further maintains a tensor category which is also assigned to its
tensors.  Note that in \cite{FMW:densors}*{Section~7} tensors do not explicitly
require a parent tensor space type.  This deviation is in accordance with
Magma's design patterns for vectors and vector spaces, matrices and matrix
spaces.  Consequently, the pattern here is more verbose and all primitive data
types representing tensors are afforded as tensor spaces of specific types,
e.g. \texttt{KTensorSpace} for tensor spaces for fields $K$,
\texttt{RTensorSpace} for commutative ring $R$ and free modules, and
\texttt{TensorSpace} for black-box tensor spaces.  Sparse and dense representations
are indeed handled by system level types to remain efficient.

\section{Constructions of tensor and cotensor spaces}

\subsection{Universal tensor spaces}

Construction of universal tensor spaces is modeled after construction of free
modules and matrix spaces. For efficiency reasons, the actual representation
may
vary based on the parameters, e.g. it may be a space of structure constants,
black-box functions, or systems of forms. So access to the tensors in these
tensor space should be made through the provided functions.

\index{KTensorSpace}
\begin{intrinsics}
KTensorSpace(K, S) : Fld, [RngIntElt] -> TenSpc
KTensorSpace(K, S, C) : Fld, [RngIntElt], TenCat -> TenSpc
\end{intrinsics}

For a field $K$ and sequence $S=[d_{\vav},\ldots, d_0]$, returns the universal
tensor space $K^{d_0}\oslash \cdots\oslash K^{d_{\vav}}$ with covariant tensor
category given by $C$. The default category is the homotopism category.

\index{RTensorSpace}
\begin{intrinsics}
RTensorSpace(R, S) : Rng, [RngIntElt] -> TenSpc
RTensorSpace(R, S, C) : Rng, [RngIntElt], TenCat -> TenSpc
\end{intrinsics}

For a commutative ring $R$ and sequence $S=[d_{\vav},\cdots, d_0]$, returns the
universal tensor space $R^{d_0}\oslash\cdots\oslash R^{d_{\vav}}$ with covariant tensor
category given by $C$. The default category is the homotopism category.

\begin{example}[UniversalKTenSpc]

We demonstrate how to construct universal tensor spaces from a field
$K=\mathbb{Q}$ and a sequence of nonnegative integers $[6,5,4,3]$. The resulting
tensor space is isomorphic to the space of multilinear maps with frame
\[
    \mathbb{Q}^6\times \mathbb{Q}^5\times\mathbb{Q}^4\rightarrowtail\mathbb{Q}^3.
\]
\begin{code}
> K := Rationals();
> S := [6, 5, 4, 3];
> T := KTensorSpace(K, S);
> T;
Tensor space of dimension 360 over Rational Field with valence 4
U3 : Full Vector space of degree 6 over Rational Field
U2 : Full Vector space of degree 5 over Rational Field
U1 : Full Vector space of degree 4 over Rational Field
U0 : Full Vector space of degree 3 over Rational Field
\end{code}

Because tensor spaces act like modules, we can construct tensors in the same way we construct vectors.
\begin{code}
> t := T![Random([-1, 0, 1]) : i in [1..Dimension(T)]];
> t;
Tensor of valence 4, U3 x U2 x U1 >-> U0
U3 : Full Vector space of degree 6 over Rational Field
U2 : Full Vector space of degree 5 over Rational Field
U1 : Full Vector space of degree 4 over Rational Field
U0 : Full Vector space of degree 3 over Rational Field
> Parent(t);
Tensor space of dimension 360 over Rational Field with valence 4
U3 : Full Vector space of degree 6 over Rational Field
U2 : Full Vector space of degree 5 over Rational Field
U1 : Full Vector space of degree 4 over Rational Field
U0 : Full Vector space of degree 3 over Rational Field
\end{code}
\end{example}

\index{TensorSpace}
\begin{intrinsics}
TensorSpace(S) : SeqEnum -> TenSpc, List
TensorSpace(S) : List -> TenSpc, List
TensorSpace(S, C) : SeqEnum, TenCat -> TenSpc, List
TensorSpace(S, C) : List, TenCat -> TenSpc, List
\end{intrinsics}

Given a sequence $S=[U_{\vav},\dots, U_0]$ of $R$-modules returns a universal tensor
space equivalent to $U_0\oslash \cdots\oslash U_{\vav}$ with covariant tensor
category given by $C$ and a list of maps into the vector spaces in the frame.
The default category is the homotopism category.

\begin{example}[UniversalTenSpc]

We will construct a similar tensor space as the previous example.
However, the objects will be different, according to Magma.
\begin{code}
> R := Integers();
> S := [* RMatrixSpace(R, 2, 3), RSpace(R, 5), RMatrixSpace(R, 2, 2), \
>     RSpace(R, 3) *];
> T := TensorSpace(S);
> T;
Tensor space of dimension 360 over Integer Ring with valence 4
U3 : Full RSpace of degree 6 over Integer Ring
U2 : Full RSpace of degree 5 over Integer Ring
U1 : Full RSpace of degree 4 over Integer Ring
U0 : Full RSpace of degree 3 over Integer Ring
\end{code}

Even though the frame of $T$ does not include matrix spaces, like with tensors,
it can still evaluate matrices. For example, we evaluate $T$ at $(0,0,0)$, which
is the trivial subspace in $\mathbb{Z}^3$.
\begin{code}
> x := < X!0 : X in S[1..3] >;
> x;
<
    [0 0 0]
    [0 0 0],

    (0 0 0 0 0),

    [0 0]
    [0 0]
>
> x @ T;
RSpace of degree 3, dimension 0 over Integer Ring
Generators:

\end{code}
\end{example}

\index{TensorSpace!signatured}
\begin{intrinsics}
TensorSpace(V, p, q) : ModTupFld, RngIntElt, RngIntElt -> TenSpc
TensorSpace(K, d, p, q) : Fld, RngIntElt, RngIntElt, RngIntElt -> TenSpc
\end{intrinsics}

Returns the signatured $(p,q)$-tensor space over the vector space $V=K^d$. The
first $p$ indices are covariant and the last $q$ indices are contravariant. This
is functionally equivalent to creating a universal tensor space from the
sequence $[V,\dots,_p V, V^*,\dots,_q V^*, K]$ and the tensor category with
arrows $[1,\dots,_p 1, -1,\dots,_q -1, 0]$ and duplicates
$\{\{p+q,\dots,1+q\},\{q,\dots,1\},\{0\}\}$. The valence of the returned tensor
space will be $p+q+1$.

\begin{example}[SignaturedTenSpc]

Here we simply demonstrate the nuances of the signatured tensor space constructor.
We set $V=\mathbb{F}_5^4$, $p=3$, and $q=2$, and the tensor space we will construct will have frame
\[ V\times V\times V \times V^* \times V^*\rightarrowtail\mathbb{F}_5. \]
Notice this is equivalent to the frame $V\times V\times V\rightarrowtail V \times V$.
\begin{code}
> K := GF(5);
> T := TensorSpace(K, 4, 3, 2);
> T;
Tensor space of dimension 1024 over GF(5) with valence 6
U5 : Full Vector space of degree 4 over GF(5)
U4 : Full Vector space of degree 4 over GF(5)
U3 : Full Vector space of degree 4 over GF(5)
U2 : Full Vector space of degree 4 over GF(5)
U1 : Full Vector space of degree 4 over GF(5)
U0 : Full Vector space of degree 1 over GF(5)
> S := KTensorSpace(K, [4, 4, 4, 4, 4, 1]);
> S;
Tensor space of dimension 1024 over GF(5) with valence 6
U5 : Full Vector space of degree 4 over GF(5)
U4 : Full Vector space of degree 4 over GF(5)
U3 : Full Vector space of degree 4 over GF(5)
U2 : Full Vector space of degree 4 over GF(5)
U1 : Full Vector space of degree 4 over GF(5)
U0 : Full Vector space of degree 1 over GF(5)
\end{code}

However, the subtleties of this construction lies in the tensor category.
On the surface, the spaces $T$ and $S$ look the same, but probing the category reveals their differences.
\begin{code}
> TensorCategory(S); // default category
Tensor category of valence 6 (->,->,->,->,->,->) ({ 1 },{ 2 },{ 0 },{ 3 },{ 4
},{ 5 })
> TensorCategory(T);
Tensor category of valence 6 (<-,<-,<-,->,->,==) ({ 0 },{ 3 .. 5 },{ 1 .. 2 })
> S eq T;
false
\end{code}
\end{example}

\subsection{Universal cotensor spaces}~

Currently, we only consider cotensor spaces over fields.

\index{KCotensorSpace}
\begin{intrinsics}
KCotensorSpace(K, S) : Fld, [RngIntElt] -> TenSpc
KCotensorSpace(K, S, C) : Fld, [RngIntElt], TenCat -> TenSpc
\end{intrinsics}

For a field $K$ and sequence $S=[d_{\vav},\dots, d_1]$ returns the universal cotensor
space $\bigotimes_{a\in\comp{0}}K^{d_a}$ with the given contravariant tensor category $C$.
The default category is the homotopism category.
Notice the sequence $S$ indices do \emph{not} include 0.

\index{CotensorSpace}
\begin{intrinsics}
CotensorSpace(S) : SeqEnum -> TenSpc, List
CotensorSpace(S) : List -> TenSpc, List
CotensorSpace(S, C) : SeqEnum, TenCat -> TenSpc, List
CotensorSpace(S, C) : List, TenCat -> TenSpc, List
\end{intrinsics}

Given a sequence $S=[U_{\vav},\dots, U_1]$ of $K$-vector spaces returns the universal tensor
space equivalent to $\bigotimes_{a\in\comp{0}}U_a$ with contravariant tensor
category given by $C$ and a list of maps into the vector spaces of the frame.
The default category is the homotopism category.
Notice the sequence $S$ indices do \emph{not} include 0.

\begin{example}[UniversalCoTenSpc]

Constructing cotensor spaces is nearly the same as constructing tensor spaces.
When providing a sequence of modules or a sequence of dimensions, we do not
include the entry for $U_0$. It is automatically set to $U_0=K$. Furthermore,
the black-box construction forgets all other structure of the vector spaces and
only builds a frame out of vector spaces. The maps are returned as a
\texttt{List} in case they are needed.
\begin{code}
> K := Rationals();
> S := [* KSpace(K, 3), MatrixAlgebra(K, 3), KMatrixSpace(K, 2, 3) *];
> S;
[*
    Full Vector space of degree 3 over Rational Field,
    Full Matrix Algebra of degree 3 over Rational Field,
    Full KMatrixSpace of 2 by 3 matrices over Rational Field
*]
> T := CotensorSpace(S);
> T;
Cotensor space of dimension 162 over Rational Field with valence 4
U3 : Full Vector space of degree 3 over Rational Field
U2 : Full Vector space of degree 9 over Rational Field
U1 : Full Vector space of degree 6 over Rational Field
\end{code}

Like with tensor spaces, cotensors are elements of cotensor spaces, and for many
purposes in Magma, cotensor and tensor spaces have similar functionality.
\begin{code}
> t := T.3;
> t;
Cotensor of valence 4, U3 x U2 x U1 >-> K
U3 : Full Vector space of degree 3 over Rational Field
U2 : Full Vector space of degree 9 over Rational Field
U1 : Full Vector space of degree 6 over Rational Field
> Eltseq(t);
[ 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0 ]
\end{code}
\end{example}

\subsection{Some standard constructions}

We include some subspaces generated by well-known tensors.

\index{AlternatingSpace}
\begin{intrinsics}
AlternatingSpace(T) : TenSpc -> TenSpc, Map
\end{intrinsics}

Returns the sub(co-)tensor space generated by all the alternating (co-)tensors
contained in the given (co-)tensor space and an embedding into $T$.

\index{AntisymmetricSpace}
\begin{intrinsics}
AntisymmetricSpace(T) : TenSpc -> TenSpc, Map
\end{intrinsics}

Returns the sub(co-)tensor space generated by all the antisymmetric (co-)tensors
contained in the given (co-)tensor space and an embedding into $T$.

\index{SymmetricSpace}
\begin{intrinsics}
SymmetricSpace(T) : TenSpc -> TenSpc, Map
\end{intrinsics}

Returns the sub(co-)tensor space generated by all the symmetric (co-)tensors
contained in the given (co-)tensor space  and an embedding into $T$.

\begin{example}[StandardTenSubspcs]

We will construct some standard tensor subspaces of the universal tensor space
with frame $\mathbb{F}_3^4\times \mathbb{F}_3^4\rightarrowtail\mathbb{F}_3^4$.
\begin{code}
> K := GF(3);
> T := KTensorSpace(K, [4, 4, 4]);
> T;
Tensor space of dimension 64 over GF(5) with valence 3
U2 : Full Vector space of degree 4 over GF(5)
U1 : Full Vector space of degree 4 over GF(5)
U0 : Full Vector space of degree 4 over GF(5)
\end{code}

First, we will construct the subspace of $T$ containing all alternating bilinear maps.
Since $\binom{4}{2}=6$, we expect the subspace to be 24-dimensional in $T$.
\begin{code}
> Alt := AlternatingSpace(T);
> Alt;
Tensor space of dimension 24 over GF(3) with valence 3
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 4 over GF(3)
> t := Random(Alt);
> 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 4 over GF(3)
> IsAlternating(t);
true
\end{code}

Now we will construct the symmetric subspace of the alternating subspace, which is trivial.
\begin{code}
> S := SymmetricSpace(Alt);
> S;
Tensor space of dimension 0 over GF(3) with valence 3
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 4 over GF(3)
\end{code}
\end{example}

\index{ExteriorCotensorSpace}
\begin{intrinsics}
ExteriorCotensorSpace(V, n) : ModTupFld, RngIntElt -> TenSpc
\end{intrinsics}

Returns the cotensor space given by the $n$th exterior power of the vector space $V$.

\index{SymmetricCotensorSpace}
\begin{intrinsics}
SymmetricCotensorSpace(V, n) : ModTupFld, RngIntElt -> TenSpc
\end{intrinsics}

Returns the cotensor space given by the $n$th symmetric power of the vector space $V$.

\begin{example}[StandardCoTenSubspcs]

We set $V=\mathbb{F}_5^6$ and we construct the cotensor space of the symmetric
square of $V$, $V\wedge V$. The frame is $V\times V\rightarrowtail
\mathbb{F}_5$, so the cotensor space is $\binom{6}{2}$-dimensional.
\begin{code}
> V := VectorSpace(GF(5), 6);
> T := ExteriorCotensorSpace(V, 2);
> T;
Cotensor space of dimension 15 over GF(5) with valence 3
U2 : Full Vector space of degree 6 over GF(5)
U1 : Full Vector space of degree 6 over GF(5)
\end{code}

The cotensor space $T$ is generated by all alternating tensors $\bra{t} :
V\times V\rightarrowtail \mathbb{F}_5$. We will demonstrate by constructing a
random cotensor from $T$.
\begin{code}
> t := Random(T);
> t;
Cotensor of valence 3, U2 x U1 >-> K
U2 : Full Vector space of degree 6 over GF(5)
U1 : Full Vector space of degree 6 over GF(5)
> SystemOfForms(t);
[
    [0 2 2 2 4 1]
    [3 0 4 1 0 0]
    [3 1 0 3 1 1]
    [3 4 2 0 2 0]
    [1 0 4 3 0 2]
    [4 0 4 0 3 0]
]
> IsAlternating(t);
true
\end{code}

Notice this construction is not $V\times V\rightarrowtail V\wedge V$.
However, if we want this tensor, we can use the intrinsic \texttt{AsTensor}.
\begin{code}
> s := AsTensor(T);
> s;
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 15 over GF(5)
> IsAlternating(s);
true
\end{code}
\end{example}

\section{Operations on tensor spaces}

\subsection{Membership and comparison with tensor spaces}

We define some intuitive functions for tensor spaces, similar to those found for modules.

\index{in}
\begin{intrinsics}
t in T : TenSpcElt, TenSpc -> BoolElt
\end{intrinsics}

Decides if $t$ is contained in the tensor space $T$.

\index{IsCoercible!tensor}\index{BANG!tensor}
\begin{intrinsics}
IsCoercible(T, t) : TenSpc, TenSpcElt -> BoolElt
T ! t : TenSpc, TenSpcElt -> TenSpcElt
\end{intrinsics}

Decides if the tensor $t$ can be coerced into the tensor space $T$. If so, the
tensor is returned as an element of $T$.

\index{IsCoercible!sequence}\index{BANG!sequence}
\begin{intrinsics}
IsCoercible(T, S) : TenSpc, [RngElt] -> BoolElt
T ! S : TenSpc, SeqEnum -> TenSpcElt
\end{intrinsics}

Decides if the sequence $S$ can be coerced into the tensor space $T$ as a
tensor. If so, the corresponding tensor is returned.

\index{IsCoercible!zero}\index{BANG!zero}
\begin{intrinsics}
IsCoercible(T, n) : TenSpc, RngIntElt -> BoolElt
T ! n : TenSpc, RngIntElt -> TenSpcElt
\end{intrinsics}

This is a shortcut designed to only work when $n=0$, and thus, return {\tt true}
and the zero tensor from the tensor space. Any other integer will yield an
error.

\begin{example}[Coercion]
We illustrate that using \texttt{!} is the same as creating the tensor from scratch.

\begin{code}
> T := KTensorSpace( GF(2), [2,3,2] );
> T;
Tensor space of dimension 12 over GF(2) with valence 3
U2 : Full Vector space of degree 2 over GF(2)
U1 : Full Vector space of degree 3 over GF(2)
U0 : Full Vector space of degree 2 over GF(2)
>
> S := [ 1 : i in [1..12] ];
> t := T!S;
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 2 over GF(2)
U1 : Full Vector space of degree 3 over GF(2)
U0 : Full Vector space of degree 2 over GF(2)
>
> t eq Tensor(GF(2), [2,3,2], S);
true
>
> T!0 in T;
true
> SystemOfForms(T!0);
[
    [0 0 0]
    [0 0 0],

    [0 0 0]
    [0 0 0]
]
\end{code}

\end{example}

\index{eq!tensor space}
\begin{intrinsics}
S eq T : TenSpc, TenSpc -> BoolElt
\end{intrinsics}

Decides if the tensor spaces $S$ and $T$ are equal.

\index{subset}
\begin{intrinsics}
S subset T : TenSpc, TenSpc -> BoolElt
\end{intrinsics}

Decides if $S$ is a subset of the tensor space $T$.

\index{IsCoercible!tensor space}\index{BANG!tensor space}
\begin{intrinsics}
IsCoercible(T, S) : TenSpc, TenSpc -> BoolElt
T ! S : TenSpc, TenSpc -> TenSpc
\end{intrinsics}

Decides if the tensor space $S$ can be coerced into the tensor space $T$ as a
subspace. If so, the corresponding subspace is returned.

\begin{example}[TenSpcContainment]

We construct the universal tensor space $T$ with the frame $\mathbb{F}_2^4\times
\mathbb{F}_2^4\rightarrowtail \mathbb{F}_2^4$. We also create a tensor space
$T_2$ with frame $\mathbb{F}_2^4\times \mathbb{F}_2\times
\mathbb{F}_2^4\times\mathbb{F}_2\rightarrowtail \mathbb{F}_2^4$.

\begin{code}
> T := KTensorSpace(GF(2), [4,4,4]);
> T;
Tensor space of dimension 64 over GF(2) with valence 3
U2 : Full Vector space of degree 4 over GF(2)
U1 : Full Vector space of degree 4 over GF(2)
U0 : Full Vector space of degree 4 over GF(2)
>
> T2 := KTensorSpace(GF(2), [4,1,4,1,4]);
> T2;
Tensor space of dimension 64 over GF(2) with valence 5
U4 : Full Vector space of degree 4 over GF(2)
U3 : Full Vector space of degree 1 over GF(2)
U2 : Full Vector space of degree 4 over GF(2)
U1 : Full Vector space of degree 1 over GF(2)
U0 : Full Vector space of degree 4 over GF(2)
>
> S := sub< T | T.2, T.4, T.8 >;
> S;
Tensor space of dimension 3 over GF(2) with valence 3
U2 : Full Vector space of degree 4 over GF(2)
U1 : Full Vector space of degree 4 over GF(2)
U0 : Full Vector space of degree 4 over GF(2)
\end{code}

We verify that $S$ is a subset of $T$ and not $T_2$. Since the tensors of $T$
naturally embed into $T_2$, the subspace $S$ can be coerced into $T_2$, which we
label as $S_2$. We then verify that $S_2$ is a subset of $T_2$ and not $T$.
\begin{code}
> S subset T2;
false
> S2 := T2!S;
> S2 subset T2;
true
> S2 subset T;
false
\end{code}
\end{example}

\subsection{Tensor spaces as modules}

We view a tensor space as a $K$-module, so we have notions of generators,
dimension (if it is free), and cardinality.

\index{Generators}\index{Basis}
\begin{intrinsics}
Basis(T) : TenSpc -> SeqEnum
Generators(T) : TenSpc -> SeqEnum
\end{intrinsics}

Returns a basis for the tensor space $T$.

\index{.!tensor space}
\begin{intrinsics}
T.i : TenSpc, RngIntElt -> TenSpcElt
\end{intrinsics}

Returns the $i$th basis tensor of the tensor space $T$.

\index{NumberOfGenerators}\index{Ngens}
\begin{intrinsics}
NumberOfGenerators(T) : TenSpc -> RngIntElt
Ngens(T) : TenSpc -> RngIntElt
\end{intrinsics}

Returns the number of generators of the tensor space $T$.

\index{Dimension}
\begin{intrinsics}
Dimension(T) : TenSpc -> RngIntElt
\end{intrinsics}

Returns the dimension of the tensor space $T$ as a free $K$-module.

\index{\#}
\begin{intrinsics}
# T : TenSpc -> RngIntElt
\end{intrinsics}

Returns the size of the tensor space, provided $T$ is finite.

\begin{example}[BasicModule]

We demonstrate the basic module functions of tensor spaces. We construct the
universal tensor space $T$ with frame
$\mathbb{F}_8^3\times\mathbb{F}_8^5\rightarrowtail\mathbb{F}_8^7$.
\begin{code}
> K := GF(8);
> T := KTensorSpace(K, [3,5,7]);
> T;
Tensor space of dimension 105 over GF(2^3) with valence 3
U2 : Full Vector space of degree 3 over GF(2^3)
U1 : Full Vector space of degree 5 over GF(2^3)
U0 : Full Vector space of degree 7 over GF(2^3)
\end{code}

Now we obtain module properties of $T$.
\begin{code}
> Dimension(T);
105
> #Basis(T);
105
> T.100 in Basis(T);
true
> T.100;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 3 over GF(2^3)
U1 : Full Vector space of degree 5 over GF(2^3)
U0 : Full Vector space of degree 7 over GF(2^3)
> #T eq 8^(3*5*7);
true
\end{code}
\end{example}

\index{Random}
\begin{intrinsics}
Random(T) : TenSpc -> TenSpcElt
\end{intrinsics}

Provided the base ring has a random algorithm in Magma, it returns a random
element of the tensor space $T$.

\index{RandomTensor}\index{RandomCotensor}
\begin{intrinsics}
RandomTensor(R, S) : Rng, [RngIntElt] -> TenSpcElt
RandomTensor(R, S, C) : Rng, [RngIntElt], TenCat -> TenSpcElt
RandomCotensor(K, S) : Fld, [RngIntElt] -> TenSpcElt
\end{intrinsics}

Provided $R$ has a random algorithm in Magma, it returns a random (co)tensor from
the universal (co)tensor space $\rversor_{s\in S} R^{s}$, with category $C$.
The default category is the homotopism category.

\begin{example}[RandomTensors]

We create some random tensors, which works similarly to \texttt{RandomMatrix} in
Magma. There are two main ways to obtain a random tensor: from a given tensor
space or from a ring and a dimension sequence (the universal tensor space).
First we will construct the alternating tensor space of the universal tensor
space with frame $\mathbb{F}_3^4\times\mathbb{F}_3^4\rightarrowtail
\mathbb{F}_3^2$.
\begin{code}
> T := KTensorSpace(GF(3), [4,4,2]);
> T;
Tensor space of dimension 32 over GF(3) with valence 3
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 2 over GF(3)
> S := AlternatingSpace(T);
> S;
Tensor space of dimension 12 over GF(3) with valence 3
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 2 over GF(3)
\end{code}

Now we construct a random alternating tensor from $S$.
\begin{code}
> t := Random(S);
> 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 2 over GF(3)
> SystemOfForms(t);
[
    [0 0 0 1]
    [0 0 1 2]
    [0 2 0 0]
    [2 1 0 0],

    [0 2 1 2]
    [1 0 1 2]
    [2 2 0 0]
    [1 1 0 0]
]
\end{code}
\end{example}

\index{RandomAlternatingTensor}
\begin{intrinsics}
RandomAlternatingTensor(R, d, n, c) : Rng, RngIntElt, RngIntElt, RngIntElt -> TenSpcElt
RandomAlternatingTensor(R, S) : Rng, [RngIntElt] -> TenSpcElt
\end{intrinsics}

Returns a random alternating tensor from the universal tensor space $\prod_{k=1}^n R^d \rightarrowtail R^c$.
If $S$ is given instead, then we assume $S=[d,\dots,d,c]$.
The returned tensor has the homotopism category but fuses every module in the domain.
An error is raised if $R$ does not have a random algorithm in Magma.

\index{RandomAntisymmetricTensor}
\begin{intrinsics}
RandomAntisymmetricTensor(R, d, n, c) : Rng, RngIntElt, RngIntElt, RngIntElt -> TenSpcElt
RandomAntisymmetricTensor(R, S) : Rng, [RngIntElt] -> TenSpcElt
\end{intrinsics}

Returns a random antisymmetric tensor from the universal tensor space $\prod_{k=1}^n R^d \rightarrowtail R^c$.
If $S$ is given instead, then we assume $S=[d,\dots,d,c]$.
The returned tensor has the homotopism category but fuses every module in the domain.
An error is raised if $R$ does not have a random algorithm in Magma.

\index{RandomSymmetricTensor}
\begin{intrinsics}
RandomSymmetricTensor(R, d, n, c) : Rng, RngIntElt, RngIntElt, RngIntElt -> TenSpcElt
RandomSymmetricTensor(R, S) : Rng, [RngIntElt] -> TenSpcElt
\end{intrinsics}

Returns a random symmetric tensor from the universal tensor space $\prod_{k=1}^n R^d \rightarrowtail R^c$.
If $S$ is given instead, then we assume $S=[d,\dots,d,c]$.
The returned tensor has the homotopism category but fuses every module in the domain.
An error is raised if $R$ does not have a random algorithm in Magma.

\begin{example}[RandomSymTen]

We just demonstrate how to use the \texttt{RandomSymmetricTensor}. The other two
intrinsics are the same. This is almost equivalent to constructing a random
tensor whose category fuses all the modules in the domain and then applying
\texttt{SymmetricTensor}. In characteristic 2, all entries on the diagonal will
be 0, but with \texttt{RandomSymmetricTensor} this is not the case.
\begin{code}
> t := RandomSymmetricTensor(GF(2), 4, 2, 3);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 4 over GF(2)
U1 : Full Vector space of degree 4 over GF(2)
U0 : Full Vector space of degree 3 over GF(2)
>
> TensorCategory(t);
Tensor category of valence 3 (->,->,->) ({ 0 },{ 1 .. 2 })
>
> SystemOfForms(t);
[
    [1 0 0 1]
    [0 1 1 1]
    [0 1 1 0]
    [1 1 0 0],

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

    [0 0 0 0]
    [0 0 1 0]
    [0 1 0 0]
    [0 0 0 1]
]
> IsSymmetric(t);
true
\end{code}
\end{example}

\subsection{Properties of tensor spaces}

We define some functions to access basic properties of tensor spaces.

\index{Valence!tensor space}
\begin{intrinsics}
Valence(T) : TenSpc -> RngIntElt
\end{intrinsics}

Returns the valence of the tensor space.

\index{Frame!tensor space}
\begin{intrinsics}
Frame(T) : TenSpc -> List
\end{intrinsics}

Returns the list of modules in the frame of the tensor space.

\index{BaseRing!tensor space}\index{BaseField!tensor space}
\begin{intrinsics}
BaseRing(T) : TenSpc -> Rng
BaseField(T) : TenSpc -> Fld
\end{intrinsics}

Returns the base ring (or field) of the tensor space.

\begin{example}[TenSpcProperties]

As with tensors, we can obtain the basic tensor properties from a tensor space.
\begin{code}
> T := KTensorSpace(Rationals(), [7,5,3,2]);
> T;
Tensor space of dimension 210 over Rational Field with valence 4
U3 : Full Vector space of degree 7 over Rational Field
U2 : Full Vector space of degree 5 over Rational Field
U1 : Full Vector space of degree 3 over Rational Field
U0 : Full Vector space of degree 2 over Rational Field
> Valence(T);
4
> Frame(T);
[*
    Full Vector space of degree 7 over Rational Field,

    Full Vector space of degree 5 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
\end{code}
\end{example}

\index{TensorCategory!tensor space}
\begin{intrinsics}
TensorCategory(T) : TenSpc -> TenCat
\end{intrinsics}

Returns the underlying tensor category of the tensor space.

\index{IsCovariant!tensor space}\index{IsContravariant!tensor space}
\begin{intrinsics}
IsCovariant(T) : TenSpc -> BoolElt
IsContravariant(T) : TenSpc -> BoolElt
\end{intrinsics}

Decides if the underlying tensor category is covariant or contravariant.

\index{ChangeTensorCategory!tensor space}
\begin{intrinsics}
ChangeTensorCategory(T, C) : TenSpc, TenCat -> TenSpc
ChangeTensorCategory(~T, C) : TenSpc, TenCat ->
\end{intrinsics}

Returns the tensor category with the given tensor category.

\begin{example}[TenSpcCategories]

Again, like with tensors, we can obtain categorical information from tensor spaces.
\begin{code}
> T := KTensorSpace(Rationals(), [4,4,4]);
> T;
Tensor space of dimension 64 over Rational Field with valence 3
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
>
> TensorCategory(T);
Tensor category of valence 3 (->,->,->) ({ 1 },{ 2 },{ 0 })
> C := TensorCategory([1,1,-1], {{0},{1,2}});
> C;
Tensor category of valence 3 (->,->,<-) ({ 0 },{ 1, 2 })
>
> ChangeTensorCategory(~T, C);
> T;
Tensor space of dimension 64 over Rational Field with valence 3
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
> TensorCategory(T);
Tensor category of valence 3 (->,->,<-) ({ 0 },{ 1, 2 })
\end{code}
\end{example}

\index{IsAlternating!tensor space}
\begin{intrinsics}
IsAlternating(T) : TenSpc -> BoolElt
\end{intrinsics}

Decides if every tensor in the tensor space is an alternating tensor.

\index{IsAntisymmetric!tensor space}
\begin{intrinsics}
IsAntisymmetric(T) : TenSpc -> BoolElt
\end{intrinsics}

Decides if every tensor in the tensor space is an antisymmetric tensor.

\index{IsSymmetric!tensor space}
\begin{intrinsics}
IsSymmetric(T) : TenSpc -> BoolElt
\end{intrinsics}

Decides if every tensor in the tensor space is a symmetric tensor.

\index{UniversalTensorSpace}\index{UniversalCotensorSpace}\index{Generic}
\begin{intrinsics}
UniversalTensorSpace(T) : TenSpc -> TenSpc
UniversalCotensorSpace(T) : TenSpc -> TenSpc
Generic(T) : TenSpc -> TenSpc
\end{intrinsics}

Returns the universal (co-)tensor space with the same frame and category as $T$.

\begin{example}[UniversalConst]

We construct the subspace of alternating tensors $S$ of the tensor space $T$
with the frame $\mathbb{Q}^6\times\mathbb{Q}^6\rightarrowtail \mathbb{Q}^2$. We
verify that the space is in fact alternating (i.e.\ every tensor is
alternating).
\begin{code}
> T := KTensorSpace(Rationals(), [6,6,2]);
> S := AlternatingSpace(T);
> S;
Tensor space of dimension 30 over Rational Field with valence 3
U2 : Full Vector space of degree 6 over Rational Field
U1 : Full Vector space of degree 6 over Rational Field
U0 : Full Vector space of degree 2 over Rational Field
> IsAlternating(S);
true
\end{code}

From $S$, we construct the universal tensor space $U$, which in this example is equal to $T$.
\begin{code}
> U := UniversalTensorSpace(S);
> U;
Tensor space of dimension 72 over Rational Field with valence 3
U2 : Full Vector space of degree 6 over Rational Field
U1 : Full Vector space of degree 6 over Rational Field
U0 : Full Vector space of degree 2 over Rational Field
> U eq T;
true
\end{code}
\end{example}

%=============================================================================

\chapter{Tensor categories}\label{ch:tensor-categories}

Following \cite{FMW:densors}*{Section~5.7 \& Section~7}, Magma allows tensors
and tensor spaces to change categories. Unless a user specifies otherwise, all
tensors are assigned a category that is natural to the method by which it was
created. For example a tensor created from an algebra will be assigned an
algebra category, whereas a tensor created by structure constants will be
assigned the homotopism category \citelist{\cite{Albert:Fundamentals}
\cite{Wilson:division} \cite{FMW:densors}*{Section~5.7}}. Tensor categories
influence the behavior of commands such as kernels and images as well as the
algebraic invariants such as derivation algebras of a tensor.

Our conventions follow \citelist{\cite{FMW:densors}*{Section~5.7} \cite{Wilson:division}}.  In particular given
a tensor $t$ framed by $[U_{\vav},\dots,U_0]$ then a tensor category for
$t$ will specify a function $A:\zrange{\vav}\to \{-1,0,1\}$ along with
a partition $\mathcal{P}$ of $\zrange{\vav}$ such that the following
rules apply to the tensors and morphisms in the category.
\begin{enumerate}
\item for each tensor $t$ framed by $[U_{\vav},\dots,U_0]$, if
$X\in\mathcal{P}$, then
$$\forall i,j\in X,\quad U_i=U_j.$$

\item Given a second tensor $s$ framed by $[V_{\vav},\dots,V_0]$,
a morphism $f:t\to s$ (Magma type {\tt Hmtp}) will be a list
$[f_{\vav},\dots,f_0]$ of homomorphisms as follows:
\begin{itemize}
\item (Covariant) if $A(i)=1$ then $f_i:U_i\to V_i$;
\item (Constant) if $A(i)=0$ then $U_i=V_i$ and $f_i=1_{U_i}$; or else
\item (Contravariant) $A(i)=-1$ and $f_i:U_i\leftarrow V_i$.
\end{itemize}
So if $A(0)=1$ then
\begin{align*}
	\left\langle \sum_{i\in A^{-1}(1)} u_i f_i
		+\sum_{j\not\in A^{-1}(-1)} v_j\right\rangle_S
		& = \left\langle  \sum_{i\in A^{-1}(1)} u_i
		+\sum_{j\not\in A^{-1}(-1)} v_j f_j\right\rangle_T f_0;
\end{align*}
if $A(0)=0$ then
\begin{align*}
	\left\langle \sum_{i\in A^{-1}(1)} u_i f_i
		+\sum_{j\not\in A^{-1}(-1)} v_j\right\rangle_S
		& = \left\langle  \sum_{i\in A^{-1}(1)} u_i
		+\sum_{j\not\in A^{-1}(-1)} v_j f_j\right\rangle_T;
\end{align*}
else $A(0)=-1$ and
\begin{align*}
	\left\langle \sum_{i\in A^{-1}(1)} u_i f_i
		+\sum_{j\not\in A^{-1}(-1)} v_j\right\rangle_S f_0
		& = \left\langle  \sum_{i\in A^{-1}(1)} u_i
		+\sum_{j\not\in A^{-1}(-1)} v_j f_j\right\rangle_T.
\end{align*}
\end{enumerate}

Magma manages internally the differences between
vectors and covectors and more generally tensors and cotensors.
Both types are issued the Magma type {\tt TenSpcElt}.
For operations sensitive to the difference, Magma stores a value of
co/contra-variance of the tensor as a property of the tensor category.
This the third general property stored in Magma's tensor category type
{\tt TenCat}.

We use the phrase tensor category exclusively for categories that describe tensors and tensor spaces.
In other words, the data structure of a tensor category is a function
$A:\zrange{\vav}\rightarrow \{-1,0,1\}$ and a partition $\mathcal{P}$ of $\zrange{\vav}$.
It is useful to distinguish from tensors and cotensors at the categorical level,
so a tensor category is either covariant or contravariant as well
(in the latter case, referred to as a cotensor category).

\section{Constructing tensor categories}~

\index{TensorCategory!constructor}
\begin{intrinsics}
TensorCategory(A, P) : [RngIntElt], {SetEnum} -> TenCat
TensorCategory(A, P) : Map, {SetEnum} -> TenCat
\end{intrinsics}

Sets up a covariant tensor space category with specified direction of
arrows $A$, and a partition $\mathcal{P}$ indicating variables to be treated as
equivalent.  The fiber $A^{-1}(1)$ denotes the covariant variables,
$A^{-1}(0)$ identifies the constant variables, and $A^{-1}(-1)$ marks
the contra-variant variables.

\index{CotensorCategory!constructor}
\begin{intrinsics}
CotensorCategory(A, P) : [RngIntElt], {SetEnum} -> TenCat
CotensorCategory(A, P) : Map, {SetEnum} -> TenCat
\end{intrinsics}

Sets up a contra-variant tensor space category with specified direction of
arrows $A$, and a partition $\mathcal{P}$ indicating variables to be treated as
equivalent.  The fiber $A^{-1}(1)$ denotes the covariant variables,
$A^{-1}(0)$ identifies the constant variables, and $A^{-1}(-1)$ marks
the contra-variant variables.

\begin{example}[BasicCatConst]

We demonstrate the basic tensor category constructor. The only difference
between \texttt{TensorCategory} and \texttt{CotensorCategory} is that the former
is covariant and the latter is contravariant.
\begin{code}
> C := TensorCategory([1,0,-1], {{0},{1},{2}});
> C;
Tensor category of valence 3 (->,==,<-) ({ 1 },{ 2 },{ 0 })
> IsCovariant(C);
true
>
> arrows := map< {1..5} -> {1} | x :-> 1 >;
> C := CotensorCategory(arrows, {{1..5}});
> C;
Cotensor category of valence 6 (->,->,->,->,->,==) ({ 0 },{ 1 .. 5 })
> IsContravariant(C);
true
\end{code}
\end{example}

\index{HomotopismCategory}
\begin{intrinsics}
HomotopismCategory(v : parameters) : RngIntElt -> TenCat
    Contravariant : BoolElt : false
\end{intrinsics}

Returns Albert's homotopism category -- all modules categories are covariant and
no duplicates considered. Set the optional parameter {\tt Contravariant} to {\tt
true} to make it a cotensor category.

\index{CohomotopismCategory}
\begin{intrinsics}
CohomotopismCategory(v) : RngIntElt -> TenCat
\end{intrinsics}

Returns the cohomotopism category -- all domain modules categories are
covariant, the codomain is contravariant, and no duplicates considered.

\index{AdjointCategory}\index{LinearCategory}
\begin{intrinsics}
AdjointCategory(v, s, t) : RngIntElt, RngIntElt, RngIntElt -> TenCat
LinearCategory(v, s, t) : RngIntElt, RngIntElt, RngIntElt -> TenCat
\end{intrinsics}

Returns the tensor category where all modules are constant except in position
$s$ and $t$.  Both $s$ and $t$ are in $[v]$.
Position $s$ is covariant, position $t$ is contravariant.

\begin{example}[TenCatSpecial]

Now we look at a few special tensor category constructors. The default tensor
category is the homotopism category, so we construct the homotopism category
using \texttt{TensorCategory} and verify they are equivalent.
\begin{code}
> C := TensorCategory([1,1,1,1], {{i} : i in [0..3]});
> C;
Tensor category of valence 4 (->,->,->,->) ({ 1 },{ 2 },{ 0 },{ 3 })
> HomotopismCategory(4) eq C;
true
\end{code}

The other special tensor categories can be constructed using
\texttt{TensorCategory} as well, but we just construct a few to show their
properties.
\begin{code}
> CohomotopismCategory(3);
Tensor category of valence 3 (->,->,<-) ({ 1 },{ 2 },{ 0 })
>
> AdjointCategory(5, 4, 1);
Tensor category of valence 5 (<-,==,==,->,==) ({ 1 },{ 0, 2, 3 },{ 4 })
\end{code}
\end{example}

\section{Operations on tensor categories}

We have basic operations for tensor categories.

\index{eq!tensor category}
\begin{intrinsics}
C1 eq C2 : TenCat, TenCat -> BoolElt
\end{intrinsics}

Decides if the tensor categories are the same.

\index{Valence!tensor category}
\begin{intrinsics}
Valence(C) : TenCat -> RngIntElt
\end{intrinsics}

Returns the valence of the tensor category.

\index{Arrows}
\begin{intrinsics}
Arrows(C) : TenCat -> SeqEnum
\end{intrinsics}

Returns the sequence of arrows of the tensor category. A $-1$ signifies an a
contravariant index, a $0$ signifies a constant index, and a $1$ signifies a
covariant index.

\index{RepeatPartition}
\begin{intrinsics}
RepeatPartition(C) : TenCat -> SetEnum
\end{intrinsics}

Returns the repeat partition for the tensor category.

\index{IsCovariant!tensor category}\index{IsContravariant!tensor category}
\begin{intrinsics}
IsCovariant(C) : TenCat -> BoolElt
IsContravariant(C) : TenCat -> BoolElt
\end{intrinsics}

Decides if the tensor category is covariant or contravariant.

\begin{example}[TenCatProperties]

We obtain basic properties of tensor categories.
\begin{code}
> C := CotensorCategory([1,0,-1,1],{{4,3},{1},{2}});
> C;
Cotensor category of valence 5 (->,==,<-,->,==) ({ 1 },{ 2 },{ 0 },{ 3, 4 })
>
> Valence(C);
5
> Arrows(C);
[ 1, 0, -1, 1 ]
> IsContravariant(C);
true
> RepeatPartition(C);
{
    { 1 },
    { 2 },
    { 3, 4 }
}
\end{code}
\end{example}

\section{Categorical operations}

In this section, we define subtensors, local ideals, ideals, and quotients of
tensors. For the following definitions fix a tensor $t\in T$, with frame
$U_0\oslash \cdots\oslash U_{\vav}$---that is $U_{\vav}\times\cdots\times
U_1\rightarrowtail U_0$.
\begin{defn}
A tensor $s:V_{\vav}\times \cdots\times V_1\rightarrowtail V_0$ is a
\emph{subtensor} of $t$ if for all $a$, $V_a\leq U_a$.
\end{defn}

\begin{defn}
For $A\subseteq \range{\vav}$, a tensor $s:V_{\vav}\times \cdots\times
V_1\rightarrowtail V_0$ is an \emph{$A$-local ideal} of $t$ if $s$ is a
subtensor of $t$ and for each $a\in A$,
\[ \langle s \,|\, V_{\vav},\dots, V_{a+1}, U_a, V_{a-1},\dots, V_1\rangle \leq V_0 .\]
\end{defn}

\begin{defn}
A tensor $s$ is an \emph{ideal} of $t$ if it is a $\{1,\dots,\vav\}$-local ideal of $t$.
\end{defn}

\begin{defn}
The \emph{$A$-local quotient} of a tensor $t$ by an $A$-local ideal $s$ is the
tensor $q:U_{\vav}/V_{\vav} \times \cdots \times U_1/V_1\rightarrowtail U_0/V_0$
where for all $\ket{\overline{v}}$,
\[ \langle q \,|\, \overline{v}\rangle \equiv \langle q \,|\, v\rangle \mod V_0. \]
\end{defn}

\begin{defn}
The \emph{quotient} of a tensor $t$ by an ideal $s$ is the $\{1,\dots,\vav\}$-local quotient of $t$ by $s$.
\end{defn}

\subsection{Categorical operations on tensors}

We include functions defined for the category of tensors.
Most functions are currently defined only for the homotopism category.

\index{Subtensor}
\begin{intrinsics}
Subtensor(t, S) : TenSpcElt, List -> TenSpcElt
Subtensor(t, S) : TenSpcElt, SeqEnum -> TenSpcElt
\end{intrinsics}

Returns the smallest submap of $t$ containing $S$.

\index{Subtensor}
\begin{intrinsics}
Subtensor(t, D, C) : TenSpcElt, List, Any -> TenSpcElt
Subtensor(t, D, C) : TenSpcElt, SeqEnum, Any -> TenSpcElt
\end{intrinsics}

Returns the smallest submap of $t$ containing $D$ in the domain and $C$ in the
codomain.

\index{IsSubtensor}
\begin{intrinsics}
IsSubtensor(t, s) : TenSpcElt, TenSpcElt -> BoolElt
\end{intrinsics}

Decides whether $s$ is a subtensor of $t$.

\begin{example}[Subtensors]

We construct the tensor $t$ given by octonion multiplication. The quaternions
$H=\mathbb{H}$ are a subalgebra of $A=\mathbb{O}$ generated by the first four
basis elements. However, $H$ cannot be coerced into $A$ because of how Magma
organizes algebras.
\begin{code}
> A := OctonionAlgebra(Rationals(), -1, -1, -1);
> t := Tensor(A);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 8 over Rational Field
U1 : Full Vector space of degree 8 over Rational Field
U0 : Full Vector space of degree 8 over Rational Field
> H := sub< A | A.1, A.2, A.3, A.4 >;
> H;
Algebra of dimension 4 with base ring Rational Field
\end{code}

There are multiple ways to get the subtensor of multiplication from $H$. We will
create $H\times H\rightarrowtail H$ as a subtensor of $A\times A\rightarrowtail
A$.
\begin{code}
> H_gens := [A.i : i in [1..4]];
> s := Subtensor(t, [*H_gens, H_gens, A!0*]);
> s;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Vector space of degree 8, dimension 4 over Rational Field
Generators:
(1 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 1 0 0 0 0)
Echelonized basis:
(1 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 1 0 0 0 0)
U1 : Vector space of degree 8, dimension 4 over Rational Field
Generators:
(1 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 1 0 0 0 0)
Echelonized basis:
(1 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 1 0 0 0 0)
U0 : Vector space of degree 8, dimension 4 over Rational Field
Generators:
(1 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 1 0 0 0 0)
Echelonized basis:
(1 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 1 0 0 0 0)
\end{code}

Note that because $H$ cannot be coerced into $A$ (i.e.\ \texttt{A!H} produces an
error), a subtensor of \texttt{AlgGen} cannot be done by \texttt{Subtensor(t,
[H, H, H])}. Now we will construct the tensor straight from $H$. There is a
subtle difference between the subtensor from $A$ and the tensor from
$H$---namely, the frame is different.
\begin{code}
> s2 := Tensor(H);
> 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 4 over Rational Field
U0 : Full Vector space of degree 4 over Rational Field
> s eq s2;
false
> Eltseq(s) eq Eltseq(s2);
true
\end{code}
\end{example}

\index{LocalIdeal}
\begin{intrinsics}
LocalIdeal(t, S, A) : TenSpcElt, List, {RngIntElt} -> TenSpcElt
LocalIdeal(t, S, A) : TenSpcElt, SeqEnum, {RngIntElt} -> TenSpcElt
\end{intrinsics}

Returns the local ideal of $t$ at $A$ constraining $S$.

\index{LocalIdeal}
\begin{intrinsics}
LocalIdeal(t, D, C, A) : TenSpcElt, List, Any, {RngIntElt} -> TenSpcElt
LocalIdeal(t, D, C, A) : TenSpcElt, SeqEnum, Any, {RngIntElt} -> TenSpcElt
\end{intrinsics}

Returns the local ideal of $t$ at $A$ constraining $D$ in the domain and $C$
in the codomain.

\index{LocalIdeal}
\begin{intrinsics}
LocalIdeal(t, s, A) : TenSpcElt, TenSpcElt, {RngIntElt} -> TenSpcElt
\end{intrinsics}

Returns the local ideal of $t$ at $A$ constraining $s$ as a submap.

\index{IsLocalIdeal}
\begin{intrinsics}
IsLocalIdeal(t, s, A) : TenSpcElt, TenSpcElt, {RngIntElt} -> BoolElt
\end{intrinsics}

Decides if $s$ is a local ideal of $t$ at $A$.

\begin{example}[LocalIdeals]

We use the same tensor $t$ as the previous example, multiplication in
$A=\mathbb{O}$, and we construct the subtensor $t_2$ given by multiplication in
$\mathbb{H}$. We construct a subtensor $s$ of $t$ as the submap containing
$\langle A_2\rangle \times \langle A_1, A_4\rangle \rightarrowtail \langle
0\rangle$, which is equal to  $\langle A_2\rangle \times \langle A_1, A_4\rangle
\rightarrowtail \langle A_2A_1, A_2A_4\rangle$.
\begin{code}
> A := OctonionAlgebra(Rationals(), -1, -1, -1);
> t := Tensor(A);
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 8 over Rational Field
U1 : Full Vector space of degree 8 over Rational Field
U0 : Full Vector space of degree 8 over Rational Field
> H_gens := [A.i : i in [1..4]];
> t2 := Subtensor(t, [*H_gens, H_gens, H_gens*]);
> s := Subtensor(t, [* A.2, [A.1, A.4], A!0 *]);
> s;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Vector space of degree 8, dimension 1 over Rational Field
Generators:
(0 1 0 0 0 0 0 0)
Echelonized basis:
(0 1 0 0 0 0 0 0)
U1 : Vector space of degree 8, dimension 2 over Rational Field
Generators:
(1 0 0 0 0 0 0 0)
(0 0 0 1 0 0 0 0)
Echelonized basis:
(1 0 0 0 0 0 0 0)
(0 0 0 1 0 0 0 0)
U0 : Vector space of degree 8, dimension 2 over Rational Field
Generators:
(0 1 0 0 0 0 0 0)
(0 0 1 0 0 0 0 0)
Echelonized basis:
(0 1 0 0 0 0 0 0)
(0 0 1 0 0 0 0 0)
\end{code}

The quaternions are a subalgebra of $A$ generated by $\{A_1,A_2,A_3,A_4\}$.
Therefore, the $\{2\}$-local ideal of $s$ in $t$ must contain $A$ in the
codomain. However, the $\{2\}$-local ideal of $s$ in $t_2$ must only contain
$\langle A_1, A_2, A_3, A_4\}$ in the codomain.
\begin{code}
> s1 := LocalIdeal(t, s, {2});
> Codomain(s1);
Full Vector space of degree 8 over Rational Field
Generators:
(1 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 1 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 1 0)
(0 0 0 0 0 0 0 1)
> s2 := LocalIdeal(t2, s, {2});
> Codomain(s2);
Vector space of degree 8, dimension 4 over Rational Field
Generators:
(1 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 1 0 0 0 0)
Echelonized basis:
(1 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 1 0 0 0 0)
\end{code}
\end{example}

\index{Ideal}
\begin{intrinsics}
Ideal(t, S) : TenSpcElt, List -> TenSpcElt
Ideal(t, S) : TenSpcElt, SeqEnum -> TenSpcElt
\end{intrinsics}

Returns the ideal of $t$ containing $S$.

\index{Ideal}
\begin{intrinsics}
Ideal(t, D, C) : TenSpcElt, List, Any -> TenSpcElt
Ideal(t, D, C) : TenSpcElt, SeqEnum, Any -> TenSpcElt
\end{intrinsics}

Returns the ideal of $t$ containing $D$ in the domain and $C$ in the codomain.

\index{Ideal}
\begin{intrinsics}
Ideal(t, s) : TenSpcElt, TenSpcElt -> TenSpcElt
\end{intrinsics}

Returns the ideal of $t$ containing $s$ as a submap.

\index{IsIdeal}
\begin{intrinsics}
IsIdeal(t, s) : TenSpcElt, TenSpcElt -> BoolElt
\end{intrinsics}

Decides if $s$ is an ideal of $t$.

\begin{example}[Ideals]

First we will construct the tensor from the $\mathbb{Q}$-algebra, $\mathbb{Q}^5$.
\begin{code}
> T := KTensorSpace(Rationals(), [5,5,5]);
> A := VectorSpace(Rationals(), 5);
> t := T!0;
> for i in [1..5] do
for>   Assign(~t, [i,i,i], 1);
for> end for;
> t;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 5 over Rational Field
U1 : Full Vector space of degree 5 over Rational Field
U0 : Full Vector space of degree 5 over Rational Field
> SystemOfForms(t);
[
    [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 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 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 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 1]
]
\end{code}

Now we will construct the ideal tensor from the subtensor containing $\langle
A_1\rangle \times \langle A_2\rangle \rightarrowtail \langle A_3\rangle$. Note
that the $\{2\}$-local ideal must include $\langle A_2,A_3\rangle$ in the
codomain, and the $\{1\}$-local ideal must contain $\langle A_1,A_3\rangle$ in
the codomain.
\begin{code}
> s := Ideal(t, [A.1, A.2, A.3]);
> s;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Vector space of degree 5, dimension 1 over Rational Field
Generators:
(1 0 0 0 0)
Echelonized basis:
(1 0 0 0 0)
U1 : Vector space of degree 5, dimension 1 over Rational Field
Generators:
(0 1 0 0 0)
Echelonized basis:
(0 1 0 0 0)
U0 : Vector space of degree 5, dimension 3 over Rational Field
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)
\end{code}

Finally, we verify that the subtensor containing $\langle A_1\rangle \times
\langle A_2\rangle \rightarrowtail \langle A_2, A_3\rangle$ is not an ideal.
\begin{code}
> r := Subtensor(t, [A.1, A.2], [A.2, A.3]);
> IsIdeal(t, r);
false
\end{code}
\end{example}

\index{LocalQuotient}
\begin{intrinsics}
LocalQuotient(t, s, A : parameters) : TenSpcElt, TenSpcElt, {RngIntElt} -> TenSpcElt, Hmtp
    Check : BoolElt : true
\end{intrinsics}

Returns the local quotient of $t$ by $s$ at $A\subseteq\range{\vav}$. If you know $s$ is a local
ideal of $t$ at $A$, set {\tt Check} to {\tt false} to skip the verification.
A homotopism is also returned, mapping from $t$ to $t/s$.

\index{Quotient!tensor}\index{/!tensor}
\begin{intrinsics}
Quotient(t, s : parameters) : TenSpcElt, TenSpcElt -> TenSpcElt, Hmtp
    Check : BoolElt : true
t / s : TenSpcElt, TenSpcElt -> TenSpcElt, Hmtp
\end{intrinsics}

Returns the quotient of $t$ by $s$. If you know $s$ is an ideal of $t$,
set {\tt Check} to {\tt false} to skip the verification.
A homotopism is also returned, mapping from $t$ to $t/s$.

\begin{example}[Quotients]

We will demonstrate one of the most common uses of taking a quotient of tensors:
constructing the associated fully nondegenerate tensor. We first construct a
tensor with a nontrivial radical given by matrix multiplication:
$\mathbb{M}_{3\times 2}(\mathbb{Q})\times \mathbb{Q}^3\rightarrowtail
\mathbb{Q}^3$, where we take a projection of $\mathbb{Q}^3$ onto $\mathbb{Q}^2$
in the 1 coordinate.
\begin{code}
> K := Rationals();
> F := [*KMatrixSpace(K, 3, 2), VectorSpace(K, 3), VectorSpace(K, 3)*];
> mult := function(x)
function>   return Transpose(x[1]*Matrix(2, 1, Eltseq(x[2])[2..3]));
function> end function;
> t := Tensor(F, 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 3 over Rational Field
> s := Subtensor(t, [*[F[1].1, F[1].4], F[2], F[3]*]);
> s;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Vector space of degree 6, dimension 2 over Rational Field
Generators:
(1 0 0 0 0 0)
(0 0 0 1 0 0)
Echelonized basis:
(1 0 0 0 0 0)
(0 0 0 1 0 0)
U1 : Full Vector space of degree 3 over Rational Field
Generators:
(1 0 0)
(0 1 0)
(0 0 1)
U0 : Full Vector space of degree 3 over Rational Field
Generators:
(1 0 0)
(0 1 0)
(0 0 1)
> IsFullyNondegenerate(s);
false
\end{code}

Now we will construct the ideal $r$ that evaluates to 0 and the largest subspace
of $\mathbb{Q}^3$ not contained in the image.
\begin{code}
> r := Ideal(t, [*F[1]!0, F[2].1, F[3].3*]);
> r;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Vector space of degree 6, dimension 0 over Rational Field
Generators:

U1 : Vector space of degree 3, dimension 1 over Rational Field
Generators:
(1 0 0)
Echelonized basis:
(1 0 0)
U0 : Vector space of degree 3, dimension 1 over Rational Field
Generators:
(0 0 1)
Echelonized basis:
(0 0 1)
> IsIdeal(t, r);
true
\end{code}

Finally, we quotient $s$ by $r$ to obtain a fully nondegenerate tensor.
\begin{code}
> q := s/r;
> q;
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 2 over Rational Field
> IsFullyNondegenerate(q);
true
\end{code}
\end{example}

\subsection{Categorical operations on tensor spaces}

We have categorical notions for tensor spaces as well, and these are inherited
from the module structure on tensor spaces.

\index{SubConstructor!tensor space}\index{sub!tensor space}
\begin{intrinsics}
SubConstructor(T, L) : TenSpc, Any -> TenSpc, Map
sub< T | L > : TenSpc, Any -> TenSpc, Map
\end{intrinsics}

Returns the subtensor space of $T$ generated by the tensors in the sequence $L$.

\index{IsSubtensorSpace}
\begin{intrinsics}
IsSubtensorSpace(T, S) : TenSpc, TenSpc -> BoolElt
\end{intrinsics}

Decides if the tensor space $S$ is a subtensor space of $T$.

\begin{example}[SubtensorSpaces]

We will construct the subspace $S$ of symmetric forms from the tensor space $T$
with frame $\mathbb{Q}^2\times\mathbb{Q}^2\rightarrowtail \mathbb{Q}$.
\begin{code}
> K := Rationals();
> T := KTensorSpace(K, [2,2,1]);
> T;
Tensor space of dimension 4 over Rational Field with valence 3
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
> S := sub< T | T.1, T.2+T.3, T.4 >;
> S;
Tensor space of dimension 3 over Rational Field with valence 3
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
> IsSymmetric(S);
true
\end{code}

Now we will construct the subspace $A$ of alternating forms from $T$.
\begin{code}
> A := sub< T | T.2-T.3 >;
> A;
Tensor space of dimension 1 over Rational Field with valence 3
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
> IsAlternating(A);
true
\end{code}

Now we verify that $A$ is not a subtensor space of $S$, and thus, we have
constructed a direct decomposition of $T$ into its symmetric and alternating
space.
\begin{code}
> IsSubtensorSpace(S, A);
false
\end{code}
\end{example}

\index{QuoConstructor!tensor space}\index{quo!tensor space}\index{/!tensor space}
\begin{intrinsics}
QuoConstructor(T, X) : TenSpc, Any -> TenSpc, Map
quo< T | X > : TenSpc, Any -> TenSpc, Map
T / S : TenSpc, TenSpc -> TenSpc, Map
\end{intrinsics}

Returns the quotient tensor space of $T$ by $S$.

\begin{example}[QuotientTensorSpaces]

We pick up with the same tensor spaces as the previous example: $T$ has frame
$\mathbb{Q}^2\times\mathbb{Q}^2\rightarrowtail \mathbb{Q}$, $S$ is the symmetric
subspace, and $A$ is the alternating subspace.
\begin{code}
> K := Rationals();
> T := KTensorSpace(K, [2,2,1]);
> T;
Tensor space of dimension 4 over Rational Field with valence 3
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
> S := sub< T | T.1, T.2+T.3, T.4 >;
> A := sub< T | T.2-T.3 >;
\end{code}

Now we construct the quotient of $T$ by $A$. The result is not a symmetric
tensor space. Note that $Q_2$ is equivalent to a symmetric tensor modulo $A$,
but this choice is arbitrary.
\begin{code}
> Q := T/A;
> Q;
Tensor space of dimension 3 over Rational Field with valence 3
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(Q.1);
[
    [1 0]
    [0 0]
]
> SystemOfForms(Q.2);
[
    [0 0]
    [1 0]
]
> SystemOfForms(Q.3);
[
    [0 0]
    [0 1]
]
\end{code}
\end{example}

\section{Homotopisms}

Magma provides functions for homotopisms, i.e.\ morphisms of tensors,
see definition in \cite{FMW:densors}*{Sections~5.7 \& 7}.
Homotopisms are also equipped with a tensor category. Because homotopisms can
contain multiple maps between modules, it is not really clear what is meant by
the domain or codomain of a given homotopism. In this context, the \emph{domain}
of a homotopism $H$ will refer to the tensor, $\bra{t}:U_{\vav}\times \cdots \times
U_1\rightarrowtail U_0$, where an arrow equal to $1$ at coordinate $a$ will mean
that the corresponding map at coordinate $a$ has domain equal to $U_a$. And in
the same vain, the tensor $\bra{s}:V_{\vav} \times\cdots \times V_1\rightarrowtail
V_0$ is the \emph{codomain} of $H$ if an arrow equal to $1$ at coordinate $a$
implies that the corresponding map at coordinate $a$ has codomain equal to
$V_a$.

\subsection{Constructions of Homotopisms}~

\index{Homotopism}
\begin{intrinsics}
Homotopism(t, s, M : parameters) : TenSpcElt, TenSpcElt, List -> Hmtp
    Check : BoolElt : true
Homotopism(t, s, M : parameters) : TenSpcElt, TenSpcElt, SeqEnum -> Hmtp
    Check : BoolElt : true
Homotopism(t, s, M, C : parameters) : TenSpcElt, TenSpcElt, List, TenCat -> Hmtp
    Check : BoolElt : true
Homotopism(t, s, M, C : parameters) : TenSpcElt, TenSpcElt, SeqEnum, TenCat -> Hmtp
    Check : BoolElt : true
\end{intrinsics}

Returns the homotopism from $t$ to $s$ given by the list of maps $M$ and the category $C$.
The default tensor category is the same as tensor categories for $t$ and $s$.
If the maps $M$ will produce a homotopism, then set \texttt{Check} to \texttt{false} to skip the verification.

\index{Homotopism}
\begin{intrinsics}
Homotopism(M, C) : List, TenCat -> Hmtp
Homotopism(M, C) : SeqEnum, TenCat -> Hmtp
\end{intrinsics}

Returns the homotopism given by the maps in $M$ with tensor category $C$.

\index{IsHomotopism}
\begin{intrinsics}
IsHomotopism(t, s, H) : TenSpcElt, TenSpcElt, Hmtp -> BoolElt
IsHomotopism(t, s, M) : TenSpcElt, TenSpcElt, List -> BoolElt
IsHomotopism(t, s, M) : TenSpcElt, TenSpcElt, SeqEnum -> BoolElt
IsHomotopism(t, s, M, C) : TenSpcElt, TenSpcElt, List, TenCat -> BoolElt
IsHomotopism(t, s, M, C) : TenSpcElt, TenSpcElt, SeqEnum, TenCat -> BoolElt
\end{intrinsics}

Decides if the list of maps $M$ induces a homotopism from $t$ to $s$ in the tensor category $C$.
The default tensor category is the homotopism category.
If it does induce a homotopism, it is also returned.

\begin{example}[HomotopismConst]

We will construct two symmetric tensors
$t,s:\mathbb{F}_3^3\times\mathbb{F}_3^3\rightarrowtail\mathbb{F}_3^3$ and apply
permutations to the bases.
\begin{code}
> T := KTensorSpace(GF(3), [3,3,3]);
> t := T.1+T.14+T.27;
> SystemOfForms(t);
[
    [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]
]
> s := (T.4+T.10)+(T.8+T.20)+(T.18+T.24);
> SystemOfForms(s);
[
    [0 1 0]
    [1 0 0]
    [0 0 0],

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

    [0 0 0]
    [0 0 1]
    [0 1 0]
]
\end{code}

Now we construct a homotopism from $t$ to $t$ given by apply a permutation matrix in every coordinate.
\begin{code}
> P := PermutationMatrix(GF(3), [2,1,3]);
> H := Homotopism(t, t, [*P, P, P*]);
> H;
Maps from U2 x U1 >-> U0 to V2 x V1 >-> V0.
U2 -> V2:
[0 1 0]
[1 0 0]
[0 0 1]
U1 -> V1:
[0 1 0]
[1 0 0]
[0 0 1]
U0 -> V0:
[0 1 0]
[1 0 0]
[0 0 1]
\end{code}

Note that this permutation matrix does not induce a homotopism of $s$.
\begin{code}
> IsHomotopism(s, s, [*P, P, P*]);
false
\end{code}
\end{example}

\begin{example}[MixedHomotopisms] Homotopisms can take mixed categories of maps.
To reuse the above example, we can encode the permutation as a \texttt{Map} and
construct homotopisms from these types.
\begin{code}
> V := VectorSpace(GF(3), 3);
> T := TensorSpace([V, V, V]);
> t := T.1+T.14+T.27;
> P := PermutationMatrix(GF(3), [2,1,3]);
> f := hom< V -> V | [<V.1, V.2>, <V.2, V.1>, <V.3, V.3>] >;
> H := Homotopism(t, t, [*f, f, f*]);
> H;
Maps from U2 x U1 >-> U0 to V2 x V1 >-> V0.
U2 -> V2: Mapping from: Full Vector space of degree 3 over GF(3) to Full
Vector space of degree 3 over GF(3)
U1 -> V1: Mapping from: Full Vector space of degree 3 over GF(3) to Full
Vector space of degree 3 over GF(3)
U0 -> V0: Mapping from: Full Vector space of degree 3 over GF(3) to Full
Vector space of degree 3 over GF(3)
\end{code}

Furthermore, we can input lists with types \texttt{Mtrx} and \texttt{Map} included.
\begin{code}
> H2 := Homotopism(t, t, [*P, f, P*]);
> H2;
Maps from U2 x U1 >-> U0 to V2 x V1 >-> V0.
U2 -> V2:
[0 1 0]
[1 0 0]
[0 0 1]
U1 -> V1: Mapping from: Full Vector space of degree 3 over GF(3) to Full
Vector space of degree 3 over GF(3)
U0 -> V0:
[0 1 0]
[1 0 0]
[0 0 1]
\end{code}
\end{example}

\subsection{Basic Operations with Homotopisms}

We provide some operations for homotopisms.

\index{$*$!homotopism}
\begin{intrinsics}
H1 * H2 : Hmtp, Hmtp -> Hmtp
\end{intrinsics}

Returns the composition of the homotopisms $H_1$ and $H_2$.

\index{.!homotopisms}
\begin{intrinsics}
H.a : Hmtp, RngIntElt -> Map
\end{intrinsics}

Returns the map on the $a$th coordinate.

\begin{example}[HomotopismOps]

We construct a nondegenerate alternating form $t$ on $V=\mathbb{Q}^6$.
The group of isometries are isomorphic to $\Sp(6, \mathbb{Q})$, the group generated by all transvections.
We construct a transvection $L$ and a corresponding matrix.
\begin{code}
> V := VectorSpace(Rationals(), 6);
> T := KTensorSpace(Rationals(), [6, 6, 1]);
> t := T.2-T.7+T.16-T.21+T.30-T.35;
> 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 6 over Rational Field
U0 : Full Vector space of degree 1 over Rational Field
>
> u := V.2+2*V.3-V.5;
> L := map< V -> V | x :-> x + (x*t*u)[1]*u >;
> L;
Mapping from: ModTupFld: V to ModTupFld: V given by a rule [no inverse]
> M := Matrix(6, 6, [V.i @ L : i in [1..6]]);
> M;
[ 1  1  2  0 -1  0]
[ 0  1  0  0  0  0]
[ 0  0  1  0  0  0]
[ 0 -2 -4  1  2  0]
[ 0  0  0  0  1  0]
[ 0  1  2  0 -1  1]
\end{code}

We construct a homotopism from the transvection.
\begin{code}
> H := Homotopism(t, t, [*L, L, IdentityMatrix(Rationals(), 1)*]);
> H;
Maps from U2 x U1 >-> U0 to V2 x V1 >-> V0.
U2 -> V2: Mapping from: Full Vector space of degree 6 over Rational Field to
Full Vector space of degree 6 over Rational Field given by a rule [no inverse]
U1 -> V1: Mapping from: Full Vector space of degree 6 over Rational Field to
Full Vector space of degree 6 over Rational Field given by a rule [no inverse]
U0 -> V0:
[1]
\end{code}

Since $H$ is an isometry of $t$, $H^2$ is also an isometry of $t$.
We verify that the 2-coordinate map of $H^2$ is exactly $M^2$.
\begin{code}
> H2 := H*H;
> H2;
Maps from U2 x U1 >-> U0 to V2 x V1 >-> V0.
U2 -> V2: Mapping from: Full Vector space of degree 6 over Rational Field to
Full Vector space of degree 6 over Rational Field
Composition of Mapping from: Full Vector space of degree 6 over Rational Field
to Full Vector space of degree 6 over Rational Field given by a rule [no
inverse] and
Mapping from: Full Vector space of degree 6 over Rational Field to Full Vector
space of degree 6 over Rational Field given by a rule [no inverse]
U1 -> V1: Mapping from: Full Vector space of degree 6 over Rational Field to
Full Vector space of degree 6 over Rational Field
Composition of Mapping from: Full Vector space of degree 6 over Rational Field
to Full Vector space of degree 6 over Rational Field given by a rule [no
inverse] and
Mapping from: Full Vector space of degree 6 over Rational Field to Full Vector
space of degree 6 over Rational Field given by a rule [no inverse]
U0 -> V0:
[1]
> M2 := Matrix(6, 6, [V.i @ H2.2 : i in [1..6]]);
> M2;
[ 1  2  4  0 -2  0]
[ 0  1  0  0  0  0]
[ 0  0  1  0  0  0]
[ 0 -4 -8  1  4  0]
[ 0  0  0  0  1  0]
[ 0  2  4  0 -2  1]
> M^2 eq M2;
true
\end{code}
\end{example}

\index{Precompose}
\begin{intrinsics}
Precompose(t, f, a) : TenSpcElt, Map, RngIntElt -> TenSpcElt
Precompose(t, M, a) : TenSpcElt, Mtrx, RngIntElt -> TenSpcElt
\end{intrinsics}

If $a>0$, then the tensor returned is the tensor that has been pre-composed by the map $f$ or matrix $M$.

\index{AT!homotopism}
\begin{intrinsics}
t @ H : TenSpcElt, Hmtp -> TenSpcElt
\end{intrinsics}

If $H$ is a cohomotopism (a homotopism in the cohomotopism category), then
either the domain or codomain of $H$ is returned, depending on the orientation
of the arrows of $H$.

\subsection{Basic Properties of Homotopisms}~

\index{Domain!homotopism}
\begin{intrinsics}
Domain(H) : Hmtp -> TenSpcElt
\end{intrinsics}

Returns the domain tensor of $H$.

\index{Codomain!homotopism}
\begin{intrinsics}
Codomain(H) : Hmtp -> TenSpcElt
\end{intrinsics}

Returns the codomain tensor of $H$.

\index{Maps}
\begin{intrinsics}
Maps(H) : Hmtp -> List
\end{intrinsics}

Returns the list of maps for the various modules in the domain and codomain
tensors.

\index{TensorCategory!homotopism}
\begin{intrinsics}
TensorCategory(H) : Hmtp -> TenCat
\end{intrinsics}

Returns the tensor category of $H$.

\index{ChangeTensorCategory!homotopism}
\begin{intrinsics}
ChangeTensorCategory(H, C) : Hmtp, TenCat -> Hmtp
ChangeTensorCategory(~H, C) : Hmtp, TenCat ->
\end{intrinsics}

Changes the tensor category of $H$ to the given category.

\index{Valence!homotopism}
\begin{intrinsics}
Valence(H) : Hmtp -> RngIntElt
\end{intrinsics}

Returns the valence of the underlying tensor category of the homotopism $H$.

\index{Kernel}
\begin{intrinsics}
Kernel(H) : Hmtp -> TenSpcElt, List
\end{intrinsics}

Returns the kernel of $H$ as an ideal of its domain tensor.

\index{Image!homotopism}
\begin{intrinsics}
Image(H) : Hmtp -> TenSpcElt, List
\end{intrinsics}

Returns the image of $H$ as a submap of the codomain tensor.

\begin{example}[HomotopismProps]

We demonstrate how to access properties of a homotopism. We construct tensors
$\bra{t}:\mathbb{Q}^4\times\mathbb{Q}^4\rightarrowtail \mathbb{Q}$ and
$\bra{s}:\mathbb{Q}^6\times\mathbb{Q}^6\rightarrowtail\mathbb{Q}$ given by the dot
product.
\begin{code}
> t := Tensor(IdentityMatrix(Rationals(), 4), 2, 1);
> s := Tensor(IdentityMatrix(Rationals(), 6), 2, 1);
> Z := ZeroMatrix(Rationals(), 4, 6);
> M := InsertBlock(Z, IdentityMatrix(Rationals(), 4), 1, 1);
> H := Homotopism(t, s, [*M, M, IdentityMatrix(Rationals(), 1)*]);
> H;
Maps from U2 x U1 >-> U0 to V2 x V1 >-> V0.
U2 -> V2:
[1 0 0 0 0 0]
[0 1 0 0 0 0]
[0 0 1 0 0 0]
[0 0 0 1 0 0]
U1 -> V1:
[1 0 0 0 0 0]
[0 1 0 0 0 0]
[0 0 1 0 0 0]
[0 0 0 1 0 0]
U0 -> V0:
[1]
\end{code}

Like with maps, we can obtain standard properties of homotopisms.
\begin{code}
> Domain(H);
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
> Codomain(H);
Tensor of valence 3, U2 x U1 >-> U0
U2 : Full Vector space of degree 6 over Rational Field
U1 : Full Vector space of degree 6 over Rational Field
U0 : Full Vector space of degree 1 over Rational Field
> Maps(H);
[*
    [1 0 0 0 0 0]
    [0 1 0 0 0 0]
    [0 0 1 0 0 0]
    [0 0 0 1 0 0],

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

    [1]
*]
> TensorCategory(H);
Tensor category of valence 3 (->,->,->) ({ 1 },{ 2 },{ 0 })
\end{code}

When the image and kernel can be computed for the each of the maps in the
homotopism, then the image and kernel can be computed for the homotopism.
\begin{code}
> Im := Image(H);
> Im;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Vector space of degree 6, dimension 4 over Rational Field
Echelonized basis:
(1 0 0 0 0 0)
(0 1 0 0 0 0)
(0 0 1 0 0 0)
(0 0 0 1 0 0)
U1 : Vector space of degree 6, dimension 4 over Rational Field
Echelonized basis:
(1 0 0 0 0 0)
(0 1 0 0 0 0)
(0 0 1 0 0 0)
(0 0 0 1 0 0)
U0 : Full Vector space of degree 1 over Rational Field
> Ker := Kernel(H);
> Ker;
Tensor of valence 3, U2 x U1 >-> U0
U2 : Vector space of degree 4, dimension 0 over Rational Field
U1 : Vector space of degree 4, dimension 0 over Rational Field
U0 : Vector space of degree 1, dimension 0 over Rational Field
\end{code}
\end{example}

\index{Shuffle!homotopism}
\begin{intrinsics}
Shuffle(H, g) : Hmtp, GrpPermElt -> Hmtp
Shuffle(H, g) : Hmtp, [RngIntElt] -> Hmtp
\end{intrinsics}

Just like the shuffle for tensors, this returns the shuffle of the homotopism $H$.
This is a functor from one tensor category to another and changes the order of the maps to
\[ \{H_{\vav^g},\dots, H_{1^g}, H_{0^g}\}. \]
In order to be defined, $g\in\text{Sym}(\{0,\dots,\vav \})$.
If $0^g\ne 0$, then both the image and pre-image of $0$ under $g$ will be replaced by their $K$-dual space.
For cotensors, $g\in\text{Sym}(\{1,\dots,\vav\})$.
Sequences $[a_1,\dots,a_{\vav+1}]$ will be interpreted as
\[ \begin{array}{cccc} 0 & 1 & \cdots & \vav \\ \downarrow & \downarrow & & \downarrow \\ a_1 & a_2 & \cdots & a_{\vav+1}. \end{array}\]


\chapter{Parametric Inference}

\begin{ex}
  Recall that if $X\sim\text{Gamma}(\alpha,\beta)$, then by Exercise 3.12,
  \[
    \E{X}=\alpha\beta,\quad
    \E{X^2} =\alpha(\alpha+1)\beta^2
    =(\alpha\beta)^2+(\alpha\beta)\beta.
  \]
  Recall that $\alphahat_1=\frac{1}{n}\sum_{i=1}^n X_i$ and
  $\alphahat_2=\frac{1}{n}\sum_{i=1}^n X_i^2$. Then,
  \[
    \begin{cases}
      \alphahat_1 = \alphahat\betahat \\
      s = \alphahat_1^2+\alphahat_1\betahat
    \end{cases} \implies
    \begin{cases}
      \alphahat_1 = \alphahat\betahat \\
      \betahat = (\alphahat_2 - \alphahat_1^2)/\alphahat_1
    \end{cases} \implies
    \begin{cases}
      \alphahat = \alphahat_1^2/(\alphahat_2-\alphahat_1^2) \\
      \betahat = (\alphahat_2-\alphahat_1^2)/\alphahat_1
    \end{cases}.
  \]
\end{ex}

\begin{ex}~
  \begin{enumerate}[(a)]
    \item Recall that if $X\sim\text{Uniform}(a, b)$,
          \[
            \E{X}=(a+b)/2,\text{ and } \E{X^2}=\var{X}+\E{X}^2=(a^2+ab+b^2)/3.
          \]
          Then,
          \begin{align*}
            \begin{cases}
              \alphahat_1 = (\ahat + \bhat)/2                 \\
              \alphahat_2 = (\ahat^2 + \ahat\bhat +\bhat^2)/3 \\
            \end{cases}\implies
            \begin{cases}
              2\alphahat_1 - \ahat = \bhat              \\
              4\alphahat_1^2 -3\alphahat_2 = \ahat\bhat \\
            \end{cases}\implies
            \begin{cases}
              2\alphahat_1 - \ahat = \bhat                            \\
              \ahat^2-2\alphahat_1\ahat+4\alphahat_1^2-3\alphahat_2=0 \\
            \end{cases},
          \end{align*}
          or solving the quadratic equation,
          \[
            \ahat=\alphahat_1\pm \sqrt{3}\sqrt{\alphahat_2-\alphahat_1^2}.
          \]
          Note that then $\bhat$ is the other solution to the quadratic
          equation, and, since $b\geq a$, we have
          \[
            \ahat=\alphahat_1- \sqrt{3}\sqrt{\alphahat_2-\alphahat_1^2},
            \quad
            \bhat=\alphahat_1+ \sqrt{3}\sqrt{\alphahat_2-\alphahat_1^2}.
          \]
    \item Let $\theta=(a,b)$. Note that then
          \[
            \L_n(\theta)=\prod_{i=1}^n \frac{I_{[a, b]}(x_i)}{b-a}
            =\begin{cases}
              (b-a)^{-n} & \text{$x_i\in [a, b]$ for all $i$}, \\
              0          & \text{otherwise}.
            \end{cases}
          \]
          Thus, to maximize $\L_n(\theta)$, we must have $a\leq X_{(1)}$ and
          $b\geq X_{(n)}$. Moreover, note that $\L_n(\theta)$ increases as $b$
          increases, and decreases as $a$ increases. Therefore,
          $\ahat= X_{(1)}$ and $\bhat= X_{(n)}$.
    \item Let $\theta=(a, b)$. Note that then
          $\tau(\theta)=\int\!x\,\d{F}(x)=\E{X}=(a+b)/2$. However, by the
          equivariance of the maximum likelihood estimator, $\tauhat
            =g(\thetahat)=(X_{(1)}+X_{(n)})/2$.
    \item Recall that the plug-in estimator of the mean is given by the sample
          average and that, by Example 7.10,
          \[
            \E{\widetilde{\tau}}   = (a + b) / 2,\quad
            \var{\widetilde{\tau}} = \frac{\sigma^2_X}{n}
            =\frac{1}{n}\frac{(b-a)^2}{12}.
          \]
          Hence,
          \[
            \mse{\tauhat}
            =\bias{\tauhat}^2
            +\var{\tauhat}
            =\frac{1}{n}\frac{(b-a)^2}{12}.
          \]
          \inputminted{python}{../code/09-02.py}
          \inputminted{text}{../output/09-02.txt}
  \end{enumerate}
\end{ex}

\begin{ex}~
  \begin{enumerate}[(a)]
    \item Let $X\sim N(\mu,\sigma^2)$. Then
          \[
            0.95
            =\P{X<\tau}
            =\P{\frac{X-\mu}{\sigma}<\frac{\tau-\mu}{\sigma}}
            =\Phi\left(\frac{\tau-\mu}{\sigma} \right),
          \]
          or,
          \[
            \tau=\Phi^{-1}(0.95)\sigma+\mu.
          \]

          Recall that by Example 9.11, the maximum likelihood estimators for $X$
          are
          \[
            \muhat = \Xbar,\text{ and }
            \sigmahat = S,
          \]
          and that therefore by the equivariance of the MLE,
          \[
            \widehat{\tau}=1.645\cdot S+\Xbar.
          \]
    \item We will use the delta method. Note that by Exercise 9.8,
          \[
            I_n(\mu,\sigma)
            =\begin{pmatrix}
              \frac{n}{\sigma^2} & 0                   \\
              0                  & \frac{2n}{\sigma^2}
            \end{pmatrix},
          \]
          and that therefore
          \[
            J_n=I^{-1}_n(\mu,\sigma)
            =\frac{1}{n}\begin{pmatrix}
              \sigma^2 & 0                  \\
              0        & \frac{\sigma^2}{2}
            \end{pmatrix}.
          \]
          Let $g(\mu,\sigma)=1.645 \sigma+\mu$. Note that
          $\nabla g=(1, 1.645)$, and that therefore
          \begin{align*}
            \widehat{\textsf{se}}(\widehat{\tau})
             & =\sqrt{\begin{pmatrix}
                1 & 1.645 \\
              \end{pmatrix}
              \begin{pmatrix}
                \sigmahat^2 & 0                     \\
                0           & \frac{\sigmahat^2}{2}
              \end{pmatrix}
              \begin{pmatrix}
                1 \\ 1.645
              \end{pmatrix}}
            =\frac{1.534\sigmahat}{\sqrt{n}}.
          \end{align*}

          Therefore,
          \[
            C_n=\left(
            1.645\cdot S+\Xbar-z_{\alpha/2}\frac{1.534 S}{\sqrt{n}},
            1.645\cdot S+\Xbar+z_{\alpha/2}\frac{1.534 S}{\sqrt{n}}
            \right).
          \]
    \item~
          \inputminted{python}{../code/09-03.py}
          \inputminted{text}{../output/09-03.txt}
  \end{enumerate}
\end{ex}

\begin{ex}
  Let $X_1,\ldots,X_n\sim\text{Uniform}(0,\theta)$. Recall that the maximum
  likelihood estimator for $\theta$ is given by the maximum of the examples, and
  that therefore, for $0<\epsilon<\theta$,
  \begin{align*}
    \P{\left|\widehat{\theta}_n-\theta\right|>\epsilon}
     & =\P{\widehat{\theta}_n < \theta-\epsilon}                 \\
     & =\P{X_1 < \theta-\epsilon}\cdots\P{X_n < \theta-\epsilon} \\
     & =\left(\frac{\theta-\epsilon}{\theta}\right)^n            \\
     & =\left(1-\frac{\epsilon}{\theta}\right)^n
  \end{align*}
  which goes to $0$ as $n$ goes to infinity. Hence,
  $\widehat{\theta}_n\xrightarrow{P} \theta$, and therefore the maximum
  likelihood estimator is consistent.
\end{ex}

% 5
\begin{ex}
  Let $X\sim\text{Poisson}(\lambda)$. Recall that then
  \[
    f_X(x)=\frac{\lambda^x e^{-\lambda}}{x!},
  \]
  and that
  \[
    \E{X}
    =\sum_{x=0}^\infty x\frac{\lambda^x e^{-\lambda}}{x!}
    =\lambda\sum_{x=1}^\infty \frac{\lambda^{x-1} e^{-\lambda}}{(x-1)!}
    =\lambda.
  \]
  Hence, the method of moments estimator for $\lambda$ is given by $\Xbar$.

  Note that
  \[
    \ell(\lambda)
    =\log\left(\frac{\lambda^X e^{-\lambda}}{X!}\right)
    =X\log{\lambda}-\lambda-\log{X!},
  \]
  and that therefore
  \[
    \frac{\pd}{\pd\lambda}\ell(\lambda)
    =X/\lambda-1.
  \]
  Hence,
  \[
    0=\ell_n(\lambda)=\sum_{i=1}^n(X_i/\lambda -1)
  \]
  implies that
  \[
    n=(n/\lambda)\Xbar
  \]
  or
  \[
    \lambda=\Xbar.
  \]
  This is a maximum since the second derivative is negative. Hence,
  $\widehat{\lambda}=\Xbar$.

  Finally, note that
  \[
    I(\lambda)=-\E{\frac{\pd^2}{\pd\lambda^2}\ell(\lambda)}
    =-\E{-X/\lambda^2}=\lambda^{-1}.
  \]
\end{ex}

\begin{ex}~
  \begin{enumerate}[(a)]
    \item We have
          \[
            \psi=\P{Y_1=1}=\P{X_1>0}=\P{X_1-\theta>-\theta}=1-\Phi(-\theta)
            =\Phi(\theta).
          \]
          Recall that the maximum likelihood estimator for $\theta$ is
          $\overline{X}=\frac{1}{n}\sum_{i=1}^nX_i$. Therefore, by the
          equivariance of the maximum likelihood, it follows that
          $\widehat{\psi}=\Phi(\overline{X})$.
    \item We will use the delta method. Note that
          $\psi=g(\theta)=\Phi(\theta)$, and that therefore
          $g'(\theta)=\phi(\theta)$. By Exercise 9.8, $I_n(\theta)=n$, and
          thus $\widehat{\textsf{se}}(\widehat{\theta})=\sqrt{1/n}$. Hence,
          \[
            \widehat{\textsf{se}}(\widehat{\psi})=\phi(\overline{X})/\sqrt{n}.
          \]
          Therefore, a $95\%$ confidence interval for $\psi$ is
          \[
            C_n=\left(
            \Phi(\overline{X})-z_{0.05/2}\phi(\overline{X})/\sqrt{n},
            \Phi(\overline{X})+z_{0.05/2}\phi(\overline{X})/\sqrt{n}
            \right).
          \]
    \item Since $\E{Y_i}=\P{Y_i=1}=\P{Y_1=1}=\psi$, and $\psihat$ is an
          average of $Y_i$'s, the result follows by the law of large numbers.
    \item We have
          \[
            \var{\psihat}
            =\var{\frac{1}{n}\sum_{i=1}^n Y_i}
            =\frac{1}{n^2}\sum_{i=1}^n \var{Y_i}
            =\frac{\Phi(\theta)(1-\Phi(\theta))}{n}.
          \]
          Thus,
          \[
            \textsc{are}(\widehat{\psi},\widetilde{\psi})
            =
            \frac{\var{\widetilde{\psi}}}{\var{\widehat{\psi}}}
            =\frac{\Phi(\theta)(1-\Phi(\theta))}{\phi^2(\theta)}.
          \]
    \item We have that $\E{\overline{X}}=\E{X_i}=\mu_X$, and therefore
          $\widehat{\psi}$ still converges to $\Phi(\mu_X)$ by
          the law of large numbers. However, $\psi=\P{Y_1=1}=
            \P{X_i>0}=1-F_X(0)$, where
          $\Phi(\mu_X)\neq 1-F_X(0)$ for an arbitrary $F_X$.
  \end{enumerate}
\end{ex}

\begin{ex}~
  \begin{enumerate}[(a)]
    \item Let $X\sim\text{Binomial(n, p)}$. Note that then
          \[
            f_{X}(x)=\binom{n}{x}p^x(1-p)^{n-x}
          \]
          and that therefore
          \[
            \ell_X(p)=\log\left[\binom{n}{X}\right]+X\log{p}+(n-X)\log(1-p),
          \]
          and
          \[
            \frac{\pd}{\pd p}\ell(p)=X/p-(n-X)/(1-p).
          \]
          Setting $\frac{\pd}{\pd p}\ell(p)$ equal to $0$ and solving for $p$,
          we get that $\widehat{p}=X/n$ is the maximum likelihood estimator
          for a Binomial distribution.

          Next, let $X_1\sim\text{Binomial}(n_1, p_1)$ and
          $X_2\sim\text{Binomial}(n_1, p_1)$ as in the problem. Since $X_1$ and
          $X_2$ are independent, it follows that the maximum likelihood
          estimator for $(p_1,p_2)$ is $(X_1/n_1, X_2/n_2$. Hence, by the
          equivariance of the maximum likelihood estimator, since
          $\psi=g(p_1,p_2)=p_1-p_2$, $\widehat{\psi}=X_1/n_1-X_2/n_2$.
    \item The density for the joint distribution is
          \[
            f_{X_1,X_2}(x_1,x_2)=
            \left[\binom{n_1}{x_1}p_1^{x_1}(1-p_1)^{n_1-x_1}\right]
            \left[\binom{n_2}{x_2}p_2^{x_2}(1-p_2)^{n_2-x_2}\right],
          \]
          and therefore
          \begin{align*}
            \ell_{X_1,X_2}(p_1,p_2)
             & =\log\left[\binom{n_1}{X_1}\right]+X_1\log{p_1}+(n_1-X_1)\log(1-p_1)       \\
             & \quad+\log\left[\binom{n_2}{X_2}\right]+X_2\log{p_2}+(n_2-X_2)\log(1-p_2).
          \end{align*}
          Hence,
          \begin{align*}
            H_{11}
            =\frac{\pd^2 \ell_{X_1,X_2}}{\pd p_1^2}
            =-\frac{X_1}{p_1^2}-\frac{n_1-X_1}{(1-p_1)^2},
          \end{align*}
          and
          \begin{align*}
            -\E{H_{11}}
            =\frac{np_1}{p_1^2}+\frac{n_1-n_1p_1}{(1-p_1)^2}
            =\frac{n_1}{p_1}+\frac{n_1}{1-p_1}
            =\frac{n_1}{p_1(1-p_1)}.
          \end{align*}
          By symmetry, we also have
          \[
            -\E{H_{22}}
            =\frac{n_2}{p_2(1-p_2)},
          \]
          and by independence, it follows that
          \[
            H_{12}=H_{21}=0.
          \]

          Therefore,
          \begin{align*}
            I(p_1, p_2)
             & =\begin{pmatrix}
              \frac{n_1}{p_1(1-p_1)} & 0                      \\
              0                      & \frac{n_2}{p_2(1-p_2)}
            \end{pmatrix}.
          \end{align*}
    \item Recall that $\psi=g(p_1,p_2)=p_1-p_2$, and therefore
          $\nabla g=(1,-1)$. Hence, by the multiparameter delta method
          \[
            \widehat{\textsf{se}}(\widehat{\psi})
            =\sqrt{
              \begin{pmatrix}
                1 & -1
              \end{pmatrix}
              \begin{pmatrix}
                \frac{p_1(1-p_1)}{n_1} & 0                      \\
                0                      & \frac{p_2(1-p_2)}{n_2}
              \end{pmatrix}
              \begin{pmatrix}
                1 \\ -1
              \end{pmatrix}
            }
            =\sqrt{\frac{p_1(1-p_1)}{n_1} + \frac{p_2(1-p_2)}{n_2}}.
          \]
    \item
          \inputminted{python}{../code/09-07.py}
          \inputminted{text}{../output/09-07.txt}
  \end{enumerate}
\end{ex}

\begin{ex}
  Let $X\sim N(\mu,\sigma^2)$. Let $\theta=(\mu,\sigma)$. Note that then
  \[
    \ell(\theta)
    =-\frac{1}{2}\frac{(x-\mu)^2}{\sigma^2}+\log{\frac{1}{\sigma\sqrt{2\pi}}},
  \]
  and, therefore
  \[
    H_{11}
    =\frac{\pd^2\ell_n}{\pd\mu^2}
    =-\frac{n}{\sigma^2},\quad
    \E{H_{11}} =-\frac{n}{\sigma^2},
  \]
  \[
    H_{22}
    =\frac{\pd^2\ell_n}{\pd\sigma^2}
    =\frac{n}{\sigma^2}-\frac{3n(x-\mu)^2}{\sigma^4},\quad
    \E{H_{22}}=\frac{n}{\sigma^2}-\frac{3n\E{(x-\mu)^2}}{\sigma^4}
    =-\frac{2n}{\sigma^2},
  \]
  \[
    H_{12}
    =\frac{\pd^2\ell_n}{\pd\mu\pd\sigma}
    =\frac{\pd}{\pd\mu}\left[\frac{n(x-\mu)^2-n\sigma^2}{\sigma^2}\right]
    =-\frac{2n(x-\mu)}{\sigma^3},\quad
    \E{H_{12}} = 0,
  \]
  \[
    H_{21}
    =\frac{\pd^2\ell_n}{\pd\sigma\pd\mu}
    =\frac{\pd}{\pd\sigma}\left[-\frac{n(x-\mu)}{\sigma^2}\right]
    =-\frac{2n(x-\mu)}{\sigma^3},\quad
    \E{H_{21}} = 0.
  \]

  Hence,
  \[
    I_n(\mu,\sigma)
    =\begin{pmatrix}
      \frac{n}{\sigma^2} & 0                   \\
      0                  & \frac{2n}{\sigma^2}
    \end{pmatrix}.
  \]
\end{ex}

\begin{ex}~
  \begin{enumerate}[(a)]
    \item Recall that for $X_1,\ldots,X_n\sim N(0,\sigma^2)$,
          $I_n(\mu)=n/\sigma^2$, and therefore, since $g(\mu)=e^\mu$,
          $g'=e^\mu$ and by the delta method,
          \[
            \widehat{\textsf{se}}(\widehat{\theta})
            =\frac{e^{\Xbar}S}{\sqrt{n}},
          \]
          and
          \[
            C_n=\left(
            e^{\Xbar}-z_{\alpha/2}\frac{e^{\Xbar}S}{\sqrt{n}},
            e^{\Xbar}+z_{\alpha/2}\frac{e^{\Xbar}S}{\sqrt{n}}
            \right),
          \]
          is a $1-\alpha$ confidence interval for $\widehat{\theta}$.

          \inputminted{python}{../code/09-09.py}
          \inputminted{text}{../output/09-09.txt}
    \item~
          \begin{figure}[H]
            \centering
            \includegraphics[scale=0.53]{../images/09-09}
            \caption{A comparison of a histogram of the true distribution of
              $\widehat{\theta}$ (upper left), non-parametric bootstrap
              replicates (lower left), parametric bootstrap replicates
              (lower right) and a plot of the delta method distribution
              (upper right).}
          \end{figure}
  \end{enumerate}
\end{ex}

\begin{ex}~
  \begin{enumerate}[(a)]
    \item We have
          \begin{align*}
            \P{\widehat{\theta}\leq x}
             & =\P{X_{(n)}\leq x}                               \\
             & =\P{X_{1}\leq x}\P{X_2\leq x}\cdots\P{X_n\leq x} \\
             & =x^n,
          \end{align*}
          and therefore
          \[
            f_{\widehat{\theta}}(x)=nx^{n-1}. \\
          \]

          \inputminted{python}{../code/09-10.py}

          \begin{figure}[H]
            \centering
            \includegraphics[scale=0.53]{../images/09-10}
            \caption{
              A comparison of a histogram of the non-parametric bootstrap
              (left), the parametric bootstrap (center) and the true
              distribution of $\widehat{\theta}$ (right).}
          \end{figure}
    \item Let $B$ be a random variable given by uniformly randomly sampling
          from $\{X_1,X_2,\ldots,X_n\}$, and let $B^n$ be a sample (with
          replacement) of $n$ elements. Then,
          \begin{align*}
            \P{\widehat{\theta}^*=\widehat{\theta}}
             & =\P{X_{(n)}\in B^n}              \\
             & =1-\P{X_{(n)}\not\in B^n}        \\
             & =1-(1-\P{B = X_{(n)}})^n         \\
             & =1-\left(1-\frac{1}{n}\right)^n,
          \end{align*}
          and therefore
          \[
            \lim_{n\to\infty}\P{\widehat{\theta}^*
              =\widehat{\theta}}
            =1-e^{-1}
            \approx 0.632.
          \]
          However, since $\widehat{\theta}$ has a continuous distribution, the
          probability that it takes on any particular value is $0$. Therefore,
          we cannot use the bootstrap to obtain an arbitrarily good
          approximation of $\widehat{\theta}$, no matter how many samples we
          use.
  \end{enumerate}
\end{ex}


\subsection{Quasi-hyperbolic discounting}

\subsubsection{Introduction}

We have:

\(U_T=\sum_[t=T]^{\infty }d_tU(x_t)\)

\subsubsection{Quasi-hyperbolic discounting}

\(d_0=1\)

\(d_t=\beta \delta^t\)

\(U_T=U(x_0)+\sum_[t=T+1]^{\infty }\beta \delta ^tU(x_t)\)

\(\delta \) is the discount rate.


\section{The Choice of Abella}

We have chosen the Abella (v2.0.5) proof assistant~\citep{AbellaDesc} to
develop our formalization.
% Our development is only based on the reasoning logic of Abella, and does not make use of its specification logic.
Although Abella takes a two-level logic approach,
where the specification logic can be expressed separately from the
reasoning logic, we only make use of its reasoning logic, due to the
difficulty of expressing our algorithmic rules with only the specification.
Abella is particularly helpful due to its built-in support for variable bindings, and
its $\lambda$-tree syntax~\citep{miller2000abstract} is a form of HOAS,
which helps with the encoding and reasoning about substitutions.  For
instance, the type $\forall x. x \to a$ is encoded as \abellae{all (x\  arrow x a)}, where \abellae{x\ arrow x a} is a lambda abstraction in
Abella. An opening $[b/x](x\to a)$ is encoded as an application
\abellae{(x\ arrow x a) b}, which can be simplified(evaluated) to
\abellae{arrow b a}.
Name supply and freshness conditions are controlled by the
$\nabla$-quantifier.  The expression \abellae{nabla x, F} means that
\abellae{x} is a unique variable in \abellae{F}, i.e. it is different
from any other names occurring elsewhere.  Such variables are called
nominal constants.  They can be of any type, in other words, every
type may contain an unlimited number of such atomic nominal constants.

%\subsection{Encoding of Declarative System}

\paragraph{Encoding of the Declarative System}
As a concrete example, our declarative context (well-formedness relation)
and well-formedness rules are encoded as follows.
\begin{abella}
	Kind ty     type.
	Type i      ty.                % the unit type
	Type all    (ty -> ty) -> ty.    % forall-quantifier
	Type arrow  ty -> ty -> ty.      % function type
	Type bound  ty -> o.            % variable collection in contexts

	Define env : olist -> prop by
		env nil;
		nabla x, env (bound x ::E) := env E.

	Define wft : olist -> ty -> prop by
		wft E i;
		nabla x, wft (E x) x := nabla x, member (bound x) (E x);
		wft E (arrow A B) := wft E A /\ wft E B;
		wft E (all A) := nabla x, wft (bound x ::E) (A x).
\end{abella}

In the above code, we first define the syntax of types and contexts in our type system.
A type of our system has type \abellae{ty}, and the context is of type \abellae{olist}.
We use the type \abellae{olist} just as normal list of \abellae{o} with two constructors,
namely \abellae{nil : olist} and \abellae{(::) : o -> olist -> olist},
where \abellae{o} purely means ``the element type of \abellae{olist}'',
and both are built-in types of Abella.
The \abellae{member : o -> olist -> prop} relation is also pre-defined.

Note that in Abella, the symbol (\abellae{:=}) used in definitions
is similar to the (\abellae{:-}) symbol in Prolog,
where we write the condition to its right and the conclusion to its left.
The second case of the relation \abellae{wft} states Rule $\mathtt{wf_d var}$.
The encoding \abellae{(E x)} basically means that the context \emph{may} contain \abellae{x}.
If we write \abellae{(E x)} as \abellae{E}, then the context should not contain \abellae{x}, and both \abellae{wft E x} and \abellae{member (bound x) E} make no sense.
Instead, we treat \abellae{E : ty -> olist} as an \emph{abstract structure} of a context, such as \abellae{x\ bound x ::bound a ::nil}.
For the fourth case of the relation \abellae{wft}, the type $\forall x. A$ in our target language is expressed as \abellae{(all A)}, and its opening $A$, \abellae{(A x)}.

\paragraph{Encoding of the Algorithmic System}
In terms of the algorithmic system, notably, Abella handles the
$\mathtt{{\le_a}instL}$ and $\mathtt{{\le_a}instR}$ rules in a nice way:
\begin{abella}
	% sub_alg_list : enva -> [subty_judgment] -> prop
	Define subal : olist -> olist -> prop by
		subal E nil;
		subal E (subt i i ::Exp) := subal E Exp;
		% some cases omitted ...
		% <: instL
		nabla x, subal (E x) (subt x (arrow A B) ::Exp x) :=
			exists E1 E2 F, nabla x y z, append E1 (exvar x ::E2) (E x) /\
				append E1 (exvar y ::exvar z ::E2) (F y z) /\
				subal (F y z) (subt (arrow y z) (arrow A B) ::Exp (arrow y z));
		% <: instR is symmetric to <: instL, omitted here
		% other cases omitted ...
\end{abella}
In this piece of code, we use \abellae{Exp} to denote the worklist $\Om$.
An algorithmic existential variable $\al$ is constructed by applying
the Abella term \abellae{exvar} to an actual nabla quantified variable.
Thanks to the way Abella deals with nominal constants, the pattern
\abellae{subt x (arrow A B)} implicitly states that $x\notin FV(A) \land x\notin FV(B)$.
If the condition were not required, we would have encoded the pattern as
\abellae{subt x (arrow (A x) (B x))} instead.

\subsection{Statistics and Discussion}\label{subsection:discussion}
\begin{figure}[t]
	\centering\begin{tabular}{|c|c|c|l|}\hline
		File(s) & SLOC & \# of Theorems & Description\\\hline
		olist.thm, nat.thm      &  303 & 55  & Basic data structures\\\hline
		higher.thm, order.thm   &  164 & 15  & Declarative system\\\hline
		higher\_alg.thm         &  618 & 44  & Algorithmic system\\\hline
		trans.thm               &  411 & 46  & Transfer\\\hline
		sound.thm               &  166 & 2   & Soundness theorem\\\hline
		depth.thm               &  143 & 12  & Definition of depth\\\hline
		complete.thm            &  626 & 28  & Lemmas and Completeness theorem\\\hline
		decidable.thm           & 1077 & 53  & Lemmas and Decidability theorem\\\hline
		Total                   & 3627 & 267 & (33 definitions in total)\\\hline
	\end{tabular}
	\caption{Statistics for the proof scripts}\label{fig:SLOC}
\end{figure}

Some basic statistics on our proof script are shown in Figure~\ref{fig:SLOC}.
The proof consists of 3627 lines of code with a total of 33 definitions and 267 theorems.
We have to mention that Abella provides few built-in tactics and does not support user-defined ones, and we would reduce significant lines of code if Abella provided more handy tactics%
\footnote{We do extend Abella with some handy tactics after this work,
which boosts our development and reduce some boilerplate codes.
One may find the modified version in \url{https://github.com/JimmyZJX/abella}.}
Moreover, the definition of natural numbers, the plus operation and less-than relation are defined within our proof due to Abella's lack of packages.
However, the way Abella deals with name bindings
is very helpful for type system formalizations and substitution-intensive formalizations, such as this one.


\chapter{Equations and Algorithm}
\label{sec-figures}

\section{Equations and Algorithm}
Let us assume $\gamma_{ij}$ is the number of matched keypoints among two keyframes, $i$ and $j$. These matches yield a distinct scale difference $\sigma_{ij} $ depending on the number of matched keypoints $\gamma_{ij}$. The optimal scale difference $\sigma^*$ will be
\begin{equation}
	\begin{aligned}
		\sigma^* &= \operatorname*{argmax}_{\gamma} \frac{1}{2}|\gamma(\sigma_{ij}), \gamma(\sigma_{i'j'}) | ,
	\end{aligned}
	\label{eqa-1}
\end{equation}
where $\sigma_{ij} $ and $\sigma_{i'j'}$ are the two nearest points such that\\
\begin{equation}
	\begin{split}
		\quad |\sigma_{ij} - \sigma_{i'j'}| \leq \Delta^* \quad \forall \quad i, j, i' \text{ and } j' \in \mathds{Z}^+, \quad \Delta^* \in \mathbb{R}.
	\end{split}
	\label{eqa-1}
\end{equation}
The estimation is further explained in Algorithm \ref{algorithm-1}.\\

\begin{algorithm}[!h]
	\SetKwInput{KwData}{Input}
	\SetKwInput{KwResult}{Output}
	\KwData{Matched keyframes $\mathbf{K}_{r_{ID}} = \{\mathbf{K}^i_{s},\mathbf{K}^j_{t}\}$ , poses $^w\mathbf{T}_{r_{ID}} = \{^w\mathbf{T}_{s}, \, ^w\mathbf{T}_{t} \}$, point clouds $P_{r_{ID}}^\mathcal{F} = \{P^{\mathcal{F}_s^i}_{s(i)},P^{\mathcal{F}_t^j}_{t(j)}$\} with $i,j \in \mathds{Z}^+$ }
	\KwResult{Optimal scale difference $\sigma^*$, initial guess relative transformation $^{si}\mathbf{T}_{ti}^{IG}$ }
	initialization\;
	\For{$z = -1:1$} {
		$ P_{s(i+z)}^{\mathcal{F}_w} = \,^w\mathbf{T}_{s(i+z)} (P^{\mathcal{F}_{s(i+z)}}_{s(i+z)}) $ \;
		$ P_{t(j+z)}^{\mathcal{F}_w} = \,^w\mathbf{T}_{t(j+z)} (P^{\mathcal{F}_{t(j+z)}}_{t(j+z)}) $ \;
		\SetKwFunction{FMain}{ PCR-Pro \cite{Bhutta2018}}
		\SetKwProg{Fn}{Function}{:}{}
		\Fn{\FMain{$\mathbf{K}_{r_{ID}}$,$P_{r_{ID}}^{\mathcal{F}_w}$}}{
			Estimate volume ratio $r_{vol}$ of $P_{s(i+z)}^{\mathcal{F}_w}, P_{t(j+z)}^{\mathcal{F}_w}$ \;
			$^{s(i+z)}\mathbf{T}_{t(j+z)}^{RC} \longleftarrow \gamma_z \longleftarrow \mathbf{K}^{i+z}_{s},\mathbf{K}^{j+z}_{t} $ \;
			$ \sigma_z \longleftarrow ^{s(i+z)}\mathbf{T}_{t(j+z)}^{RC} , \gamma_z, ^w\mathbf{T}_{s(i+z)} , ^w\mathbf{T}_{t(j+z)} $\;
			$^{s(i+z)}\mathbf{T}_{t(j+z)}^{IG} \longleftarrow \sigma_z, P_{s(i+z)}^{\mathcal{F}_w},P_{t(j+z)}^{\mathcal{F}_w} $ \;
			\KwRet $\sigma_z, ^{s(i+z)}\mathbf{T}_{t(j+z)}^{IG} $ \; }
	}
	\eIf{$r_{vol} > 0.5$}{
		$\Delta^* = 5 $\;
		\For{$x = -1: 1$}{
			\For{$y = -1: 1$}{
				\If{$x \neq y$}{
					$ \Delta = |\sigma_x - \sigma_y| $\;
					\If{$\gamma^* < \gamma_{xy}$ \&\& $\Delta^* > \Delta$ \&\& $\Delta^* \neq 0$ }{
						$\sigma^* = avg(\sigma_x,\sigma_y)$ \;
						$\Delta^* = \Delta$ \;
						$\gamma^* = \gamma_{xy}$ \;
					}
				}
			}
		}
	}{ $\sigma^* =\sigma_{xy=00} $ \; }
	\caption{Finest Tuning for Optimal Scale Estimation}
	\label{algorithm-1}
\end{algorithm}

\newpage

\section{Appendix}

\newpage
\renewcommand*{\bibname}{\section{References}}
\bibliographystyle{ieeetr}
\bibliography{Thesis}