# Multiplying Tensors

## Tensor times vector (ttv for tensor)

Compute a tensor times a vector (or vectors) in one (or more) modes.

```rand('state',0);
X = tenrand([5,3,4,2]); %<-- Create a dense tensor.
A = rand(5,1); B = rand(3,1); C = rand(4,1); D = rand(2,1); %<-- Some vectors.
```
```Y = ttv(X, A, 1) %<-- X times A in mode 1.
```
```Y is a tensor of size 3 x 4 x 2
Y(:,:,1) =
1.6875    1.9480    0.9951    0.9505
0.8258    0.9495    1.4104    0.6771
1.4496    0.8295    1.5943    1.6259
Y(:,:,2) =
1.8369    1.3352    1.0743    1.4354
1.0471    1.2250    1.5317    1.2519
1.4225    1.2897    1.1595    0.5775
```
```Y = ttv(X, {A,B,C,D}, 1) %<-- Same as above.
```
```Y is a tensor of size 3 x 4 x 2
Y(:,:,1) =
1.6875    1.9480    0.9951    0.9505
0.8258    0.9495    1.4104    0.6771
1.4496    0.8295    1.5943    1.6259
Y(:,:,2) =
1.8369    1.3352    1.0743    1.4354
1.0471    1.2250    1.5317    1.2519
1.4225    1.2897    1.1595    0.5775
```
```Y = ttv(X, {A,B,C,D}, [1 2 3 4]) %<-- All-mode multiply produces a scalar.
```
```Y =
7.8707
```
```Y = ttv(X, {D,C,B,A}, [4 3 2 1]) %<-- Same as above.
```
```Y =
7.8707
```
```Y = ttv(X, {A,B,C,D}) %<-- Same as above.
```
```Y =
7.8707
```
```Y = ttv(X, {C,D}, [3 4]) %<-- X times C in mode-3 & D in mode-4.
```
```Y is a tensor of size 5 x 3
Y(:,:) =
1.0157    1.1081    1.5654
1.3799    1.2137    1.0599
1.5625    1.1830    1.0658
1.2323    1.2410    1.4481
1.4374    0.9573    0.8644
```
```Y = ttv(X, {A,B,C,D}, [3 4]) %<-- Same as above.
```
```Y is a tensor of size 5 x 3
Y(:,:) =
1.0157    1.1081    1.5654
1.3799    1.2137    1.0599
1.5625    1.1830    1.0658
1.2323    1.2410    1.4481
1.4374    0.9573    0.8644
```
```Y = ttv(X, {A,B,D}, [1 2 4]) %<-- 3-way multiplication.
```
```Y is a tensor of size 4
Y(:) =
4.9369
4.5013
4.4941
3.8857
```
```Y = ttv(X, {A,B,C,D}, [1 2 4]) %<-- Same as above.
```
```Y is a tensor of size 4
Y(:) =
4.9369
4.5013
4.4941
3.8857
```
```Y = ttv(X, {A,B,D}, -3) %<-- Same as above.
```
```Y is a tensor of size 4
Y(:) =
4.9369
4.5013
4.4941
3.8857
```
```Y = ttv(X, {A,B,C,D}, -3) %<-- Same as above.
```
```Y is a tensor of size 4
Y(:) =
4.9369
4.5013
4.4941
3.8857
```

## Sparse tensor times vector (ttv for sptensor)

This is the same as in the dense case, except that the result may be either dense or sparse (or a scalar).

```X = sptenrand([5,3,4,2],5); %<-- Create a sparse tensor.
```
```Y = ttv(X, A, 1) %<-- X times A in mode 1. Result is sparse.
```
```Y is a sparse tensor of size 3 x 4 x 2 with 5 nonzeros
(1,3,1)    0.0014
(2,2,1)    0.3357
(3,1,1)    0.5973
(3,1,2)    0.0005
(3,3,1)    0.0039
```
```Y = ttv(X, {A,B,C,D}, [1 2 3 4]) %<-- All-mode multiply.
```
```Y =
0.1196
```
```Y = ttv(X, {C,D}, [3 4]) %<-- X times C in mode-3 & D in mode-4.
```
```Y is a sparse tensor of size 5 x 3 with 5 nonzeros
(2,3)    0.0009
(3,2)    0.0612
(3,3)    0.0959
(4,1)    0.0064
(4,3)    0.0149
```
```Y = ttv(X, {A,B,D}, -3) %<-- 3-way multiplication. Result is *dense*!
```
```Y is a tensor of size 4
Y(:) =
0.1512
0.1064
0.0014
0
```

## Kruskal tensor times vector (ttv for ktensor)

The special structure of a ktensor allows an efficient implementation of vector multiplication. The result is a ktensor or a scalar.

```X = ktensor([10;1],rand(5,2),rand(3,2),rand(4,2),rand(2,2)); %<-- Ktensor.
Y = ttv(X, A, 1) %<-- X times A in mode 1. Result is a ktensor.
```
```Y is a ktensor of size 3 x 4 x 2
Y.lambda =
5.9997    1.1433
Y.U{1} =
0.6927    0.4418
0.0841    0.3533
0.4544    0.1536
Y.U{2} =
0.6756    0.5548
0.6992    0.1210
0.7275    0.4508
0.4784    0.7159
Y.U{3} =
0.8928    0.2548
0.2731    0.8656
```
```norm(full(Y) - ttv(full(X),A,1)) %<-- Result is the same as dense case.
```
```ans =
7.0654e-16
```
```Y = ttv(X, {A,B,C,D}) %<-- All-mode multiply -- scalar result.
```
```Y =
4.8677
```
```Y = ttv(X, {C,D}, [3 4]) %<-- X times C in mode-3 & D in mode-4.
```
```Y is a ktensor of size 5 x 3
Y.lambda =
6.0729    0.7856
Y.U{1} =
0.6124    0.5869
0.6085    0.0576
0.0158    0.3676
0.0164    0.6315
0.1901    0.7176
Y.U{2} =
0.6927    0.4418
0.0841    0.3533
0.4544    0.1536
```
```Y = ttv(X, {A,B,D}, [1 2 4]) %<-- 3-way multiplication.
```
```Y is a ktensor of size 4
Y.lambda =
3.6628    0.9389
Y.U{1} =
0.6756    0.5548
0.6992    0.1210
0.7275    0.4508
0.4784    0.7159
```

## Tucker tensor times vector (ttv for ttensor)

The special structure of a ttensor allows an efficient implementation of vector multiplication. The result is a ttensor or a scalar.

```X = ttensor(tenrand([2,2,2,2]),rand(5,2),rand(3,2),rand(4,2),rand(2,2));
Y = ttv(X, A, 1) %<-- X times A in mode 1.
```
```Y is a ttensor of size 3 x 4 x 2
Y.core is a tensor of size 2 x 2 x 2
Y.core(:,:,1) =
1.3171    0.2658
1.0694    0.9612
Y.core(:,:,2) =
1.3377    1.4308
0.3816    0.7186
Y.U{1} =
0.8729    0.9669
0.2379    0.6649
0.6458    0.8704
Y.U{2} =
0.0099    0.8903
0.1370    0.7349
0.8188    0.6873
0.4302    0.3461
Y.U{3} =
0.1660    0.1911
0.1556    0.4225
```
```norm(full(Y) - ttv(full(X),A, 1)) %<-- Same as dense case.
```
```ans =
6.2311e-16
```
```Y = ttv(X, {A,B,C,D}, [1 2 3 4]) %<-- All-mode multiply -- scalar result.
```
```Y =
3.8758
```
```Y = ttv(X, {C,D}, [3 4]) %<-- X times C in mode-3 & D in mode-4.
```
```Y is a ttensor of size 5 x 3
Y.core is a tensor of size 2 x 2
Y.core(:,:) =
0.6489    0.3358
0.5348    0.3779
Y.U{1} =
0.3651    0.4586
0.3932    0.8699
0.5915    0.9342
0.1197    0.2644
0.0381    0.1603
Y.U{2} =
0.8729    0.9669
0.2379    0.6649
0.6458    0.8704
```
```Y = ttv(X, {A,B,D}, [1 2 4]) %<-- 3-way multiplication.
```
```Y is a ttensor of size 4
Y.core is a tensor of size 2
Y.core(:) =
2.3205
2.3598
Y.U{1} =
0.0099    0.8903
0.1370    0.7349
0.8188    0.6873
0.4302    0.3461
```

## Tensor times matrix (ttm for tensor)

Compute a tensor times a matrix (or matrices) in one (or more) modes.

```X = tensor(rand(5,3,4,2));
A = rand(4,5); B = rand(4,3); C = rand(3,4); D = rand(3,2);
```
```Y = ttm(X, A, 1);         %<-- X times A in mode-1.
Y = ttm(X, {A,B,C,D}, 1); %<-- Same as above.
Y = ttm(X, A', 1, 't')    %<-- Same as above.
```
```Y is a tensor of size 4 x 3 x 4 x 2
Y(:,:,1,1) =
1.0365    0.6095    0.7110
1.9302    1.4742    2.0003
1.7555    1.2961    1.7017
1.8896    1.4325    1.5902
Y(:,:,2,1) =
0.6694    0.9350    0.8098
1.4311    2.0724    1.5604
1.2080    1.5796    1.4965
1.2773    1.7966    1.4659
Y(:,:,3,1) =
1.1284    1.1872    1.2511
1.8427    1.8095    1.8762
1.6982    1.5964    1.5908
1.8864    1.8810    1.8543
Y(:,:,4,1) =
0.9565    1.0452    0.8766
1.7992    1.8762    1.8659
1.4832    1.6716    1.9043
1.6718    1.8121    1.7510
Y(:,:,1,2) =
1.1974    0.8965    0.8668
1.5665    2.1589    1.3825
1.3373    2.0494    1.1534
1.5943    2.0267    1.4569
Y(:,:,2,2) =
1.0229    1.3605    1.0827
2.3149    2.1127    1.9503
2.1861    1.8910    1.5869
2.0542    1.9491    1.9094
Y(:,:,3,2) =
0.7033    0.8874    0.5347
1.4749    1.4350    1.3381
1.5048    1.3274    1.2796
1.2465    1.5395    1.1617
Y(:,:,4,2) =
1.3135    0.2809    0.9096
2.4720    1.0792    1.5503
2.2423    0.9677    1.1401
2.3171    0.8680    1.4500
```
```Y = ttm(X, {A,B,C,D}, [1 2 3 4]); %<-- 4-way mutliply.
Y = ttm(X, {D,C,B,A}, [4 3 2 1]); %<-- Same as above.
Y = ttm(X, {A,B,C,D});            %<-- Same as above.
Y = ttm(X, {A',B',C',D'}, 't')    %<-- Same as above.
```
```Y is a tensor of size 4 x 4 x 3 x 3
Y(:,:,1,1) =
2.4869    4.5774    4.3080    2.4909
4.7042    8.5104    8.0518    4.6694
4.1588    7.5379    7.1537    4.1590
4.4802    8.1581    7.6647    4.4226
Y(:,:,2,1) =
2.4107    4.4549    4.1826    2.4144
4.8310    8.7053    8.2015    4.7393
4.2267    7.6101    7.2157    4.1903
4.4979    8.1691    7.6629    4.4153
Y(:,:,3,1) =
1.8798    3.4093    3.2097    1.8545
3.3879    6.1536    5.8167    3.3717
3.0143    5.4614    5.1902    3.0207
3.2654    5.9270    5.5773    3.2215
Y(:,:,1,2) =
1.4376    2.7014    2.5398    1.4693
2.7470    5.0786    4.7737    2.7583
2.4439    4.5664    4.2765    2.4655
2.6095    4.8234    4.5165    2.6018
Y(:,:,2,2) =
1.4740    2.7639    2.5977    1.5023
2.8931    5.3300    4.9868    2.8703
2.5479    4.7381    4.4189    2.5385
2.7060    4.9891    4.6705    2.6895
Y(:,:,3,2) =
1.0365    1.9368    1.8275    1.0598
1.9305    3.6151    3.4161    1.9837
1.7213    3.2586    3.0731    1.7830
1.8406    3.4297    3.2279    1.8680
Y(:,:,1,3) =
1.3367    2.4889    2.3411    1.3540
2.5428    4.6564    4.3894    2.5403
2.2559    4.1595    3.9180    2.2671
2.4183    4.4405    4.1641    2.4005
Y(:,:,2,3) =
1.3373    2.4918    2.3410    1.3528
2.6485    4.8327    4.5351    2.6148
2.3258    4.2653    4.0063    2.3123
2.4723    4.5286    4.2431    2.4440
Y(:,:,3,3) =
0.9845    1.8150    1.7108    0.9905
1.8066    3.3375    3.1542    1.8302
1.6093    2.9879    2.8273    1.6426
1.7309    3.1876    2.9998    1.7345
```
```Y = ttm(X, {C,D}, [3 4]);    %<-- X times C in mode-3 & D in mode-4
Y = ttm(X, {A,B,C,D}, [3 4]) %<-- Same as above.
```
```Y is a tensor of size 5 x 3 x 3 x 3
Y(:,:,1,1) =
1.5822    1.3415    1.3949
1.2553    1.1977    1.2159
1.4244    1.6067    1.3862
1.2104    0.7492    1.5089
1.2932    1.3210    1.1591
Y(:,:,2,1) =
1.5112    1.0441    1.3712
1.1439    1.2984    1.2236
1.5205    1.6549    1.5110
1.3913    0.8995    1.5692
1.2733    1.4256    1.0567
Y(:,:,3,1) =
1.0920    1.0458    1.1802
0.9569    0.8498    0.8816
0.9992    1.0501    0.9638
0.8583    0.5944    1.0157
0.9676    1.0079    0.8150
Y(:,:,1,2) =
0.9474    0.8303    0.7452
0.8904    0.7530    0.6234
0.7403    0.9461    0.8350
0.8144    0.4605    0.7893
0.7803    0.6910    0.7280
Y(:,:,2,2) =
0.9542    0.7092    0.7569
0.8336    0.8635    0.6079
0.8297    0.9292    0.9154
0.8980    0.5883    0.7834
0.8064    0.7848    0.7567
Y(:,:,3,2) =
0.6673    0.6108    0.5736
0.6973    0.4752    0.4593
0.5460    0.6273    0.5737
0.5921    0.3631    0.5820
0.5514    0.4938    0.5138
Y(:,:,1,3) =
0.8673    0.7494    0.7182
0.7597    0.6751    0.6126
0.7228    0.8726    0.7625
0.7098    0.4168    0.7683
0.7120    0.6726    0.6529
Y(:,:,2,3) =
0.8539    0.6157    0.7186
0.7037    0.7561    0.6064
0.7919    0.8754    0.8338
0.7962    0.5187    0.7797
0.7207    0.7460    0.6432
Y(:,:,3,3) =
0.6056    0.5653    0.5783
0.5887    0.4485    0.4479
0.5208    0.5749    0.5266
0.5108    0.3295    0.5433
0.5160    0.4959    0.4601
```
```Y = ttm(X, {A,B,D}, [1 2 4]);   %<-- 3-way multiply.
Y = ttm(X, {A,B,C,D}, [1 2 4]); %<-- Same as above.
Y = ttm(X, {A,B,D}, -3);        %<-- Same as above.
Y = ttm(X, {A,B,C,D}, -3)       %<-- Same as above.
```
```Y is a tensor of size 4 x 4 x 4 x 3
Y(:,:,1,1) =
1.0560    2.1553    2.0387    1.1911
2.4278    4.3898    4.2181    2.4754
2.1441    3.9274    3.7356    2.1771
2.2457    4.2196    3.9658    2.2936
Y(:,:,2,1) =
1.3324    2.2654    2.0972    1.1901
2.6489    4.6589    4.2674    2.4065
2.2210    3.9024    3.6500    2.0934
2.3874    4.1487    3.8458    2.1882
Y(:,:,3,1) =
1.5259    2.6902    2.5346    1.4625
2.4233    4.3577    4.1285    2.3958
2.1583    3.9709    3.7404    2.1642
2.4544    4.4132    4.1332    2.3769
Y(:,:,4,1) =
1.2470    2.3630    2.2327    1.2974
2.4531    4.5551    4.3305    2.5251
2.2263    4.0016    3.8576    2.2685
2.3016    4.2637    4.0530    2.3627
Y(:,:,1,2) =
0.6944    1.3989    1.3155    0.7645
1.4979    2.6951    2.5093    1.4364
1.3402    2.4234    2.2267    1.2614
1.4163    2.6071    2.4098    1.3735
Y(:,:,2,2) =
0.8962    1.5379    1.4173    0.8018
1.6626    3.0068    2.7746    1.5774
1.4220    2.6151    2.4249    1.3856
1.5214    2.7047    2.5241    1.4463
Y(:,:,3,2) =
0.8062    1.4427    1.3306    0.7556
1.3527    2.4504    2.3102    1.3362
1.2317    2.2839    2.1471    1.2410
1.3547    2.4308    2.2533    1.2850
Y(:,:,4,2) =
0.6588    1.3312    1.3007    0.7781
1.3637    2.6926    2.5765    1.5156
1.2072    2.3770    2.2702    1.3333
1.2520    2.4805    2.3848    1.4080
Y(:,:,1,3) =
0.6109    1.2374    1.1665    0.6794
1.3537    2.4408    2.3039    1.3333
1.2045    2.1900    2.0426    1.1717
1.2680    2.3547    2.1921    1.2574
Y(:,:,2,3) =
0.7812    1.3355    1.2330    0.6984
1.4915    2.6660    2.4525    1.3896
1.2650    2.2829    2.1244    1.2158
1.3562    2.3881    2.2224    1.2697
Y(:,:,3,3) =
0.7811    1.3880    1.2929    0.7398
1.2777    2.3069    2.1797    1.2626
1.1519    2.1284    2.0027    1.1581
1.2862    2.3100    2.1515    1.2317
Y(:,:,4,3) =
0.6383    1.2522    1.2053    0.7119
1.2905    2.4790    2.3654    1.3861
1.1555    2.1838    2.0942    1.2306
1.1966    2.2999    2.2001    1.2917
```

## Sparse tensor times matrix (ttm for sptensor)

It is also possible to multiply an sptensor times a matrix or series of matrices. The arguments are the same as for the dense case. The result may be dense or sparse, depending on its density.

```X = sptenrand([5 3 4 2],10);
Y = ttm(X, A, 1);         %<-- X times A in mode-1.
Y = ttm(X, {A,B,C,D}, 1); %<-- Same as above.
Y = ttm(X, A', 1, 't')    %<-- Same as above
```
```Y is a sparse tensor of size 4 x 3 x 4 x 2 with 28 nonzeros
(1,1,1,1)    0.1506
(1,2,2,1)    0.0129
(1,3,2,1)    0.0893
(1,2,1,2)    0.4196
(1,1,2,2)    0.0066
(1,3,2,2)    0.0377
(1,3,3,2)    0.4310
(2,1,1,1)    0.7738
(2,2,2,1)    0.3652
(2,3,2,1)    0.4116
(2,2,1,2)    0.2315
(2,1,2,2)    0.1852
(2,3,2,2)    0.2910
(2,3,3,2)    0.7843
(3,1,1,1)    0.8920
(3,2,2,1)    0.2743
(3,3,2,1)    0.3639
(3,2,1,2)    0.3365
(3,1,2,2)    0.1391
(3,3,2,2)    0.2387
(3,3,3,2)    0.9501
(4,1,1,1)    0.5556
(4,2,2,1)    0.3154
(4,3,2,1)    0.1610
(4,2,1,2)    0.4202
(4,1,2,2)    0.1600
(4,3,2,2)    0.1799
(4,3,3,2)    0.7447
```
```norm(full(Y) - ttm(full(X),A, 1) ) %<-- Same as dense case.
```
```ans =
5.5511e-17
```
```Y = ttm(X, {A,B,C,D}, [1 2 3 4]); %<-- 4-way multiply.
Y = ttm(X, {D,C,B,A}, [4 3 2 1]); %<-- Same as above.
Y = ttm(X, {A,B,C,D});            %<-- Same as above.
Y = ttm(X, {A',B',C',D'}, 't')    %<-- Same as above.
```
```Y is a tensor of size 4 x 4 x 3 x 3
Y(:,:,1,1) =
0.0890    0.1395    0.1470    0.0913
0.2458    0.5003    0.5113    0.3157
0.2497    0.5323    0.5461    0.3388
0.2063    0.4095    0.3985    0.2375
Y(:,:,2,1) =
0.0985    0.1757    0.1675    0.0976
0.3510    0.7241    0.7029    0.4190
0.3310    0.7403    0.7158    0.4273
0.2770    0.5858    0.5249    0.2942
Y(:,:,3,1) =
0.0419    0.0376    0.0617    0.0462
0.1291    0.1583    0.1999    0.1358
0.1288    0.1546    0.2055    0.1430
0.1050    0.1303    0.1583    0.1054
Y(:,:,1,2) =
0.0981    0.1224    0.1323    0.0821
0.1729    0.2599    0.3046    0.2013
0.1919    0.2865    0.3360    0.2219
0.1682    0.2465    0.2699    0.1710
Y(:,:,2,2) =
0.0973    0.1452    0.1299    0.0708
0.1977    0.3532    0.3625    0.2229
0.2021    0.3706    0.3744    0.2280
0.1835    0.3276    0.3052    0.1747
Y(:,:,3,2) =
0.0483    0.0371    0.0666    0.0510
0.1054    0.0994    0.1585    0.1176
0.1157    0.1031    0.1730    0.1305
0.0945    0.0895    0.1386    0.1018
Y(:,:,1,3) =
0.0719    0.0965    0.1034    0.0642
0.1480    0.2538    0.2795    0.1794
0.1587    0.2752    0.3040    0.1956
0.1361    0.2251    0.2346    0.1450
Y(:,:,2,3) =
0.0738    0.1169    0.1071    0.0599
0.1860    0.3555    0.3552    0.2152
0.1835    0.3684    0.3644    0.2199
0.1610    0.3092    0.2830    0.1605
Y(:,:,3,3) =
0.0350    0.0282    0.0491    0.0374
0.0853    0.0892    0.1296    0.0932
0.0905    0.0902    0.1384    0.1016
0.0739    0.0773    0.1094    0.0777
```
```Y = ttm(X, {C,D}, [3 4]);    %<-- X times C in mode-3 & D in mode-4
Y = ttm(X, {A,B,C,D}, [3 4]) %<-- Same as above.
```
```Y is a tensor of size 5 x 3 x 3 x 3
Y(:,:,1,1) =
0    0.1004    0.0998
0.4075         0    0.1363
0.0221    0.1332    0.0167
0         0    0.3307
0         0         0
Y(:,:,2,1) =
0    0.1323    0.0395
0.5371         0    0.0540
0.0427    0.2578    0.0322
0         0    0.6257
0         0         0
Y(:,:,3,1) =
0    0.0154    0.0943
0.0626         0    0.1289
0.0123    0.0742    0.0093
0         0    0.1878
0         0         0
Y(:,:,1,2) =
0    0.1342    0.1334
0.1478         0    0.1823
0.0295    0.0483    0.0223
0         0    0.1626
0         0         0
Y(:,:,2,2) =
0    0.1769    0.0528
0.1948         0    0.0722
0.0571    0.0935    0.0431
0         0    0.2955
0         0         0
Y(:,:,3,2) =
0    0.0206    0.1262
0.0227         0    0.1724
0.0164    0.0269    0.0124
0         0    0.0954
0         0         0
Y(:,:,1,3) =
0    0.0933    0.0927
0.1737         0    0.1267
0.0205    0.0568    0.0155
0         0    0.1630
0         0         0
Y(:,:,2,3) =
0    0.1229    0.0367
0.2290         0    0.0502
0.0397    0.1099    0.0300
0         0    0.3022
0         0         0
Y(:,:,3,3) =
0    0.0143    0.0877
0.0267         0    0.1198
0.0114    0.0316    0.0086
0         0    0.0942
0         0         0
```
```Y = ttm(X, {A,B,D}, [1 2 4]);   %<-- 3-way multiply.
Y = ttm(X, {A,B,C,D}, [1 2 4]); %<-- Same as above.
Y = ttm(X, {A,B,D}, -3);        %<-- Same as above.
Y = ttm(X, {A,B,C,D}, -3)       %<-- Same as above.
```
```Y is a tensor of size 4 x 4 x 4 x 3
Y(:,:,1,1) =
0.1010    0.2463    0.1918    0.0950
0.1515    0.7021    0.6066    0.3415
0.1879    0.8297    0.7130    0.3989
0.1573    0.5785    0.4856    0.2645
Y(:,:,2,1) =
0.0416    0.0313    0.0563    0.0431
0.3903    0.4667    0.4983    0.3058
0.3136    0.3615    0.4026    0.2533
0.2647    0.3646    0.3297    0.1801
Y(:,:,3,1) =
0.0468    0.0249    0.0651    0.0543
0.0851    0.0453    0.1184    0.0988
0.1031    0.0549    0.1434    0.1196
0.0808    0.0430    0.1124    0.0938
Y(:,:,4,1) =
0     0     0     0
0     0     0     0
0     0     0     0
0     0     0     0
Y(:,:,1,2) =
0.1147    0.2091    0.1501    0.0656
0.0980    0.3207    0.2645    0.1410
0.1308    0.3970    0.3232    0.1696
0.1353    0.3298    0.2568    0.1271
Y(:,:,2,2) =
0.0194    0.0152    0.0275    0.0211
0.1805    0.2340    0.2663    0.1713
0.1451    0.1809    0.2133    0.1397
0.1221    0.1841    0.1830    0.1087
Y(:,:,3,2) =
0.0626    0.0333    0.0870    0.0726
0.1138    0.0606    0.1584    0.1321
0.1379    0.0735    0.1919    0.1600
0.1081    0.0576    0.1504    0.1254
Y(:,:,4,2) =
0     0     0     0
0     0     0     0
0     0     0     0
0     0     0     0
Y(:,:,1,3) =
0.0834    0.1668    0.1233    0.0566
0.0868    0.3335    0.2816    0.1545
0.1125    0.4033    0.3373    0.1830
0.1074    0.3086    0.2487    0.1289
Y(:,:,2,3) =
0.0200    0.0153    0.0277    0.0212
0.1865    0.2324    0.2566    0.1616
0.1499    0.1798    0.2064    0.1327
0.1263    0.1822    0.1733    0.0992
Y(:,:,3,3) =
0.0435    0.0232    0.0605    0.0504
0.0791    0.0421    0.1100    0.0918
0.0958    0.0510    0.1333    0.1112
0.0751    0.0400    0.1045    0.0872
Y(:,:,4,3) =
0     0     0     0
0     0     0     0
0     0     0     0
0     0     0     0
```

The result may be dense or sparse.

```X = sptenrand([5 3 4],1);
Y = ttm(X, A, 1) %<-- Sparse result.
```
```Y is a sparse tensor of size 4 x 3 x 4 with 4 nonzeros
(1,3,2)    0.0232
(2,3,2)    0.1067
(3,3,2)    0.0943
(4,3,2)    0.0417
```
```X = sptenrand([5 3 4],50);
Y = ttm(X, A, 1) %<-- Dense result.
```
```Y is a tensor of size 4 x 3 x 4
Y(:,:,1) =
0.4159    0.5631    0.0406
0.9765    1.4239    0.2088
0.9029    1.2234    0.2406
0.8744    1.2606    0.1499
Y(:,:,2) =
1.0127    0.5477         0
1.4153    1.1141         0
1.1989    1.0105         0
1.6381    0.9835         0
Y(:,:,3) =
0.5923    0.6934    0.9184
0.8260    0.9650    0.8641
0.4955    0.7236    0.5323
0.8762    0.9604    1.0351
Y(:,:,4) =
1.2906    0.7036    0.4899
1.2638    0.8427    1.1469
1.1332    0.8936    1.0464
1.5305    0.9649    0.9588
```

Sometimes the product may be too large to reside in memory. For example, try the following: X = sptenrand([100 100 100 100], 1e4); A = rand(1000,100); ttm(X,A,1); %<-- too large for memory

## Matricized Khatri-Rao product of a tensor.

mttkrp computes the matricized Khatri-Rao product of a tensor X with a cell array of matrices U. The operation first matricizes (i.e. flattens) a tensor X with m modes, in a given mode n. Then the Khatri-Rao product of a cell array of matrices U={U1,...,Um} is computed, omitting the nth term in the array. The returned value is then the product matricized tensor X and Khatri-Rao product of the cell array. This operation is useful in many numerical procedures, e.g. formulating the subproblems in an alternating least squares CP decomposition of tensor.

Each matrix in the cell array U must have the same number of columns. The number of rows of the matrix Ui equal the dimension of X in mode i. In the example that follows we will verify that mttkrp performs the calculation indicated above.

```U = {rand(2,3), 2*rand(3,3), 3*rand(4,3)}; %<--the cell array
X = tensor(rand(2,3,4)); %<--the tensor
n = 2; %<--the dimension to matricize with respect to.

KRP = khatrirao(U{1}, U{3}); %<--Khatri-Rao product, omitting U{2}
M = permute(X.data, [n:size(X,n), 1:n-1]);
M = reshape(M,size(X,n),[]); %<--Matricized tensor data

norm(M*KRP-mttkrp(X,U,n)) < 1e-14 %<--They are equal, within machine precision
```
```ans =
logical
1
```

## Kruskal tensor times matrix (ttm for ktensor)

The special structure of a ktensor allows an efficient implementation of matrix multiplication. The arguments are the same as for the dense case.

```X = ktensor({rand(5,1) rand(3,1) rand(4,1) rand(2,1)});
```
```Y = ttm(X, A, 1);         %<-- X times A in mode-1.
Y = ttm(X, {A,B,C,D}, 1); %<-- Same as above.
Y = ttm(X, A', 1, 't')    %<-- Same as above.
```
```Y is a ktensor of size 4 x 3 x 4 x 2
Y.lambda =
1
Y.U{1} =
0.9195
1.0464
1.0804
1.2324
Y.U{2} =
0.3348
0.3762
0.9522
Y.U{3} =
0.7193
0.7793
0.6177
0.6492
Y.U{4} =
0.7563
0.1478
```
```Y = ttm(X, {A,B,C,D}, [1 2 3 4]); %<-- 4-way mutliply.
Y = ttm(X, {D,C,B,A}, [4 3 2 1]); %<-- Same as above.
Y = ttm(X, {A,B,C,D});            %<-- Same as above.
Y = ttm(X, {A',B',C',D'}, 't')    %<-- Same as above.
```
```Y is a ktensor of size 4 x 4 x 3 x 3
Y.lambda =
1
Y.U{1} =
0.9195
1.0464
1.0804
1.2324
Y.U{2} =
0.6186
0.8281
0.9655
0.6314
Y.U{3} =
1.2905
1.3673
0.9019
Y.U{4} =
0.7582
0.3193
0.3461
```
```Y = ttm(X, {C,D}, [3 4]);    %<-- X times C in mode-3 & D in mode-4.
Y = ttm(X, {A,B,C,D}, [3 4]) %<-- Same as above.
```
```Y is a ktensor of size 5 x 3 x 3 x 3
Y.lambda =
1
Y.U{1} =
0.9971
0.3462
0.1761
0.0679
0.3094
Y.U{2} =
0.3348
0.3762
0.9522
Y.U{3} =
1.2905
1.3673
0.9019
Y.U{4} =
0.7582
0.3193
0.3461
```
```Y = ttm(X, {A,B,D}, [1 2 4]);   %<-- 3-way multiply.
Y = ttm(X, {A,B,C,D}, [1 2 4]); %<-- Same as above.
Y = ttm(X, {A,B,D}, -3);        %<-- Same as above.
Y = ttm(X, {A,B,C,D}, -3)       %<-- Same as above.
```
```Y is a ktensor of size 4 x 4 x 4 x 3
Y.lambda =
1
Y.U{1} =
0.9195
1.0464
1.0804
1.2324
Y.U{2} =
0.6186
0.8281
0.9655
0.6314
Y.U{3} =
0.7193
0.7793
0.6177
0.6492
Y.U{4} =
0.7582
0.3193
0.3461
```

## Tucker tensor times matrix (ttm for ttensor)

The special structure of a ttensor allows an efficient implementation of matrix multiplication.

```X = ttensor(tensor(rand(2,2,2,2)),{rand(5,2) rand(3,2) rand(4,2) rand(2,2)});
```
```Y = ttm(X, A, 1);         %<-- computes X times A in mode-1.
Y = ttm(X, {A,B,C,D}, 1); %<-- Same as above.
Y = ttm(X, A', 1, 't')    %<-- Same as above.
```
```Y is a ttensor of size 4 x 3 x 4 x 2
Y.core is a tensor of size 2 x 2 x 2 x 2
Y.core(:,:,1,1) =
0.5995    0.1719
0.8986    0.8189
Y.core(:,:,2,1) =
0.0693    0.3173
0.9557    0.0052
Y.core(:,:,1,2) =
0.7599    0.7153
0.3087    0.0809
Y.core(:,:,2,2) =
0.8459    0.8704
0.7184    0.8722
Y.U{1} =
1.3576    0.9672
2.5857    1.7605
2.2392    1.4629
2.4193    1.6863
Y.U{2} =
0.7233    0.4236
0.2397    0.7957
0.4899    0.7634
Y.U{3} =
0.2389    0.2685
0.6351    0.9912
0.2315    0.7603
0.6159    0.4822
Y.U{4} =
0.9452    0.0844
0.3607    0.9485
```
```Y = ttm(X, {A,B,C,D}, [1 2 3 4]); %<-- 4-way multiply.
Y = ttm(X, {D,C,B,A}, [4 3 2 1]); %<-- Same as above.
Y = ttm(X, {A,B,C,D});            %<-- Same as above.
Y = ttm(X, {A',B',C',D'}, 't')    %<-- Same as above.
```
```Y is a ttensor of size 4 x 4 x 3 x 3
Y.core is a tensor of size 2 x 2 x 2 x 2
Y.core(:,:,1,1) =
0.5995    0.1719
0.8986    0.8189
Y.core(:,:,2,1) =
0.0693    0.3173
0.9557    0.0052
Y.core(:,:,1,2) =
0.7599    0.7153
0.3087    0.0809
Y.core(:,:,2,2) =
0.8459    0.8704
0.7184    0.8722
Y.U{1} =
1.3576    0.9672
2.5857    1.7605
2.2392    1.4629
2.4193    1.6863
Y.U{2} =
0.4280    0.8254
0.9494    1.2692
0.9504    1.2097
0.5811    0.6974
Y.U{3} =
0.7658    1.1522
0.8756    1.1782
0.5976    0.9002
Y.U{4} =
1.0017    0.3714
0.4715    0.4192
0.4829    0.3051
```
```Y = ttm(X, {C,D}, [3 4]);    %<-- X times C in mode-3 & D in mode-4
Y = ttm(X, {A,B,C,D}, [3 4]) %<-- Same as above.
```
```Y is a ttensor of size 5 x 3 x 3 x 3
Y.core is a tensor of size 2 x 2 x 2 x 2
Y.core(:,:,1,1) =
0.5995    0.1719
0.8986    0.8189
Y.core(:,:,2,1) =
0.0693    0.3173
0.9557    0.0052
Y.core(:,:,1,2) =
0.7599    0.7153
0.3087    0.0809
Y.core(:,:,2,2) =
0.8459    0.8704
0.7184    0.8722
Y.U{1} =
0.7616    0.6399
0.6695    0.1562
0.9020    0.7832
0.8215    0.7314
0.8327    0.5647
Y.U{2} =
0.7233    0.4236
0.2397    0.7957
0.4899    0.7634
Y.U{3} =
0.7658    1.1522
0.8756    1.1782
0.5976    0.9002
Y.U{4} =
1.0017    0.3714
0.4715    0.4192
0.4829    0.3051
```
```Y = ttm(X, {A,B,D}, [1 2 4]);   %<-- 3-way multiply
Y = ttm(X, {A,B,C,D}, [1 2 4]); %<-- Same as above.
Y = ttm(X, {A,B,D}, -3);        %<-- Same as above.
Y = ttm(X, {A,B,C,D}, -3)       %<-- Same as above.
```
```Y is a ttensor of size 4 x 4 x 4 x 3
Y.core is a tensor of size 2 x 2 x 2 x 2
Y.core(:,:,1,1) =
0.5995    0.1719
0.8986    0.8189
Y.core(:,:,2,1) =
0.0693    0.3173
0.9557    0.0052
Y.core(:,:,1,2) =
0.7599    0.7153
0.3087    0.0809
Y.core(:,:,2,2) =
0.8459    0.8704
0.7184    0.8722
Y.U{1} =
1.3576    0.9672
2.5857    1.7605
2.2392    1.4629
2.4193    1.6863
Y.U{2} =
0.4280    0.8254
0.9494    1.2692
0.9504    1.2097
0.5811    0.6974
Y.U{3} =
0.2389    0.2685
0.6351    0.9912
0.2315    0.7603
0.6159    0.4822
Y.U{4} =
1.0017    0.3714
0.4715    0.4192
0.4829    0.3051
```

## Tensor times tensor (ttt for tensor)

```X = tensor(rand(4,2,3)); Y = tensor(rand(3,4,2));
Z = ttt(X,Y); %<-- Outer product of X and Y.
size(Z)
```
```ans =
4     2     3     3     4     2
```
```Z = ttt(X,X,1:3) %<-- Inner product of X with itself.
```
```Z =
8.9942
```
```Z = ttt(X,Y,[1 2 3],[2 3 1]) %<-- Inner product of X & Y.
```
```Z =
6.3410
```
```Z = innerprod(X,permute(Y, [2 3 1])) %<-- Same as above.
```
```Z =
6.3410
```
```Z = ttt(X,Y,[1 3],[2 1]) %<-- Product of X & Y along specified dims.
```
```Z is a tensor of size 2 x 2
Z(:,:) =
2.4886    2.4765
3.2827    3.8524
```

## Sparse tensor times sparse tensor (ttt for sptensor)

```X = sptenrand([4 2 3],3); Y = sptenrand([3 4 2],3);
Z = ttt(X,Y) %<--Outer product of X and Y.
```
```Z is a sparse tensor of size 4 x 2 x 3 x 3 x 4 x 2 with 9 nonzeros
(1,1,3,1,3,1)    0.1445
(1,1,3,3,1,1)    0.4935
(1,1,3,3,4,1)    0.5292
(2,2,3,1,3,1)    0.1181
(2,2,3,3,1,1)    0.4033
(2,2,3,3,4,1)    0.4325
(3,2,1,1,3,1)    0.1132
(3,2,1,3,1,1)    0.3867
(3,2,1,3,4,1)    0.4147
```
```norm(full(Z)-ttt(full(X),full(Y))) %<-- Same as dense.
```
```ans =
0
```
```Z = ttt(X,X,1:3) %<-- Inner product of X with itself.
```
```Z =
2.2738
```
```X = sptenrand([2 3],1); Y = sptenrand([3 2],1);
Z = ttt(X, Y) %<-- Sparse result.
```
```Z is a sparse tensor of size 2 x 3 x 3 x 2 with 1 nonzeros
(2,1,2,1)    0.7262
```
```X = sptenrand([2 3],20); Y = sptenrand([3 2],20);
Z = ttt(X, Y) %<-- Dense result.
```
```Z is a tensor of size 2 x 3 x 3 x 2
Z(:,:,1,1) =
0    0.1584    0.1237
0.5586    0.2357    0.0374
Z(:,:,2,1) =
0    0.1367    0.1067
0.4820    0.2034    0.0322
Z(:,:,3,1) =
0    0.1968    0.1536
0.6939    0.2928    0.0464
Z(:,:,1,2) =
0    0.0550    0.0430
0.1940    0.0819    0.0130
Z(:,:,2,2) =
0    0.0418    0.0326
0.1473    0.0622    0.0099
Z(:,:,3,2) =
0    0.1293    0.1009
0.4559    0.1924    0.0305
```
```Z = ttt(X,Y,[1 2],[2 1]) %<-- inner product of X & Y
```
```Z =
0.5770
```

## Inner product (innerprod)

The function innerprod efficiently computes the inner product between two tensors X and Y. The code does this efficiently depending on what types of tensors X and Y.

```X = tensor(rand(2,2,2))
Y = ktensor({rand(2,2),rand(2,2),rand(2,2)})
```
```X is a tensor of size 2 x 2 x 2
X(:,:,1) =
0.6496    0.3348
0.0418    0.4334
X(:,:,2) =
0.0986    0.0271
0.6809    0.3208
Y is a ktensor of size 2 x 2 x 2
Y.lambda =
1     1
Y.U{1} =
0.0525    0.3839
0.3696    0.3359
Y.U{2} =
0.8907    0.0810
0.2381    0.3015
Y.U{3} =
0.1800    0.7903
0.7162    0.3313
```
```z = innerprod(X,Y)
```
```z =
0.3010
```

## Contraction on tensors (contract for tensor)

The function contract sums the entries of X along dimensions I and J. Contraction is a generalization of matrix trace. In other words, the trace is performed along the two-dimensional slices defined by dimensions I and J. It is possible to implement tensor multiplication as an outer product followed by a contraction.

```X = sptenrand([4 3 2],5);
Y = sptenrand([3 2 4],5);
```
```Z1 = ttt(X,Y,1,3); %<-- Normal tensor multiplication
```
```Z2 = contract(ttt(X,Y),1,6); %<-- Outer product + contract
```
```norm(Z1-Z2) %<-- Should be zero
```
```ans =
0
```

Using contract on either sparse or dense tensors gives the same result

```X = sptenrand([4 2 3 4],20);
Z1 = contract(X,1,4)        % sparse version of contract
```
```Z1 is a tensor of size 2 x 3
Z1(:,:) =
0.0047    0.2498    0.2491
0.5821    0.4739    0.3943
```
```Z2 = contract(full(X),1,4)  % dense version of contract
```
```Z2 is a tensor of size 2 x 3
Z2(:,:) =
0.0047    0.2498    0.2491
0.5821    0.4739    0.3943
```
```norm(full(Z1) - Z2) %<-- Should be zero
```
```ans =
0
```

The result may be dense or sparse, depending on its density.

```X = sptenrand([4 2 3 4],8);
Y = contract(X,1,4) %<-- should be sparse
```
```Y is a sparse tensor of size 2 x 3 with 2 nonzeros
(1,3)    0.5531
(2,2)    0.7281
```
```X = sptenrand([4 2 3 4],80);
Y = contract(X,1,4) %<-- should be dense
```
```Y is a tensor of size 2 x 3
Y(:,:) =
1.0451    1.9378    0.9447
1.9514    1.3196    1.6253
```

## Relationships among ttv, ttm, and ttt

The three "tensor times _" functions (ttv, ttm, ttt) all perform specialized calculations, but they are all related to some degree. Here are several relationships among them:

```X = tensor(rand(4,3,2));
A = rand(4,1);
```

Tensor times vector gives a 3 x 2 result

```Y1 = ttv(X,A,1)
```
```Y1 is a tensor of size 3 x 2
Y1(:,:) =
1.3897    1.2870
0.3184    0.6756
0.5032    1.3496
```

When ttm is used with the transpose option, the result is almost the same as ttv

```Y2 = ttm(X,A,1,'t')
```
```Y2 is a tensor of size 1 x 3 x 2
Y2(:,:,1) =
1.3897    0.3184    0.5032
Y2(:,:,2) =
1.2870    0.6756    1.3496
```

We can use squeeze to remove the singleton dimension left over from ttm to give the same answer as ttv

```squeeze(Y2)
```
```ans is a tensor of size 3 x 2
ans(:,:) =
1.3897    1.2870
0.3184    0.6756
0.5032    1.3496
```

Tensor outer product may be used in conjuction with contract to produce the result of ttm. Please note that this is more expensive than using ttm.

```Z = ttt(tensor(A),X);
size(Z)
```
```ans =
4     1     4     3     2
```
```Y3 = contract(Z,1,3)
```
```Y3 is a tensor of size 1 x 3 x 2
Y3(:,:,1) =
1.3897    0.3184    0.5032
Y3(:,:,2) =
1.2870    0.6756    1.3496
```

Finally, use squeeze to remove the singleton dimension to get the same result as ttv.

```squeeze(Y3)
```
```ans is a tensor of size 3 x 2
ans(:,:) =
1.3897    1.2870
0.3184    0.6756
0.5032    1.3496
```

## Frobenius norm of a tensor

The Frobenius norm of any type of tensor may be computed with the function norm. Each class is optimized to calculate the norm in the most efficient manner.

```X = sptenrand([4 3 2],5)
norm(X)
norm(full(X))
```
```X is a sparse tensor of size 4 x 3 x 2 with 5 nonzeros
(2,2,1)    0.8295
(2,3,2)    0.7905
(3,2,2)    0.8002
(3,3,1)    0.9895
(4,1,1)    0.8698
ans =
1.9206
ans =
1.9206
```
```X = ktensor({rand(4,2),rand(3,2)})
norm(X)
```
```X is a ktensor of size 4 x 3
X.lambda =
1     1
X.U{1} =
0.8201    0.6458
0.9506    0.2407
0.5689    0.0888
0.1064    0.9876
X.U{2} =
0.7440    0.7862
0.5461    0.8098
0.4219    0.6288
ans =
2.6010
```
```X = ttensor(tensor(rand(2,2)),{rand(4,2),rand(3,2)})
norm(X)
```
```X is a ttensor of size 4 x 3
X.core is a tensor of size 2 x 2
X.core(:,:) =
0.3186    0.0491
0.3027    0.6021
X.U{1} =
0.2244    0.6691
0.8587    0.8619
0.7536    0.8412
0.2630    0.0178
X.U{2} =
0.8048    0.1238
0.5318    0.0792
0.3100    0.3897
ans =
1.0605
```