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

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