Converting a Tensor to a Matrix and Vice Versa

We show how to convert a tensor to a matrix stored with extra information so that it can be converted back to a tensor. Converting to a matrix requies an ordered mapping of the tensor indices to the rows and the columns of the matrix.

Contents

Creating a tenmat (tensor as matrix) object

X = tensor(1:24,[3 2 2 2]) %<-- Create a tensor.
X is a tensor of size 3 x 2 x 2 x 2
	X(:,:,1,1) = 
	     1     4
	     2     5
	     3     6
	X(:,:,2,1) = 
	     7    10
	     8    11
	     9    12
	X(:,:,1,2) = 
	    13    16
	    14    17
	    15    18
	X(:,:,2,2) = 
	    19    22
	    20    23
	    21    24
A = tenmat(X,[1 2],[3 4]) %<-- Dims [1 2] map to rows, [3 4] to columns.
A is a matrix corresponding to a tensor of size 3 x 2 x 2 x 2
	A.rindices = [ 1  2 ] (modes of tensor corresponding to rows)
	A.cindices = [ 3  4 ] (modes of tensor corresponding to columns)
	A.data = 
		     1     7    13    19
		     2     8    14    20
		     3     9    15    21
		     4    10    16    22
		     5    11    17    23
		     6    12    18    24
B = tenmat(X,[2 1],[3 4]) %<-- Order matters!
B is a matrix corresponding to a tensor of size 3 x 2 x 2 x 2
	B.rindices = [ 2  1 ] (modes of tensor corresponding to rows)
	B.cindices = [ 3  4 ] (modes of tensor corresponding to columns)
	B.data = 
		     1     7    13    19
		     4    10    16    22
		     2     8    14    20
		     5    11    17    23
		     3     9    15    21
		     6    12    18    24
C = tenmat(X,[1 2],[4 3]) %<-- Order matters!
C is a matrix corresponding to a tensor of size 3 x 2 x 2 x 2
	C.rindices = [ 1  2 ] (modes of tensor corresponding to rows)
	C.cindices = [ 4  3 ] (modes of tensor corresponding to columns)
	C.data = 
		     1    13     7    19
		     2    14     8    20
		     3    15     9    21
		     4    16    10    22
		     5    17    11    23
		     6    18    12    24

Creating a tenmat by specifying the dimensions mapped to the rows

If just the row indices are specified, then the columns are arranged in increasing order.

A = tenmat(X,1) %<-- Same as A = tenmat(X,1,2:4)
A is a matrix corresponding to a tensor of size 3 x 2 x 2 x 2
	A.rindices = [ 1 ] (modes of tensor corresponding to rows)
	A.cindices = [ 2  3  4 ] (modes of tensor corresponding to columns)
	A.data = 
		     1     4     7    10    13    16    19    22
		     2     5     8    11    14    17    20    23
		     3     6     9    12    15    18    21    24

Creating a tenmat by specifying the dimensions mapped to the columns

Likewise, just the columns can be specified if the 3rd argument is a 't'. The rows are arranged in increasing order.

A = tenmat(X, [2 3], 't') %<-- Same as A = tenmat(X,[1 4],[2 3]).
A is a matrix corresponding to a tensor of size 3 x 2 x 2 x 2
	A.rindices = [ 1  4 ] (modes of tensor corresponding to rows)
	A.cindices = [ 2  3 ] (modes of tensor corresponding to columns)
	A.data = 
		     1     4     7    10
		     2     5     8    11
		     3     6     9    12
		    13    16    19    22
		    14    17    20    23
		    15    18    21    24

Vectorize via tenmat

All the dimensions can be mapped to the rows or the columnns.

A = tenmat(X,1:4,'t') %<-- Map all the dimensions to the columns
A is a matrix corresponding to a tensor of size 3 x 2 x 2 x 2
	A.rindices = [  ] (modes of tensor corresponding to rows)
	A.cindices = [ 1  2  3  4 ] (modes of tensor corresponding to columns)
	A.data = 
		  Columns 1 through 13
		     1     2     3     4     5     6     7     8     9    10    11    12    13
		  Columns 14 through 24
		    14    15    16    17    18    19    20    21    22    23    24

Alternative ordering for the columns for mode-n matricization

Mode-n matricization means that only mode n is mapped to the rows. Different column orderings are available.

A = tenmat(X,2) %<-- By default, columns are ordered as [1 3 4].
A is a matrix corresponding to a tensor of size 3 x 2 x 2 x 2
	A.rindices = [ 2 ] (modes of tensor corresponding to rows)
	A.cindices = [ 1  3  4 ] (modes of tensor corresponding to columns)
	A.data = 
		     1     2     3     7     8     9    13    14    15    19    20    21
		     4     5     6    10    11    12    16    17    18    22    23    24
A = tenmat(X,2,[3 1 4]) %<-- Explicit specification.
A is a matrix corresponding to a tensor of size 3 x 2 x 2 x 2
	A.rindices = [ 2 ] (modes of tensor corresponding to rows)
	A.cindices = [ 3  1  4 ] (modes of tensor corresponding to columns)
	A.data = 
		     1     7     2     8     3     9    13    19    14    20    15    21
		     4    10     5    11     6    12    16    22    17    23    18    24
A = tenmat(X,2,'fc') %<-- Forward cyclic, i.e., [3 4 1].
A is a matrix corresponding to a tensor of size 3 x 2 x 2 x 2
	A.rindices = [ 2 ] (modes of tensor corresponding to rows)
	A.cindices = [ 3  4  1 ] (modes of tensor corresponding to columns)
	A.data = 
		     1     7    13    19     2     8    14    20     3     9    15    21
		     4    10    16    22     5    11    17    23     6    12    18    24
A = tenmat(X,2,'bc') %<-- Backward cyclic, i.e., [1 4 3].
A is a matrix corresponding to a tensor of size 3 x 2 x 2 x 2
	A.rindices = [ 2 ] (modes of tensor corresponding to rows)
	A.cindices = [ 1  4  3 ] (modes of tensor corresponding to columns)
	A.data = 
		     1     2     3    13    14    15     7     8     9    19    20    21
		     4     5     6    16    17    18    10    11    12    22    23    24

Constituent parts of a tenmat

A.data %<-- The matrix itself.
ans =
     1     2     3    13    14    15     7     8     9    19    20    21
     4     5     6    16    17    18    10    11    12    22    23    24
A.tsize %<-- Size of the original tensor.
ans =
     3     2     2     2
A.rdims %<-- Dimensions that were mapped to the rows.
ans =
     2
A.cdims %<-- Dimensions that were mapped to the columns.
ans =
     1     4     3

Creating a tenmat from its constituent parts

B = tenmat(A.data,A.rdims,A.cdims,A.tsize) %<-- Recreates A
B is a matrix corresponding to a tensor of size 3 x 2 x 2 x 2
	B.rindices = [ 2 ] (modes of tensor corresponding to rows)
	B.cindices = [ 1  4  3 ] (modes of tensor corresponding to columns)
	B.data = 
		     1     2     3    13    14    15     7     8     9    19    20    21
		     4     5     6    16    17    18    10    11    12    22    23    24

Creating an empty tenmat

B = tenmat %<-- Empty tenmat.
B is a matrix corresponding to a tensor of size [empty tensor]
	B.rindices = [  ] (modes of tensor corresponding to rows)
	B.cindices = [  ] (modes of tensor corresponding to columns)
	B.data = []

Use double to convert a tenmat to a MATLAB matrix

double(A) %<-- converts A to a standard matrix
ans =
     1     2     3    13    14    15     7     8     9    19    20    21
     4     5     6    16    17    18    10    11    12    22    23    24

Use tensor to convert a tenmat to a tensor

Y = tensor(A)
Y is a tensor of size 3 x 2 x 2 x 2
	Y(:,:,1,1) = 
	     1     4
	     2     5
	     3     6
	Y(:,:,2,1) = 
	     7    10
	     8    11
	     9    12
	Y(:,:,1,2) = 
	    13    16
	    14    17
	    15    18
	Y(:,:,2,2) = 
	    19    22
	    20    23
	    21    24

Use size and tsize for the dimensions of a tenmat

size(A) %<-- Matrix size
tsize(A) %<-- Corresponding tensor size
ans =
     2    12
ans =
     3     2     2     2

Subscripted reference for a tenmat

A(2,1) %<-- returns the (2,1) element of the matrix.
ans =
     4

Subscripted assignment for a tenmat

A(1:2,1:2) = ones(2) %<-- Replace part of the matrix.
A is a matrix corresponding to a tensor of size 3 x 2 x 2 x 2
	A.rindices = [ 2 ] (modes of tensor corresponding to rows)
	A.cindices = [ 1  4  3 ] (modes of tensor corresponding to columns)
	A.data = 
		     1     1     3    13    14    15     7     8     9    19    20    21
		     1     1     6    16    17    18    10    11    12    22    23    24

Use end for the last index

A(end,end) %<-- Same as X(2,12)
ans =
    24

Basic operations for tenmat

norm(A) %<-- Norm of the matrix.
ans =
   69.6994
A' %<-- Calls ctranspose (also swaps mapped dimensions).
ans is a matrix corresponding to a tensor of size 3 x 2 x 2 x 2
	ans.rindices = [ 1  4  3 ] (modes of tensor corresponding to rows)
	ans.cindices = [ 2 ] (modes of tensor corresponding to columns)
	ans.data = 
		     1     1
		     1     1
		     3     6
		    13    16
		    14    17
		    15    18
		     7    10
		     8    11
		     9    12
		    19    22
		    20    23
		    21    24
+A %<-- Calls uplus.
ans is a matrix corresponding to a tensor of size 3 x 2 x 2 x 2
	ans.rindices = [ 2 ] (modes of tensor corresponding to rows)
	ans.cindices = [ 1  4  3 ] (modes of tensor corresponding to columns)
	ans.data = 
		     1     1     3    13    14    15     7     8     9    19    20    21
		     1     1     6    16    17    18    10    11    12    22    23    24
-A %<-- Calls uminus.
ans is a matrix corresponding to a tensor of size 3 x 2 x 2 x 2
	ans.rindices = [ 2 ] (modes of tensor corresponding to rows)
	ans.cindices = [ 1  4  3 ] (modes of tensor corresponding to columns)
	ans.data = 
		    -1    -1    -3   -13   -14   -15    -7    -8    -9   -19   -20   -21
		    -1    -1    -6   -16   -17   -18   -10   -11   -12   -22   -23   -24
A+A %<-- Calls plus.
ans is a matrix corresponding to a tensor of size 3 x 2 x 2 x 2
	ans.rindices = [ 2 ] (modes of tensor corresponding to rows)
	ans.cindices = [ 1  4  3 ] (modes of tensor corresponding to columns)
	ans.data = 
		     2     2     6    26    28    30    14    16    18    38    40    42
		     2     2    12    32    34    36    20    22    24    44    46    48
A-A %<-- Calls minus.
ans is a matrix corresponding to a tensor of size 3 x 2 x 2 x 2
	ans.rindices = [ 2 ] (modes of tensor corresponding to rows)
	ans.cindices = [ 1  4  3 ] (modes of tensor corresponding to columns)
	ans.data = 
		     0     0     0     0     0     0     0     0     0     0     0     0
		     0     0     0     0     0     0     0     0     0     0     0     0

Multiplying two tenmats

It is possible to compute the product of two tenmats and have a result that can be converted into a tensor.

B = A * A' %<-- Tenmat that is the product of two tenmats.
B is a matrix corresponding to a tensor of size 2 x 2
	B.rindices = [ 1 ] (modes of tensor corresponding to rows)
	B.cindices = [ 2 ] (modes of tensor corresponding to columns)
	B.data = 
		        1997        2384
		        2384        2861
tensor(B) %<-- Corresponding tensor.
ans is a tensor of size 2 x 2
	ans(:,:) = 
	        1997        2384
	        2384        2861

Displaying a tenmat

Shows the original tensor dimensions, the modes mapped to rows, the modes mapped to columns, and the matrix.

disp(A)
ans is a matrix corresponding to a tensor of size 3 x 2 x 2 x 2
	ans.rindices = [ 2 ] (modes of tensor corresponding to rows)
	ans.cindices = [ 1  4  3 ] (modes of tensor corresponding to columns)
	ans.data = 
		     1     1     3    13    14    15     7     8     9    19    20    21
		     1     1     6    16    17    18    10    11    12    22    23    24