Dense Tensor (pyttb.tensor)
For all examples in this document, the following imports are assumed:
>>> import pyttb as ttb
>>> import numpy as np
- class pyttb.tensor[source]
Bases:
objectClass for dense tensors.
- Parameters:
data (optional) – Source data as
numpy.ndarray.shape (optional) – Shape of the tensor as a
tupleor any iterable array of integers. A single integer means that the tensor should be a 1D array. Ifshapeis not given, defaults tonumpy.ndarray.shapeofdata. Otherwise,datais reshaped to the specifiedshape.copy (optional) – Whether to deep copy (versus reference)
data. By default,datais deep copied.
Examples
Create a
pyttb.tensorfrom a three-waynumpy.ndarray:>>> data = np.array( ... [[[1,13],[5,17],[ 9,21]], ... [[2,14],[6,18],[10,22]], ... [[3,15],[7,19],[11,23]], ... [[4,16],[8,20],[12,24]]] ... ) >>> T = ttb.tensor(data) >>> print(T) tensor of shape (4, 3, 2) with order F data[:, :, 0] = [[ 1 5 9] [ 2 6 10] [ 3 7 11] [ 4 8 12]] data[:, :, 1] = [[13 17 21] [14 18 22] [15 19 23] [16 20 24]]
Create a
pyttb.tensorfrom anumpy.ndarrayvector and reshape it:>>> data = np.arange(1,25) >>> T = ttb.tensor(data, shape=(4, 3, 2)) >>> print(T) tensor of shape (4, 3, 2) with order F data[:, :, 0] = [[ 1 5 9] [ 2 6 10] [ 3 7 11] [ 4 8 12]] data[:, :, 1] = [[13 17 21] [14 18 22] [15 19 23] [16 20 24]]
Create an empty
pyttb.tensor:>>> T = ttb.tensor() >>> print(T) empty tensor of shape () data = []
Notes
Instances of
pyttb.tensorcan also be created using the following methods:from_function()- Create a tensor from a functioncopy()- Make a deep copy of a tensortenones()- Create an all ones tensor of a specified sizetenzeros()- Create an all zeros tensor of a specified sizetenrand()- Create a random tensor of a specified sizetendiag()- Create a tensor with a specified diagonalteneye()- Create an identity tensorpyttb.sptensor.to_tensor()- Convert a sparse tensor to a dense tensorpyttb.ktensor.to_tensor()- Convert a Kruskal tensor to a dense tensorpyttb.ttensor.to_tensor()- Convert a Tucker tensor to a dense tensorpyttb.tenmat.to_tensor()- Convert a tenmat to a dense tensor
Tutorial
See the Dense Tensors tutorial for getting started with the tensor class.
Attributes and Methods
- property ndims: int
Number of dimensions of the tensor (i.e., length of the tensor shape).
Examples
>>> T = ttb.tenones((2, 2, 2)) >>> T.ndims 3
- property nnz: int
Number of non-zero elements in the tensor (even though this is a dense tensor).
Examples
>>> T = ttb.tenones((2, 2, 2)) >>> T.nnz 8
- classmethod from_function(function_handle: Callable[[tuple[int, ...]], ndarray], shape: int | Iterable[int]) tensor[source]
Construct a
pyttb.tensorwith data from a function.- Parameters:
function_handle – A function that can accept a shape (i.e.,
tupleof dimension sizes) and return anumpy.ndarrayof that shape. The array returned by the function should ideally be in Fortran order. If that is not the case, an expensive reordering of the data will be required. One way to avoid this reordering is to return a 1D vector.shape – Shape of the resulting tensor.
- Returns:
Constructed tensor.
Examples
Create a
pyttb.tensorwith entries drawn from a normal distribution usingnumpy.random.randn(). Observe that we actually generate a vector to avoid having a C-ordered array (the default if we had provided the shape array) be rearranged as a F-ordered array:>>> randn = lambda s : np.random.randn(np.prod(s)) >>> np.random.seed(0) # reproducibility >>> T = ttb.tensor.from_function(randn, (4, 3, 2)) >>> print(T) tensor of shape (4, 3, 2) with order F data[:, :, 0] = [[ 1.7640... 1.8675... -0.1032...] [ 0.4001... -0.9772... 0.4105...] [ 0.9787... 0.9500... 0.1440...] [ 2.2408... -0.1513... 1.4542...]] data[:, :, 1] = [[ 0.7610... 1.4940... -2.5529...] [ 0.1216... -0.2051... 0.6536...] [ 0.4438... 0.3130... 0.8644...] [ 0.3336... -0.8540... -0.7421...]]
Create a
pyttb.tensorwith all entries equal to 1 usingnumpy.ones(). Observe that we specifically specify Fortran order:>>> T = ttb.tensor.from_function(lambda s: np.ones(s), (2, 3, 4)) >>> print(T) tensor of shape (2, 3, 4) with order F data[:, :, 0] = [[1. 1. 1.] [1. 1. 1.]] data[:, :, 1] = [[1. 1. 1.] [1. 1. 1.]] data[:, :, 2] = [[1. 1. 1.] [1. 1. 1.]] data[:, :, 3] = [[1. 1. 1.] [1. 1. 1.]]
- collapse(dims: None, fun: Callable[[np.ndarray], float | np.ndarray]) float[source]
- collapse(dims: int | float | Iterable[int] | Iterable[float] | ndarray, fun: Callable[[np.ndarray], float | np.ndarray] = np.sum) np.ndarray | tensor
Collapse tensor along specified dimensions using a function.
- Parameters:
dims (optional) – Dimensions to collapse (default: all).
fun (optional) – Function used to collapse dimensions (default:
numpy.sum()).
- Returns:
Scalar (if all dimensions collapsed) or tensor.
Examples
Sum all elements of tensor:
>>> T = ttb.tenones((4, 3, 2)) >>> T.collapse() 24.0
Compute the sum for each mode-0 fiber (output is a tensor):
>>> T.collapse(0) tensor of shape (3, 2) with order F data[:, :] = [[4. 4.] [4. 4.] [4. 4.]]
Compute the sum of the entries in each mode-0 slice (output is a tensor):
>>> T.collapse([1, 2]) tensor of shape (4,) with order F data[:] = [6. 6. 6. 6.]
Compute the max entry in each mode-2 slice (output is a tensor):
>>> T.collapse([0, 1], fun=np.max) tensor of shape (2,) with order F data[:] = [1. 1.]
Find the maximum and minimum values in a tensor:
>>> randn = lambda s: np.random.randn(np.prod(s)) >>> np.random.seed(0) # reproducibility >>> T = ttb.tensor.from_function(randn, (2, 2, 2)) >>> print(T) tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[1.7640... 0.9787...] [0.4001... 2.2408...]] data[:, :, 1] = [[ 1.8675... 0.9500...] [-0.9772... -0.1513...]] >>> max_val = T.collapse(fun=np.max) >>> min_val = T.collapse(fun=np.min) >>> print(f"Max value: {max_val:1.4f}") Max value: 2.2409 >>> print(f"Min value: {min_val:1.4f}") Min value: -0.9773
- contract(i1: int, i2: int) np.ndarray | tensor[source]
Contract tensor along two dimensions (array trace).
Note that the dimensions used in the contraction must have the same size.
- Parameters:
i1 – First dimension.
i2 – Second dimension.
- Returns:
Contracted tensor.
Examples
Contract a three-way 2 x 2 x 2 tensor along two dimensions in three possible ways:
>>> T = ttb.tenones((2, 2, 2)) # All-ones 2 x 2 x 2 tensor >>> T.contract(0, 1) tensor of shape (2,) with order F data[:] = [2. 2.] >>> T = ttb.tensor(np.arange(1, 9), (2, 2, 2)) >>> print(T) tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[1 3] [2 4]] data[:, :, 1] = [[5 7] [6 8]] >>> T.contract(0, 1) tensor of shape (2,) with order F data[:] = [ 5. 13.] >>> T.contract(0, 2) tensor of shape (2,) with order F data[:] = [ 7. 11.] >>> T.contract(1, 2) tensor of shape (2,) with order F data[:] = [ 8. 10.]
- copy() tensor[source]
Make a deep copy of a
pyttb.tensor.- Returns:
Deep copy of original tensor.
Examples
Observing the difference between a shallow copy and a deep copy. When the original tensor changes, so does the shallow copy, but the deep copy does not:
>>> T = ttb.tensor(np.ones(8), (2, 2, 2)) >>> T_shallow = T >>> T_deep = T.copy() >>> T[0, 0, 0] = 3 >>> T[0, 0, 0] == T_shallow[0, 0, 0] True >>> T[0, 0, 0] == T_deep[0, 0, 0] False
- double(immutable: bool = False) ndarray[source]
Convert :class:pyttb.tensor to an :class:numpy.ndarray of doubles.
- Parameters:
immutable – Whether or not the returned data cam be mutated. May enable additional optimizations.
- Returns:
Array of tensor data.
Examples
>>> T = ttb.tensor(np.ones(8), (2, 2, 2)) # All-ones 2 x 2 x 2 tensor >>> T.double() array([[[1., 1.], [1., 1.]], [[1., 1.], [1., 1.]]])
- exp() tensor[source]
Exponential of the elements of tensor.
- Returns:
Copy of tensor data with the exponential function applied to data element-wise.
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) # Tensor with entries 0 to 7 >>> print(T) tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0 2] [1 3]] data[:, :, 1] = [[4 6] [5 7]] >>> print(T.exp()) tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[ 1. 7.3890...] [ 2.7182... 20.0855...]] data[:, :, 1] = [[ 54.5981... 403.4287...] [ 148.4131... 1096.6331...]]
- find() tuple[ndarray, ndarray][source]
Find subscripts of nonzero elements in a tensor.
- Returns:
Array of subscripts of the nonzero values in the tensor and a column vector of
the corresponding values.
Examples
Create a random tensor with approximately 50% zero entries:
>>> np.random.seed(6) # reproducibility >>> sprandint = lambda s: np.where(np.random.rand(np.prod(s)) < 0.5, ... 0.0, np.random.rand(np.prod(s))) >>> T = ttb.tensor.from_function(sprandint, (2,2,2)) >>> print(T) tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0.3354... 0.4381...] [0. 0. ]] data[:, :, 1] = [[0. 0.6453...] [0.5788... 0. ]]
Find the nonzero entries in the tensor:
>>> subs, vals = T.find() >>> print(subs) [[0 0 0] [0 1 0] [1 0 1] [0 1 1]] >>> print(vals) [[0.3354...] [0.4381...] [0.5788...] [0.6453...]]
- full() tensor[source]
Create a dense tensor from dense tensor.
Convenience method to maintain common interface with other tensor types.
- Returns:
Shallow copy of original tensor.
- innerprod(other: tensor | ttb.sptensor | ttb.ktensor | ttb.ttensor) float[source]
Efficient inner product between a tensor and other
pyttbtensors.- Parameters:
other – Tensor to take an inner product with.
Examples
>>> T = ttb.tensor(np.array([[1.0, 0.0], [0.0, 4.0]])) >>> T.innerprod(T) 17.0 >>> S = T.to_sptensor() >>> T.innerprod(S) 17.0
- isequal(other: tensor | ttb.sptensor) bool[source]
Exact equality for tensors.
- Parameters:
other – Tensor to compare against.
Examples
>>> T1 = ttb.tensor(2 * np.ones((2, 2, 2))) >>> T2 = 2 * ttb.tensor(np.ones((2, 2, 2))) >>> T1.isequal(T2) True >>> T2[1, 0, 1] = 1 >>> T1.isequal(T2) False
- issymmetric(grps: np.ndarray | None, version: Any | None, return_details: Literal[False]) bool[source]
- issymmetric(grps: np.ndarray | None, version: Any | None, return_details: Literal[True]) tuple[bool, ndarray, ndarray]
Determine if a dense tensor is symmetric in specified modes.
- Parameters:
grps – Modes to check for symmetry.
version – Any non-None value will call the non-default old version.
return_details – Flag to return symmetry details in addition to bool.
- Returns:
If symmetric in modes; optionally all differences and permutations.
Examples
>>> T = ttb.tenones((2, 2, 2)) >>> T.issymmetric() True >>> T.issymmetric(grps=np.arange(T.ndims)) True >>> is_sym, diffs, perms = T.issymmetric( ... grps=np.arange(T.ndims), version=1, return_details=True ... ) >>> print(f"Tensor is symmetric: {is_sym}") Tensor is symmetric: True >>> print(f"Differences in modes: {diffs}") Differences in modes: [[0.] [0.] [0.] [0.] [0.] [0.]] >>> print(f"Permutations: {perms}") Permutations: [[0. 1. 2.] [0. 2. 1.] [1. 0. 2.] [1. 2. 0.] [2. 0. 1.] [2. 1. 0.]]
- logical_and(other: float | tensor) tensor[source]
Logical and for tensors.
- Parameters:
other – Value to perform and against.
Examples
>>> T = ttb.tenones((2, 2, 2)) >>> T.logical_and(T).collapse() # All true 8.0
- logical_not() tensor[source]
Logical not for tensors.
Examples
>>> T = ttb.tenones((2, 2, 2)) >>> T.logical_not().collapse() # All false 0.0
- logical_or(other: float | tensor) tensor[source]
Logical or for tensors.
- Parameters:
other – Value to perform or against.
Examples
>>> T = ttb.tenones((2, 2, 2)) >>> T.logical_or(T.logical_not()).collapse() # All true 8.0
- logical_xor(other: float | tensor) tensor[source]
Logical xor for tensors.
- Parameters:
other – Value to perform xor against.
Examples
>>> T = ttb.tenones((2, 2, 2)) >>> T.logical_xor(T.logical_not()).collapse() # All true 8.0
- mask(W: tensor) ndarray[source]
Extract non-zero values at locations specified by mask tensor W.
- Parameters:
W – Mask tensor.
- Returns:
Array of extracted values.
Examples
Create a 2 x 2 x 2 tensor with values 0-7, then extract the values along the diagonal of the tensor:
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> print(T) tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0 2] [1 3]] data[:, :, 1] = [[4 6] [5 7]] >>> W = ttb.tendiag(np.ones(T.shape[0]), T.shape) >>> T.mask(W) array([0, 7])
- mttkrp(U: ttb.ktensor | Sequence[np.ndarray], n: int | np.integer) np.ndarray[source]
Matricized tensor times Khatri-Rao product.
The matrices used in the Khatri-Rao product are passed as a
pyttb.ktensor(where the factor matrices are used) or as a list ofnumpy.ndarrayobjects.- Parameters:
U – Matrices to create the Khatri-Rao product.
n – Mode used to matricize tensor.
- Returns:
Array containing matrix product.
Examples
>>> T = ttb.tenones((2, 2, 2)) >>> U = [np.ones((2, 2))] * 3 >>> T.mttkrp(U, 2) array([[4., 4.], [4., 4.]])
- mttkrps(U: ttb.ktensor | Sequence[np.ndarray]) list[np.ndarray][source]
Sequence of MTTKRP calculations for a tensor.
Result is equivalent to [T.mttkrp(U, k) for k in range(T.ndims)].
- Parameters:
U – Matrices to create the Khatri-Rao product.
- Returns:
Array containing matrix product.
Examples
>>> T = ttb.tenones((2, 2, 2)) >>> U = [np.ones((2, 2))] * 3 >>> T.mttkrps(U) [array([[4., 4.], [4., 4.]]), array([[4., 4.], [4., 4.]]), array([[4., 4.], [4., 4.]])]
- norm() float[source]
Frobenius norm of the tensor.
Defined as the square root of the sum of the squares of the elements of the tensor.
Examples
>>> T = ttb.tenones((2, 2, 2, 2)) >>> T.norm() 4.0
- nvecs(n: int, r: int, flipsign: bool = True) ndarray[source]
Compute the leading mode-n vectors of the tensor.
Computes the r leading eigenvectors of Tn*Tn.T (where Tn is the mode-n matricization/unfolding of self), which provides information about the mode-n fibers. In two-dimensions, the r leading mode-1 vectors are the same as the r left singular vectors and the r leading mode-2 vectors are the same as the r right singular vectors. By default, this method computes the top r eigenvectors of Tn*Tn.T.
- Parameters:
n – Mode for tensor matricization.
r – Number of eigenvectors to compute and use.
flipsign – If True, make each column’s largest element positive.
- Returns:
Computed eigenvectors.
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> T.nvecs(0, 1) array([[0.6318...], [0.7751...]]) >>> T.nvecs(0, 2) array([[ 0.6318..., 0.7751...], [ 0.7751..., -0.6318...]])
- permute(order: int | float | Iterable[int] | Iterable[float] | ndarray) tensor[source]
Permute tensor dimensions.
The result is a tensor that has the same values, but the order of the subscripts needed to access any particular element are rearranged as specified by order.
- Parameters:
order – New order of tensor dimensions.
- Returns:
New tensor with permuted dimensions.
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> print(T) tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0 2] [1 3]] data[:, :, 1] = [[4 6] [5 7]] >>> T.permute(np.array((2, 1, 0))) tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0 2] [4 6]] data[:, :, 1] = [[1 3] [5 7]]
- reshape(shape: int | Iterable[int]) tensor[source]
Reshape the tensor.
- Parameters:
shape – New shape.
Examples
>>> T = ttb.tenones((2, 2, 2)) >>> T.shape (2, 2, 2) >>> T.reshape((1, 4, 2)) tensor of shape (1, 4, 2) with order F data[:, :, 0] = [[1. 1. 1. 1.]] data[:, :, 1] = [[1. 1. 1. 1.]]
- scale(factor: np.ndarray | ttb.tensor, dims: float | np.ndarray) tensor[source]
Scale along specified dimensions for tensors.
- Parameters:
factor – Scaling factor.
dims – Dimensions to scale.
- Returns:
Scaled tensor.
Examples
Create tensor of ones and scale dimension 2 using a
numpy.ndarray:>>> T = ttb.tenones((3, 4, 5)) >>> S = np.arange(5) >>> Y = T.scale(S, 2) >>> T.data[0, 0, :] array([1., 1., 1., 1., 1.]) >>> Y.data[0, 0, :] array([0., 1., 2., 3., 4.])
Scale in the same way using a tensor:
>>> S = ttb.tensor(np.arange(5)) >>> Y = T.scale(S, 2) >>> Y.data[0, 0, :] array([0., 1., 2., 3., 4.])
Scale along multiple dimensions:
>>> S = ttb.tensor(np.arange(12), shape=(3, 4)) >>> Y = T.scale(S, [0, 1]) >>> Y.data[:, :, 0] array([[ 0., 3., 6., 9.], [ 1., 4., 7., 10.], [ 2., 5., 8., 11.]])
- squeeze() tensor | float[source]
Remove singleton dimensions from the tensor.
- Returns:
Tensor or scalar if all dims squeezed.
Examples
Create a 3-way tensor with two singleton dimensions and then apply squeeze:
>>> T = ttb.tensor(np.array([[[1, 2, 3]]])) >>> print(T) tensor of shape (1, 1, 3) with order F data[:, :, 0] = [[1]] data[:, :, 1] = [[2]] data[:, :, 2] = [[3]] >>> T.squeeze() tensor of shape (3,) with order F data[:] = [1 2 3]
- symmetrize(grps: np.ndarray | None = None, version: Any | None = None) tensor[source]
Symmetrize a tensor in the specified modes.
It is the same or less work to just call T = T.symmetrize() then to first check if T is symmetric and then symmetrize it, even if T is already symmetric.
- Parameters:
grps – Modes to check for symmetry.
version – Any non-None value will call the non-default old version.
- Returns:
Symmetrized tensor.
Examples
Create a 2 x 2 x 2 tensor with values 0-7 and check if it is symmetric:
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0 2] [1 3]] data[:, :, 1] = [[4 6] [5 7]] >>> T.issymmetric() False
Symmetrize the tensor:
>>> T.symmetrize() tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0. 2.3333...] [2.3333... 4.6666...]] data[:, :, 1] = [[2.3333... 4.6666...] [4.6666... 7. ]]
- ttm(matrix: np.ndarray | Sequence[np.ndarray], dims: OneDArray | None = None, exclude_dims: OneDArray | None = None, transpose: bool = False) tensor[source]
Tensor times matrix.
Computes the n-mode product of self with the matrix matrix; i.e., self x_n matrix. The integer n specifies the dimension (or mode) along which the matrix should be multiplied. If matrix.shape = (J,I), then the tensor must have self.shape[n] = I. The result will be the same order and shape as self except that the size of dimension n will be J.
Multiplication with more than one matrix is provided using a list of matrices and corresponding dimensions in the tensor to use. Multiplication using the transpose of the matrix (or matrices) is also provided.
The dimensions of the tensor with which to multiply can be provided as dims, or the dimensions to exclude from [0, …, self.ndims] can be specified using exclude_dims.
- Parameters:
matrix – Matrix or matrices to multiple by.
dims – Dimensions to multiply against.
exclude_dims – Multiply using all dimensions but these.
transpose – Transpose matrices during multiplication.
- Returns:
Tensor product.
Examples
Create 4-way tensor of ones and multiply by matrix specified by list of vectors:
>>> T = ttb.tenones((2, 2, 2, 2)) >>> A = 2 * np.ones((2, 1)) >>> T.ttm([A, A], dims=[0, 1], transpose=True) tensor of shape (1, 1, 2, 2) with order F data[:, :, 0, 0] = [[16.]] data[:, :, 1, 0] = [[16.]] data[:, :, 0, 1] = [[16.]] data[:, :, 1, 1] = [[16.]]
Repeat by specifying which dimensions to exclude rather than to include:
>>> T.ttm([A, A], exclude_dims=[0, 1], transpose=True) tensor of shape (2, 2, 1, 1) with order F data[:, :, 0, 0] = [[16. 16.] [16. 16.]]
- ttt(other: tensor, selfdims: int | np.ndarray | None = None, otherdims: int | np.ndarray | None = None) tensor[source]
Tensor times tensor.
Computes the contracted product of tensors, self and other, in the dimensions specified by the selfdims and otherdims. The sizes of the dimensions specified by selfdims and otherdims must match; that is, self.shape(selfdims) must equal other.shape(otherdims). If only selfdims is provided as input, it is used to specify the dimensions for both self and other.
- Parameters:
other – Tensor to multiply by.
selfdims – Dimensions to contract self by for multiplication.
otherdims – Dimensions to contract other tensor by for multiplication.
- Returns:
Tensor product.
Examples
Create 4-way tensor with values 0-15 and 2-way tensor of ones:
>>> T1 = ttb.tensor(np.arange(16), (2, 2, 2, 2)) >>> T2 = ttb.tenones((2, 2, 2))
Compute tensor times tensor using dimensions 0 and 1 of both tensors:
>>> T1.ttt(T2, np.array([0, 1])) tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[ 6. 38.] [22. 54.]] data[:, :, 1] = [[ 6. 38.] [22. 54.]]
Compute tensor times tensor using different (but compatible) dimensions of the two tensors involved:
>>> T1.ttt(T2, selfdims=np.array([1, 3]), otherdims=np.array([0, 1])) tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[20. 36.] [24. 40.]] data[:, :, 1] = [[20. 36.] [24. 40.]]
- ttsv(vector: OneDArray, skip_dim: int | None = None, version: int | None = None) float | np.ndarray | tensor[source]
Tensor times same vector in multiple modes.
See
ttv()for details on multiplication of a tensor with a vector. When skip_dim is provided, multiply the vector by all but dimensions except [0, …, skip_dim].- Parameters:
vector – Vector to multiply by.
skip_dim – Initial dimensions of the tensor to skip when multiplying.
Examples
>>> T = ttb.tensor(np.array([[1, 2], [3, 4]])) >>> T.ttsv(np.ones(2)) 10.0 >>> T.ttsv(np.ones(2), 0) array([3., 7.]) >>> T.ttsv(np.ones(2), 1) array([[1, 2], [3, 4]])
- ttv(vector: np.ndarray | Sequence[np.ndarray], dims: OneDArray | None = None, exclude_dims: OneDArray | None = None) float | tensor[source]
Tensor times vector.
Computes the n-mode product of self with the vector vector; i.e., self x_n vector. The integer n specifies the dimension (or mode) along which the vector should be multiplied. If vector.shape = (I,), then the tensor must have self.shape[n] = I. The result will be the same order and shape as self except that the size of dimension n will be J. The resulting tensor has one less dimension, as dimension n is removed in the multiplication.
Multiplication with more than one vector is provided using a list of vectors and corresponding dimensions in the tensor to use.
The dimensions of the tensor with which to multiply can be provided as dims, or the dimensions to exclude from [0, …, self.ndims] can be specified using exclude_dims.
- Parameters:
vector – Vector or vectors to multiply by.
dims – Dimensions to multiply against.
exclude_dims – Multiply using all dimensions but these.
- Returns:
Tensor product.
Examples
Create 3-way tensor with values 0-7 and multiple by vector of ones along dimension 0:
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> print(T) tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0 2] [1 3]] data[:, :, 1] = [[4 6] [5 7]] >>> T.ttv(np.ones(2), 0) tensor of shape (2, 2) with order F data[:, :] = [[ 1. 9.] [ 5. 13.]]
Multiply along all but dimension 2 using two vectors of ones:
>>> T.ttv([np.ones(2), np.ones(2)], exclude_dims=np.array([1])) tensor of shape (2,) with order F data[:] = [10. 18.]
- tenfun(function_handle: Callable[[np.ndarray, np.ndarray], np.ndarray] | Callable[[np.ndarray], np.ndarray], *inputs: float | int | np.ndarray | ttb.tensor | ttb.ktensor | ttb.ttensor | ttb.sptensor | ttb.sumtensor) ttb.tensor[source]
Apply a function to each element in a tensor or tensors.
See
pyttb.tensor.tensor.tenfun_binary()andpyttb.tensor.tensor.tenfun_unary()for supported options.
- tenfun_binary(function_handle: Callable[[np.ndarray, np.ndarray], np.ndarray], other: ttb.tensor | int | float, first: bool = True) ttb.tensor[source]
Apply a binary operation to two tensors or a tensor and a scalar.
- Parameters:
function_handle – Function to apply.
other – Other input to the binary function.
first – Whether the tensor comes first in the method call (if ordering matters).
Examples
Create a tensor of ones and add it to itself using an add function:
>>> add = lambda x, y: x + y >>> T0 = ttb.tenones((2, 2, 2)) >>> T1 = T0.tenfun_binary(add, T0) >>> T1.isequal(T0 * 2) True
Use the same add function to add a scalar to the original tensor:
>>> T2 = T0.tenfun_binary(add, 1) >>> T2.isequal(T1) True
- tenfun_unary(function_handle: Callable[[ndarray], ndarray], *inputs: tensor) tensor[source]
Apply a unary operation to multiple tensors columnwise.
Examples
Create two tensors with values 0-7 and 7-0 (reversed):
>>> T1 = ttb.tensor(np.arange(8), (2, 2, 2)) >>> print(T1) tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0 2] [1 3]] data[:, :, 1] = [[4 6] [5 7]] >>> T2 = ttb.tensor(np.arange(8)[::-1], (2, 2, 2)) >>> print(T2) tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[7 5] [6 4]] data[:, :, 1] = [[3 1] [2 0]]
Apply an operation columnwise across the tensors:
>>> tensor_max = lambda x: np.max(x, axis=0) >>> T3 = T1.tenfun_unary(tensor_max, T2) >>> print(T3) tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[7. 5.] [6. 4.]] data[:, :, 1] = [[4. 6.] [5. 7.]]
- to_sptensor() sptensor[source]
Construct a
pyttb.sptensorfrom :class:pyttb.tensor.Examples
Construct a 2x2x2 tensor with some nonzero entries:
>>> np.random.seed(3) # reproducibility >>> sprandint = lambda s: np.random.randint(0, 4, size=np.prod(s)) / 4; >>> T = ttb.tensor.from_function(sprandint, (2, 2, 2)) >>> print(T) tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0.5 0.25] [0. 0.75]] data[:, :, 1] = [[0. 0. ] [0. 0.25]]
Convert to a sparse tensor:
>>> S = T.to_sptensor() >>> print(S) sparse tensor of shape (2, 2, 2) with 4 nonzeros and order F [0, 0, 0] = 0.5 [0, 1, 0] = 0.25 [1, 1, 0] = 0.75 [1, 1, 1] = 0.25
- to_tenmat(rdims: np.ndarray | None = None, cdims: np.ndarray | None = None, cdims_cyclic: Literal['fc'] | Literal['bc'] | Literal['t'] | None = None, copy: bool = True) ttb.tenmat[source]
Construct a
pyttb.tenmatfrom apyttb.tensor.- Parameters:
rdims – Mapping of row indices.
cdims – Mapping of column indices.
cdims_cyclic – When only rdims is specified maps a single rdim to the rows and the remaining dimensions span the columns. _fc_ (forward cyclic) in the order range(rdims,self.ndims()) followed by range(0, rdims). _bc_ (backward cyclic) range(rdims-1, -1, -1) then range(self.ndims(), rdims, -1).
copy – Whether to make a copy of provided data or just reference it.
Notes
Forward cyclic is defined by Kiers [1] and backward cyclic is defined by De Lathauwer, De Moor, and Vandewalle [2].
References
Examples
Create a
pyttb.tensor:>>> tshape = (2, 2, 2) >>> data = np.reshape(np.arange(prod(tshape)), tshape) >>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> print(T) tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0 2] [1 3]] data[:, :, 1] = [[4 6] [5 7]]
Convert to a
pyttb.tenmatunwrapping around the first dimension. Either allow for implicit column or explicit column dimension specification:>>> TM1 = T.to_tenmat(rdims=np.array([0])) >>> TM2 = T.to_tenmat(rdims=np.array([0]), cdims=np.array([1, 2])) >>> TM1.isequal(TM2) True
Convert using cyclic column ordering. For the three mode case _fc_ is the same result:
>>> TM3 = T.to_tenmat(rdims=np.array([0]), cdims_cyclic="fc") >>> TM3 matrix corresponding to a tensor of shape (2, 2, 2) with order F rindices = [ 0 ] (modes of tensor corresponding to rows) cindices = [ 1, 2 ] (modes of tensor corresponding to columns) data[:, :] = [[0 2 4 6] [1 3 5 7]]
Backwards cyclic reverses the order:
>>> TM4 = T.to_tenmat(rdims=np.array([0]), cdims_cyclic="bc") >>> TM4 matrix corresponding to a tensor of shape (2, 2, 2) with order F rindices = [ 0 ] (modes of tensor corresponding to rows) cindices = [ 2, 1 ] (modes of tensor corresponding to columns) data[:, :] = [[0 4 2 6] [1 5 3 7]]
- __setitem__(key, value)[source]
Subscripted assignment for a tensor.
We can assign elements to a tensor in three ways.
Case 1: T[R1,R2,…,Rn] = Y, in which case we replace the rectangular subtensor (or single element) specified by the ranges R1,…,`Rn` with Y. The right-hand-side can be a scalar, a tensor, or a
numpy.ndarray.Case 2a: T[S] = V, where S is a p x n array of subscripts and V is a scalar or a vector containing p values.
Case 2b: T[I] = V, where I is a set of p linear indices and V is a scalar or a vector containing p values. Resizing is not allowed in this case.
Examples
>>> T = tenones((3, 4, 2)) >>> # replaces subtensor >>> T[0:2, 0:2, 0] = np.ones((2, 2)) >>> # replaces two elements >>> T[np.array([[1, 1, 1], [1, 1, 2]])] = [5, 7] >>> # replaces two elements with linear indices >>> T[np.array([1, 13])] = [5, 7] >>> # grows tensor to accept new element >>> T[1, 1, 2:3] = 1 >>> T[1, 1, 4] = 1
- __getitem__(item)[source]
Subscripted reference for tensors.
We can extract elements or subtensors from a tensor in the following ways.
Case 1a: y = T[I1,I2,…,In], where each I is an index, returns a scalar.
Case 1b: Y = T[R1,R2,…,Rn], where one or more R is a range and the rest are indices, returns a tensor.
Case 2a: V = T[S] where S is a p x n array of subscripts, returns a vector of p values.
Case 2b: V = T[I] where I is a set of p linear indices, returns a vector of p values.
Any ambiguity results in executing the first valid case. This is particularly an issue if self.ndims == 1.
Examples
>>> T = tenones((3, 4, 2, 1)) >>> T[0, 0, 0, 0] # produces a scalar 1.0 >>> # produces a tensor of order 1 and size 1 >>> T[1, 1, 1, :] tensor of shape (1,) with order F data[:] = [1.] >>> # produces a tensor of size 2 x 2 x 1 >>> T[0:2, [2, 3], 1, :] tensor of shape (2, 2, 1) with order F data[:, :, 0] = [[1. 1.] [1. 1.]] >>> # returns a vector of length 2 >>> # Equivalent to selecting [0, 0, 0, 0] and [1, 1, 1 ,0] separately >>> T[np.array([[0, 0, 0, 0], [1, 1, 1, 0]])] array([1., 1.]) >>> # extracts the first three linearized indices >>> T[[0, 1, 2]] array([1., 1., 1.])
- __eq__(other)[source]
Equal for tensors (element-wise).
- Parameters:
other (
pyttb.tensor, float, int)- Returns:
pyttb.tensorof bool.
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> T == T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[ True True] [ True True]] data[:, :, 1] = [[ True True] [ True True]] >>> T == 1 tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[False False] [ True False]] data[:, :, 1] = [[False False] [False False]]
- __ne__(other)[source]
Not equal (!=) for tensors (element-wise).
- Parameters:
other (
pyttb.tensor, float, int)- Returns:
pyttb.tensorof bool.
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> T != T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[False False] [False False]] data[:, :, 1] = [[False False] [False False]] >>> T != 1 tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[ True True] [False True]] data[:, :, 1] = [[ True True] [ True True]]
- __ge__(other)[source]
Greater than or equal (>=) for tensors (element-wise).
- Parameters:
other (
pyttb.tensor, float, int)- Returns:
pyttb.tensorof bool.
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> T >= T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[ True True] [ True True]] data[:, :, 1] = [[ True True] [ True True]] >>> T >= 1 tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[False True] [ True True]] data[:, :, 1] = [[ True True] [ True True]]
- __le__(other)[source]
Less than or equal (<=) for tensors (element-wise).
- Parameters:
other (
pyttb.tensor, float, int)- Returns:
pyttb.tensorof bool.
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> T <= T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[ True True] [ True True]] data[:, :, 1] = [[ True True] [ True True]] >>> T <= 1 tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[ True False] [ True False]] data[:, :, 1] = [[False False] [False False]]
- __gt__(other)[source]
Greater than (>) for tensors (element-wise).
- Parameters:
other (
pyttb.tensor, float, int)- Returns:
pyttb.tensorof bool.
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> T > T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[False False] [False False]] data[:, :, 1] = [[False False] [False False]] >>> T > 1 tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[False True] [False True]] data[:, :, 1] = [[ True True] [ True True]]
- __lt__(other)[source]
Less than (<) for tensors (element-wise).
- Parameters:
other (
pyttb.tensor, float, int)- Returns:
pyttb.tensorof bool.
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> T < T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[False False] [False False]] data[:, :, 1] = [[False False] [False False]] >>> T < 1 tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[ True False] [False False]] data[:, :, 1] = [[False False] [False False]]
- __sub__(other)[source]
Binary subtraction (-) for tensors.
- Parameters:
other (
pyttb.tensor, float, int)- Returns:
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> T - T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0 0] [0 0]] data[:, :, 1] = [[0 0] [0 0]] >>> T - 1 tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[-1 1] [ 0 2]] data[:, :, 1] = [[3 5] [4 6]]
- __add__(other)[source]
Binary addition (+) for tensors.
- Parameters:
other (
pyttb.tensor, float, int)- Returns:
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> T + T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0 4] [2 6]] data[:, :, 1] = [[ 8 12] [10 14]] >>> T + 1 tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[1 3] [2 4]] data[:, :, 1] = [[5 7] [6 8]]
- __radd__(other)[source]
Right binary addition (+) for tensors.
- Parameters:
other (
pyttb.tensor, float, int)- Returns:
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> 1 + T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[1 3] [2 4]] data[:, :, 1] = [[5 7] [6 8]]
- __pow__(power)[source]
Element-wise Power (**) for tensors.
- Parameters:
other (
pyttb.tensor, float, int)- Returns:
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> T**2 tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0 4] [1 9]] data[:, :, 1] = [[16 36] [25 49]]
- __mul__(other)[source]
Element-wise multiplication (*) for tensors.
- Parameters:
other (
pyttb.tensor, float, int)- Returns:
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> T * T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0 4] [1 9]] data[:, :, 1] = [[16 36] [25 49]] >>> T * 2 tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0 4] [2 6]] data[:, :, 1] = [[ 8 12] [10 14]]
- __rmul__(other)[source]
Elementwise right multiplication (*) for tensors.
- Parameters:
other (
pyttb.tensor, float, int)- Returns:
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> 2 * T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0 4] [2 6]] data[:, :, 1] = [[ 8 12] [10 14]]
- __truediv__(other)[source]
Element-wise left division (/) for tensors.
- Parameters:
other (
pyttb.tensor, float, int)- Returns:
Examples
>>> T = ttb.tensor(np.arange(8) + 1, (2, 2, 2)) >>> T / T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[1. 1.] [1. 1.]] data[:, :, 1] = [[1. 1.] [1. 1.]] >>> T / 2 tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0.5 1.5] [1. 2. ]] data[:, :, 1] = [[2.5 3.5] [3. 4. ]]
- __rtruediv__(other)[source]
Element wise right division (/) for tensors.
- Parameters:
other (
pyttb.tensor, float, int)- Returns:
Examples
>>> T = ttb.tensor(np.arange(8) + 11, (2, 2, 2)) >>> 1 / T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0.0909... 0.0769...] [0.0833... 0.0714...]] data[:, :, 1] = [[0.0666... 0.0588...] [0.0625... 0.0555...]]
- __pos__()[source]
Unary plus (+) for tensors.
- Returns:
Copy of tensor.
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> +T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0 2] [1 3]] data[:, :, 1] = [[4 6] [5 7]]
- __neg__()[source]
Unary minus (-) for tensors.
- Returns:
Copy of negated tensor.
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> -T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[ 0 -2] [-1 -3]] data[:, :, 1] = [[-4 -6] [-5 -7]]
- __repr__()[source]
Return string representation of the tensor.
- Returns:
String displaying shape and data as strings on different lines.
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0 2] [1 3]] data[:, :, 1] = [[4 6] [5 7]]
- __str__()
Return string representation of the tensor.
- Returns:
String displaying shape and data as strings on different lines.
Examples
>>> T = ttb.tensor(np.arange(8), (2, 2, 2)) >>> T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0 2] [1 3]] data[:, :, 1] = [[4 6] [5 7]]
- __hash__ = None
- pyttb.tendiag(elements: OneDArray, shape: Shape | None = None, order: MemoryLayout = 'F') tensor[source]
Create a tensor with elements along super diagonal.
If provided shape is too small the tensor will be enlarged to accommodate.
- Parameters:
elements – Elements to set along the diagonal.
shape – Shape of resulting tensor.
order – Memory layout for resulting tensor.
- Returns:
Constructed tensor.
Examples
>>> diagonal_values = np.ones(3) >>> T = ttb.tendiag(diagonal_values) >>> T tensor of shape (3, 3, 3) with order F data[:, :, 0] = [[1. 0. 0.] [0. 0. 0.] [0. 0. 0.]] data[:, :, 1] = [[0. 0. 0.] [0. 1. 0.] [0. 0. 0.]] data[:, :, 2] = [[0. 0. 0.] [0. 0. 0.] [0. 0. 1.]] >>> # dimensions enlarged to match length of diagonal_values >>> T2 = ttb.tendiag(diagonal_values, (1, 2, 3)) >>> T.isequal(T2) True
- pyttb.teneye(ndims: int, size: int, order: Literal['F', 'C'] = 'F') tensor[source]
Create identity tensor of specified shape.
T is an identity tensor if T.ttsv(x, skip_dim=0) = x for all x such that norm(x) == 1.
An identity tensor only exists if
ndimsis even. This method is resource intensive for even moderate orders or sizes (>=6).- Parameters:
ndims – Number of dimensions of tensor.
size – Number of elements in any dimension of the tensor.
order – Memory layout for resulting tensor.
- Returns:
Identity tensor.
Examples
>>> T = ttb.teneye(ndims=4, size=2) >>> T tensor of shape (2, 2, 2, 2) with order F data[:, :, 0, 0] = [[1. 0. ] [0. 0.3333...]] data[:, :, 1, 0] = [[0. 0.3333...] [0.3333... 0. ]] data[:, :, 0, 1] = [[0. 0.3333...] [0.3333... 0. ]] data[:, :, 1, 1] = [[0.3333... 0. ] [0. 1. ]] >>> # check identity tensor using ttsv method and unit vector x >>> x = np.ones(2) >>> x /= np.linalg.norm(x) >>> np.allclose(T.ttsv(x, 0), x) True
- pyttb.tenones(shape: int | Iterable[int], order: Literal['F', 'C'] = 'F') tensor[source]
Create a tensor of all ones.
- Parameters:
shape – Shape of resulting tensor.
order – Memory layout for resulting tensor.
- Returns:
Constructed tensor.
Examples
>>> T = ttb.tenones((3,)) >>> T tensor of shape (3,) with order F data[:] = [1. 1. 1.] >>> T = ttb.tenones((3, 3)) >>> T tensor of shape (3, 3) with order F data[:, :] = [[1. 1. 1.] [1. 1. 1.] [1. 1. 1.]]
- pyttb.tenrand(shape: int | Iterable[int], order: Literal['F', 'C'] = 'F') tensor[source]
Create a tensor with entries drawn from a uniform distribution on [0, 1].
- Parameters:
shape – Shape of resulting tensor.
order – Memory layout for resulting tensor.
- Returns:
Constructed tensor.
Examples
>>> np.random.seed(1) >>> T = ttb.tenrand((2, 2, 2)) >>> T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[4.1702...e-01 1.1437...e-04] [7.2032...e-01 3.0233...e-01]] data[:, :, 1] = [[0.1467... 0.1862...] [0.0923... 0.3455...]]
- pyttb.tenzeros(shape: int | Iterable[int], order: Literal['F', 'C'] = 'F') tensor[source]
Create a tensor of all zeros.
- Parameters:
shape – Shape of resulting tensor.
order – Memory layout for resulting tensor.
- Returns:
Constructed tensor.
Examples
>>> T = ttb.tenzeros((2, 2, 2)) >>> T tensor of shape (2, 2, 2) with order F data[:, :, 0] = [[0. 0.] [0. 0.]] data[:, :, 1] = [[0. 0.] [0. 0.]]