# 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
- Creating a tenmat by specifying the dimensions mapped to the rows
- Creating a tenmat by specifying the dimensions mapped to the columns
- Vectorize via tenmat
- Alternative ordering for the columns for mode-n matricization
- Constituent parts of a tenmat
- Creating a tenmat from its constituent parts
- Creating an empty tenmat
- Use double to convert a tenmat to a MATLAB matrix
- Use tensor to convert a tenmat to a tensor
- Use size and tsize for the dimensions of a tenmat
- Subscripted reference for a tenmat
- Subscripted assignment for a tenmat
- Use end for the last index
- Basic operations for tenmat
- Multiplying two tenmats
- Displaying a tenmat

## 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