Tensors
There are many jokes[1] about how to define a tensor. The definition we are giving here might not be the most correct one, but it is good enough for our use case (don't kill me please, mathematicians). A tensor $T$ of order[2] $n$ is a multilinear[3] application between $n$ vector spaces over a field $\mathcal{F}$.
\[T : \mathcal{F}^{\dim(1)} \times \dots \times \mathcal{F}^{\dim(n)} \mapsto \mathcal{F}\]
In layman's terms, it is a linear function whose inputs are vectors and the output is a scalar number.
\[T(\mathbf{v}^{(1)}, \dots, \mathbf{v}^{(n)}) = c \in \mathcal{F} \qquad\qquad \forall i, \mathbf{v}^{(i)} \in \mathcal{F}^{\dim(i)}\]
Tensor algebra is a higher-order generalization of linear algebra, where scalar numbers can be viewed as order-0 tensors, vectors as order-1 tensors, matrices as order-2 tensors, ...
Letters are used to identify each of the vector spaces the tensor relates to. In computer science, you would intuitively think of tensors as "n-dimensional arrays with named dimensions".
\[T_{ijk} \iff \mathtt{T[i,j,k]}\]
The Tensor
type
In Tenet
, a tensor is represented by the Tensor
type, which wraps an array and a list of symbols. As it subtypes AbstractArray
, many array operations can be dispatched to it.
You can create a Tensor
by passing an array and a list of Symbol
s that name indices.
julia> Tᵢⱼₖ = Tensor(rand(3,5,2), (:i,:j,:k))
3×5×2 Tensor{Float64, 3, Array{Float64, 3}}: [:, :, 1] = 0.856683 0.145502 0.0557248 0.278963 0.491097 0.206406 0.386431 0.730751 0.568332 0.811748 0.339962 0.472565 0.503165 0.257437 0.90054 [:, :, 2] = 0.188117 0.87917 0.455394 0.66334 0.540783 0.033555 0.552676 0.63456 0.169788 0.991496 0.659076 0.84335 0.544048 0.893069 0.32084
The dimensionality or size of each index can be consulted using the size
function.
Base.size
— MethodBase.size(::Tensor[, i])
Return the size of the underlying array or the dimension i
(specified by Symbol
or Integer
).
julia> size(Tᵢⱼₖ)
(3, 5, 2)
julia> size(Tᵢⱼₖ, :j)
5
julia> length(Tᵢⱼₖ)
30
Operations
Contraction
Tenet.contract
— Methodcontract(a::Tensor[, b::Tensor]; dims=nonunique([inds(a)..., inds(b)...]))
Perform tensor contraction operation.
Factorizations
LinearAlgebra.svd
— MethodLinearAlgebra.svd(tensor::Tensor; left_inds, right_inds, virtualind, kwargs...)
Perform SVD factorization on a tensor.
Keyword arguments
left_inds
: left indices to be used in the SVD factorization. Defaults to all indices oft
exceptright_inds
.right_inds
: right indices to be used in the SVD factorization. Defaults to all indices oft
exceptleft_inds
.virtualind
: name of the virtual bond. Defaults to a randomSymbol
.
LinearAlgebra.qr
— MethodLinearAlgebra.qr(tensor::Tensor; left_inds, right_inds, virtualind, kwargs...)
Perform QR factorization on a tensor.
Keyword arguments
left_inds
: left indices to be used in the QR factorization. Defaults to all indices oft
exceptright_inds
.right_inds
: right indices to be used in the QR factorization. Defaults to all indices oft
exceptleft_inds
.virtualind
: name of the virtual bond. Defaults to a randomSymbol
.
LinearAlgebra.lu
— MethodLinearAlgebra.lu(tensor::Tensor; left_inds, right_inds, virtualind, kwargs...)
Perform LU factorization on a tensor.
Keyword arguments
left_inds
: left indices to be used in the LU factorization. Defaults to all indices oft
exceptright_inds
.right_inds
: right indices to be used in the LU factorization. Defaults to all indices oft
exceptleft_inds
.virtualind
: name of the virtual bond. Defaults to a randomSymbol
.
- 1For example, recursive definitions like a tensor is whatever that transforms as a tensor.
- 2The order of a tensor may also be known as rank or dimensionality in other fields. However, these can be missleading, since it has nothing to do with the rank of linear algebra nor with the dimensionality of a vector space. We prefer to use word order.
- 3Meaning that the relationships between the output and the inputs, and the inputs between them, are linear.