# Other Tensor Formats¶

Besides the natively supported formats, you can use tntorch to emulate other structured tensor decompositions (or at least, some of their functionality).

Reference: all the following models are surveyed in *”Tensor Decompositions and Applications”*, by Kolda and Bader (2009).

## INDSCAL¶

Individual differences in scaling (INDSCAL) is just a 3D CP decomposition with two shared factors, say the first two.

[1]:

import tntorch as tn
import torch

def INDSCAL(shape, rank):

assert len(shape) == 3
assert shape[0] == shape[1]

B = A  # The first two cores share the same memory

return tn.Tensor([A, B, C])

t = INDSCAL([10, 10, 64], 8)
print(t)
print(tn.mean(t))

3D CP tensor:

10  10  64
|   |   |
<0> <1> <2>
/ \ / \ / \
8   8   8   8



This tensor’s two first factors are the same PyTorch tensor in memory. So if we optimize (fit) the tensor they will stay the same, as is desirable.

## CANDELINC¶

CANDELINC (canonical decomposition with linear constraints) is a CP decomposition such that each factor is compressed along its columns by an additional given matrix (the linear constraints). In other words, it is a CP-Tucker format with fixed Tucker factors.

[2]:

def CANDELINC(rank, constraints):  # constraints are N In x Sn matrices encoding the linear constraints for the N CP factors
cores = [torch.randn(c.shape[1], rank, requires_grad=True) for c in constraints]
return tn.Tensor(cores, constraints)

N = 3
rank = 3
constraints = [torch.randn(10, 5), torch.randn(11, 6), torch.randn(12, 7)]
CANDELINC(rank, constraints)

[2]:

3D CP-Tucker tensor:

10  11  12
|   |   |
5   6   7
<0> <1> <2>
/ \ / \ / \
3   3   3   3


## DEDICOM¶

In three-way decomposition into directional components (DEDICOM), 5 factors interact to encode a 3D tensor (2 of those factors are repeated). All factors use the same rank.

[3]:

def DEDICOM(shape, rank):

assert len(shape) == 3
assert shape[0] == shape[2]

R = torch.randn(rank, 1, rank, requires_grad=True)

return tn.Tensor([A, D, R, D, A])

DEDICOM([10, 64, 10], 8)

[3]:

5D TT-CP tensor:

10  64   1  64  10
|   |   |   |   |
<0> <1> (2) <3> <4>
/ \ / \ / \ / \ / \
8   8   8   8   8   8


Note that this tensor is to be accessed via a special pattern (t[i, j, k] should be written as t[i, j, 0, j, k]). Some routines (e.g. numel(), torch(), norm(), etc.) that are unaware of this special structure will not work properly.

## PARATUCK2¶

PARATUCK2 is a variant of DEDICOM in which no factors are repeated, and two different ranks intervene.

[4]:

def PARATUCK2(shape, ranks):

assert len(shape) == 3
assert shape[0] == shape[2]
assert len(ranks) == 2

R = torch.randn(ranks[0], 1, ranks[1], requires_grad=True)

return tn.Tensor([A, DA, R, DB, B])

PARATUCK2([10, 64, 10], [7, 8])

[4]:

5D TT-CP tensor:

10  64   1  64  10
|   |   |   |   |
<0> <1> (2) <3> <4>
/ \ / \ / \ / \ / \
7   7   7   8   8   8