Functions

The elementary tensor operations can also be accessed via functions, mainly for compatibility with older versions of this toolbox. The function-based syntax is also required when the contraction pattern is not known at compile time but is rather determined dynamically.

The basic exposed interface, as listed below, makes use of any iterable IA, IB or IC to denote labels of indices, in a similar fashion as when used in the context of @tensor. When making use of this functionality, in-place operations are no longer supported, as these are reserved for the expert mode. Note that the return type is only inferred when the labels are entered as tuples, and also IC is specified.

The expert mode exposes both mutating and non-mutating versions of these functions. In this case, selected indices are determined through permutations, specified by pA, pB and pC. In order to distinguish from the non-mutating version in simple mode, overlapping functionality is distinguished by specializing on these permutations, which are required to take a particular form of the type Index2Tuple.

TensorOperations.Index2TupleType
Index2Tuple{N₁,N₂} = Tuple{NTuple{N₁,Int},NTuple{N₂,Int}}

A specification of a permutation of N₁ + N₂ indices that are partitioned into N₁ left and N₂ right indices.

source

The motivation for this particular convention for specifying permutations comes from the fact that for many operations, it is useful to think of a tensor as a linear map or matrix, in which its different indices are partioned into two groups, the first of which correspond to the range of the linear map (the row index of the associated matrix), whereas the second group corresponds to the domain of the linear map (the column index of the associated matrix). This is most obvious for tensor contraction, which then becomes equivalent to matrix multiplication (which is also how it is implemented by the StridedBLAS backend). While less relevant for tensor permutations, we use this convention throughout for uniformity and generality (e.g. for compatibility with libraries that always represent tensors as linear maps, such as TensorKit.jl).

Note, finally, that only the expert mode call style exposes the ability to select custom backends.

Non-mutating functions

TensorOperations.tensorcopyFunction
tensorcopy([IC=IA], A, IA, [conjA=:N, [α=1]])
tensorcopy(pC::Index2Tuple, A, conjA, α) # expert mode

Create a copy of A, where the dimensions of A are assigned indices from the iterable IA and the indices of the copy are contained in IC. Both iterables should contain the same elements, optionally in a different order.

The result of this method is equivalent to α * permutedims(A, pC) where pC is the permutation such that IC = IA[pC]. The implementation of tensorcopy is however more efficient on average, especially if Threads.nthreads() > 1.

Optionally, the symbol conjA can be used to specify whether the input tensor should be conjugated (:C) or not (:N).

See also tensorcopy!.

source
TensorOperations.tensoraddFunction
tensoradd([IC=IA], A, IA, [conjA], B, IB, [conjB], [α=1, [β=1]])
tensoradd(A, pA::Index2Tuple, conjA, B, pB::Index2Tuple, pB::Index2Tuple, conjB, α=1, β=1, [backend]) # expert mode

Return the result of adding arrays A and B where the iterables IA and IB denote how the array data should be permuted in order to be added. More specifically, the result of this method is equivalent to α * permutedims(A, pA) + β * permutedims(B, pB) where pA (pB) is the permutation such that IC = IA[pA] (IB[pB]). The implementation of tensoradd is however more efficient on average, as the temporary permuted arrays are not created.

Optionally, the symbols conjA and conjB can be used to specify whether the input tensors should be conjugated (:C) or not (:N).

See also tensoradd!.

source
TensorOperations.tensortraceFunction
tensortrace([IC], A, IA, [conjA], [α=1])
tensortrace(pC::Index2Tuple, A, pA::Index2Tuple, conjA, α=1, [backend]) # expert mode

Trace or contract pairs of indices of tensor A, by assigning them identical indices in the iterable IA. The untraced indices, which are assigned a unique index, can be reordered according to the optional argument IC. The default value corresponds to the order in which they appear. Note that only pairs of indices can be contracted, so that every index in IA can appear only once (for an untraced index) or twice (for an index in a contracted pair).

Optionally, the symbol conjA can be used to specify that the input tensor should be conjugated.

See also tensortrace!.

source
TensorOperations.tensorcontractFunction
tensorcontract([IC], A, IA, [conjA], B, IB, [conjB], [α=1])
tensorcontract(pC::Index2Tuple, A, pA::Index2Tuple, conjA, B, pB::Index2Tuple, conjB, α=1, [backend]) # expert mode

Contract indices of tensor A with corresponding indices in tensor B by assigning them identical labels in the iterables IA and IB. The indices of the resulting tensor correspond to the indices that only appear in either IA or IB and can be ordered by specifying the optional argument IC. The default is to have all open indices of A followed by all open indices of B. Note that inner contractions of an array should be handled first with tensortrace, so that every label can appear only once in IA or IB seperately, and once (for an open index) or twice (for a contracted index) in the union of IA and IB.

Optionally, the symbols conjA and conjB can be used to specify that the input tensors should be conjugated.

See also tensorcontract!.

source
TensorOperations.tensorproductFunction
tensorproduct([IC], A, IA, [conjA], B, IB, [conjB], [α=1])
tensorproduct(pC::Index2Tuple, A, pA::Index2Tuple, conjA, B, pB::Index2Tuple, conjB, α=1, [backend]) # expert mode

Compute the tensor product (outer product) of two tensors A and B, i.e. returns a new tensor C with ndims(C) = ndims(A) + ndims(B). The indices of the output tensor are related to those of the input tensors by the pattern specified by the indices. Essentially, this is a special case of tensorcontract with no indices being contracted over. This method checks whether the indices indeed specify a tensor product instead of a genuine contraction.

Optionally, the symbols conjA and conjB can be used to specify that the input tensors should be conjugated.

See also tensorproduct! and tensorcontract.

source

Mutating functions

TensorOperations.tensorcopy!Function
tensorcopy!(C, pC::Index2Tuple, A, conjA=:N, α=1, [backend])

Copy the contents of tensor A into C, where the dimensions A are permuted according to the permutation and repartition pC.

The result of this method is equivalent to α * permutedims!(C, A, pC).

Optionally, the symbol conjA can be used to specify whether the input tensor should be conjugated (:C) or not (:N).

Warning

The object C must not be aliased with A.

See also tensorcopy and tensoradd!

source
TensorOperations.tensoradd!Function
tensoradd!(C, pC, A, conjA, α=1, β=1 [, backend])

Compute C = β * C + α * permutedims(opA(A), pC) without creating the intermediate temporary. The operation opA acts as identity if conjA equals :N and as conj if conjA equals :C. Optionally specify a backend implementation to use.

Warning

The permutation needs to be trivial or C must not be aliased with A.

See also tensoradd.

source
TensorOperations.tensortrace!Function
tensortrace!(C, pC, A, pA, conjA, α=1, β=0 [, backend])

Compute C = β * C + α * permutedims(partialtrace(opA(A)), pC) without creating the intermediate temporary, where A is partially traced, such that indices in pA[1] are contracted with indices in pA[2], and the remaining indices are permuted according to pC. The operation opA acts as identity if conjA equals :N and as conj if conjA equals :C. Optionally specify a backend implementation to use.

Warning

The object C must not be aliased with A.

See also tensortrace.

source
TensorOperations.tensorcontract!Function
tensorcontract!(C, pC, A, pA, conjA, B, pB, conjB, α=1, β=0 [, backend])

Compute C = β * C + α * permutedims(contract(opA(A), opB(B)), pC) without creating the intermediate temporary, where A and B are contracted such that the indices pA[2] of A are contracted with indices pB[1] of B. The remaining indices (pA[1]..., pB[2]...) are then permuted according to pC. The operation opA acts as identity if conjA equals :N and as conj if conjA equals :C; the operation opB is determined by conjB analogously. Optionally specify a backend implementation to use.

Warning

The object C must not be aliased with A or B.

See also tensorcontract.

source
TensorOperations.tensorproduct!Function
tensorproduct!(C, pC::Index2Tuple, A, pA::Index2Tuple, conjA, B, pB::Index2Tuple, conjB, α=1, β=0)

Compute the tensor product (outer product) of two tensors A and B, i.e. a wrapper of tensorcontract! with no indices being contracted over. This method checks whether the indices indeed specify a tensor product instead of a genuine contraction.

Warning

The object C must not be aliased with A or B.

See als tensorproduct and tensorcontract!.

source