Orbital library

## orbital.math Interface Tensor

All Superinterfaces:
Arithmetic, Normed
All Known Subinterfaces:
Matrix, Vector

`public interface Tensorextends Arithmetic`

Represents a tensor t∈Rn0×n1×…×nr-1 of dimensions n0×n1×…×nr-1 and rank r.

If you intend to use mutable arithmetic elements, note the discussion of mutations per reference vs. explicit cloning in `set(int[],Arithmetic)` which generally holds for all operations that set component values.

Also note that some few methods will change its instance and explicitly `return this` to allow chaining of structural changes, whilst arithmetic methods will leave a tensor unchanged but return a modified version. Refer to the documentation of the individual methods for details.

Author:
André Platzer
`ValueFactory.tensor(Arithmetic[])`, `ValueFactory.tensor(Arithmetic[][])`, `ValueFactory.tensor(Arithmetic[][][])`, `ValueFactory.tensor(Object)`
Invariants:
succeedes(#clone()) ∧ (overwrites(#clone()) ∨ this implements Cloneable)
Structure:
extends Arithmetic, extends Iteratable

Field Summary

Fields inherited from interface orbital.math.Arithmetic
`numerical`

Method Summary
` Tensor` `add(Tensor b)`
Adds two tensors returning a tensor.
` java.lang.Object` `clone()`

` int[]` `dimensions()`
Returns the dimensions of the tensor.
` java.util.Iterator` `entries()`
Returns an iterator over our (relevant) entries (index, coefficient)-pairs.
` Arithmetic` `get(int[] i)`
Get the component specified by index.
` java.util.Iterator` `indices()`
Returns an iterator over the (relevant) indices.
` java.util.ListIterator` `iterator()`
Returns an iterator over all components.
` Tensor` `multiply(Tensor b)`
Inner product of a tensor with a tensor returning a tensor.
` int` `rank()`
Get the rank of the tensor.
` void` ```set(int[] i, Arithmetic vi)```
Sets the component specified by index.
` void` ```setSubTensor(int level, int index, Tensor part)```
Sets a part of lesser rank in this tensor.
` Tensor` ```subTensor(int[] i1, int[] i2)```
Get a sub-tensor view ranging (i1:i2) inclusive.
` Tensor` ```subTensor(int level, int index)```
Get a view on a part of the tensor of a lesser rank.
` Tensor` `subTensorTransposed(int[] permutation)`
Returns a view on this tensor transposed.
` Tensor` `subtract(Tensor b)`
Subtracts two tensors returning a tensor.
` Tensor` `tensor(Tensor b)`
Tensor product of a tensor with a tensor returning a tensor.

Methods inherited from interface orbital.math.Arithmetic
`add, divide, equals, inverse, isOne, isZero, minus, multiply, one, power, scale, subtract, toString, valueFactory, zero`

Methods inherited from interface orbital.math.Normed
`norm`

Method Detail

### clone

`java.lang.Object clone()`
Postconditions:
RES≠RES ∧ RES≠this ∧ RES.equals(this)

### rank

`int rank()`
Get the rank of the tensor. The rank is the number of dimensions needed as indices for the components of this tensor. It is the grade for the tensor algebra T(M) over the underlying module M.

`Matrix.linearRank()`
Postconditions:
RES≥0

### dimensions

`int[] dimensions()`
Returns the dimensions of the tensor.

If n0×n1×…×nr-1 are the dimensions of this tensor of rank r, then all (valid) indices i∈Nr to this tensor satisfy ∀k ik∈{0,…,nk-1}.

Returns:
an array d containing the dimensions of this tensor.
Postconditions:
RES.length == rank()

### get

`Arithmetic get(int[] i)`
Get the component specified by index.

Of course, this method only has a meaning for tensors of free modules like vector spaces.

Parameters:
`i` - the index i of the component value to get.
Returns:
ti[0].i[1],…i[i.length-1] ∈ R.
Preconditions:
valid(i) := (i.length == rank() ∧ ∀k 0≤i[k]≤dimensions()[k]-1)

### set

```void set(int[] i,
Arithmetic vi)
throws java.lang.UnsupportedOperationException```
Sets the component specified by index.

Of course, this method only has a meaning for tensors of free modules like vector spaces.

Depending upon the implementation, the value vi might be kept per reference, if possible. However, whether it is kept per reference is a matter of performance and subject to free interpretation by the implementation class. So if vi is mutable, and a tensor implementation decides to keep it per reference, any modifications of vi would also appear in that tensor, rendering it useless. Since every implementation is allowed to choose the tensor's internal data representation freely, you should not rely on such behaviour of mutable arithmetic objects to provoke inner state changes. Instead you should carefully avoid setting a value by reference without cloning, if you intend to change its state, afterwards. Explicitly cloning vi prior to setting it as an element of this tensor is always safe (provided that you do not keep additional references to it). If, however, vi is immutable (which should be the usual case), no such sources of mistakes exist.

Parameters:
`i` - the index i of the component value to set.
`vi` - the value to set for the component vi at position i.
Throws:
`java.lang.UnsupportedOperationException` - if this tensor is constant and does not allow modifications.
Preconditions:
valid(i)

### iterator

`java.util.ListIterator iterator()`
Returns an iterator over all components.

Note: the list iterator returned is not required to support `ListIterator.nextIndex()` and `ListIterator.previousIndex()`, or `ListIterator.add(Object)` and `ListIterator.remove()`, and won't usually do so. The reason is that one-dimensional indices are meaningless for tensors of rank r>1 and that adding a single component to a tensor is not allowed as it would destroy its rectangular form. Nevertheless, vectors (rank 1) may support those operations.

Returns:
an iterator that iterates over v0,…,0,…,v1,…,0,……,vn1-1,…,nr-1.

### indices

`java.util.Iterator indices()`
Returns an iterator over the (relevant) indices.

The order of this iterator is not generally defined, but should be deterministic. Particularly, the iterator may - but need not - be restricted to occurring indices with coefficients ≠0.

Returns:
an iterator over a finite set of indices in Vector<Integer> at least containing all indices of coefficients ≠0.
Postconditions:
∀i∈Vector<Integer>∖RES get(i)=0

### entries

`java.util.Iterator entries()`
Returns an iterator over our (relevant) entries (index, coefficient)-pairs.

The order of this iterator is not generally defined, but should be deterministic. Particularly, the iterator may - but need not - be restricted to occurring indices with coefficients ≠0.

Returns:
an iterator over a finite set of pairs of indices in Vector<Integer> and coefficients in R at least containing all pairs for coefficients ≠0.
Postconditions:
∀(i,c)∈Vector<Integer>×R∖RES get(i)=0

### subTensor

```Tensor subTensor(int[] i1,
int[] i2)```
Get a sub-tensor view ranging (i1:i2) inclusive.

The resulting tensor is a (sub-)view of this tensor. Therefore, the returned tensor is backed by this tensor, so changes in the returned tensor are reflected in this tensor, and vice-versa.

The semantics of the tensor returned by this method becomes undefined if the backing tensor (i.e., this object) is structurally modified in any way other than via the returned tensor. (Structural modifications are those that change the dimensions, or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results.)

The resulting tensor is structurally unmodifiable in order to prevent it from inducing undefined behaviour on its backing tensor. Query operations on the returned tensor "read through" to this object, and attempts to structurally modify the returned vector, whether direct or via its iterator, result in an `UnsupportedOperationException`. However, setting single components will "write through" to the this object.

Returns:
a tensor view of the specified part of this tensor.
 t(i1:i2) = (ml)l∈{l∈Nr ¦ ∀k i1[k]≤l[k]≤i2[k]}
Preconditions:
i1.length==rank() ∧ i2.length==rank() ∧ ∀k i1[k]≤i2[k] ∧ valid(i1) ∧ valid(i2)

### subTensor

```Tensor subTensor(int level,
int index)```
Get a view on a part of the tensor of a lesser rank.

The returned tensor is a structurally unmodifiable view.

Parameters:
`level` - the level l of indices to fix for this view.
`index` - the index cl of the tensor part view at the level-th index.
Returns:
a tensor view of the specified part ti0×i1×…×il-1×&cl×il+1&×l…×ir-1 in this tensor.
`setSubTensor(int,int,Tensor)`, `Functionals.bindFirst(orbital.logic.functor.BinaryFunction, Object)`, `Functionals.bindSecond(orbital.logic.functor.BinaryFunction, Object)`
Postconditions:
RES.rank() = rank() - 1 ∧ ....

### setSubTensor

```void setSubTensor(int level,
int index,
Tensor part)```
Sets a part of lesser rank in this tensor.

`subTensor(int,int)`
Preconditions:
part.rank()==rank()-1 ∧ Utilities.equalsAll(part.dimensions(), subTensor(level,index).dimensions())

### subTensorTransposed

`Tensor subTensorTransposed(int[] permutation)`
Returns a view on this tensor transposed.

The returned tensor is a view.

Parameters:
`permutation` - the mapping table of a permutation σ∈Srank() mapping i↦permutation[i] for permuting the indices.
Returns:
a tensor view of the transposed tensor tiσ(0)×iσ(1)×…×iσ(r-1) with permuted indices.
Preconditions:
permutation∈Srank()
Postconditions:
RES.rank() = rank() ∧ RES.get(i) = get(permutation(i))

`Tensor add(Tensor b)`
Adds two tensors returning a tensor.

Preconditions:
Arrays.equals(dimensions(), b.dimension()) otherwise there can only be a purely symbolic result in tensor algebra.
Postconditions:
Arrays.equals(RES.dimensions(), dimensions()) && RES.get(i) == get(i) + b.get(i)
Attributes:
associative, neutral (0), inverse (-v), commutative

### subtract

`Tensor subtract(Tensor b)`
Subtracts two tensors returning a tensor.

Preconditions:
Arrays.equals(dimensions(), b.dimension()) otherwise there can only be a purely symbolic result in tensor algebra.
Postconditions:
Arrays.equals(RES.dimensions(), dimensions()) && RES.get(i) == get(i) - b.get(i)
Attributes:
associative

### multiply

`Tensor multiply(Tensor b)`
Inner product of a tensor with a tensor returning a tensor.
 · Rn0×…×nr-1×h×Rh×m0×…×ms-1 → Rn0×…×nr-1×h×Rh×m0×…×ms-1 ((ai0,…,ir-1,ir)i0,…,ir-1,ir , (bj-1,j0,…,js-1)j-1,j0,…,js-1) ↦ (∑ν=0h-1 ai0,…,ir-1,ν⋅bν,j0,…,js-1)i0,…,ir-1,j0,…,js-1

Returns:
the inner product a·b.
Preconditions:
dimensions()[rank()-1] == b.dimensions()[0]
Postconditions:
RES.dimensions() = {dimensions()[0],…dimensions()[rank()-2]}∪{b.dimensions()[1],…b.dimensions()[b.rank()-1]}
Note:
inner product is only one (partial) multiplication on graded tensor algebra

### tensor

`Tensor tensor(Tensor b)`
Tensor product of a tensor with a tensor returning a tensor.
 ⊗ Rn0×…×nr-1×Rm0×…×ms-1 → Rn0×…×nr-1×m0×…×ms-1 ((ai0,…,ir-1)i0,…,ir-1 , (bj0,…,js-1)j0,…,js-1)=(a,b) ↦ (ai0,…,ir-1⋅bj0,…,js-1)i0,…,ir-1,j0,…,js-1 =̂ (ai0,…,ir-1·b)i0,…,ir-1
At least formally, the last form of the calculation resembles the scalar multiplication b·a if a was a vector of a left-Rm0×…×ms-1-modules.

Returns:
the tensor product (or outer product) a⊗b.
Postconditions:
RES.dimensions() = dimensions()∪b.dimensions()
Note:
tensor product is only one multiplication on graded tensor algebra T(M). Although it is always defined, a more "natural" multiplication on tensors of rank 2, for example, is the `inner product` which therefore plays the role of the default (though partial) ring multiplication.

Orbital library
1.3.0: 11 Apr 2009