# `tensorly.cp_tensor`.unfolding_dot_khatri_rao

unfolding_dot_khatri_rao(tensor, cp_tensor, mode)[source]

mode-n unfolding times khatri-rao product of factors

Parameters
tensortl.tensor

tensor to unfold

factorstl.tensor list

list of matrices of which to the khatri-rao product

modeint

mode on which to unfold tensor

Returns
mttkrp

dot(unfold(tensor, mode), khatri-rao(factors))

Notes

This is a variant of:

```unfolded = unfold(tensor, mode)
kr_factors = khatri_rao(factors, skip_matrix=mode)
mttkrp2 = tl.dot(unfolded, kr_factors)
```

Multiplying with the Khatri-Rao product is equivalent to multiplying, for each rank, with the kronecker product of each factor. In code:

```mttkrp_parts = []
for r in range(rank):
component = tl.tenalg.multi_mode_dot(tensor, [f[:, r] for f in factors], skip=mode)
mttkrp_parts.append(component)
mttkrp = tl.stack(mttkrp_parts, axis=1)
return mttkrp
```

This can be done by taking n-mode-product with the full factors (faster but more memory consuming):

```projected = multi_mode_dot(tensor, factors, skip=mode, transpose=True)
ndims = T.ndim(tensor)
res = []
for i in range(factors.shape):
index = tuple([slice(None) if k == mode  else i for k in range(ndims)])
res.append(projected[index])
return T.stack(res, axis=-1)
```

The same idea could be expressed using einsum:

```ndims = tl.ndim(tensor)
tensor_idx = ''.join(chr(ord('a') + i) for i in range(ndims))
rank = chr(ord('a') + ndims + 1)
op = tensor_idx
for i in range(ndims):
if i != mode:
op += ',' + ''.join([tensor_idx[i], rank])
else:
result = ''.join([tensor_idx[i], rank])
op += '->' + result
factors = [f for (i, f) in enumerate(factors) if i != mode]
return tl_einsum(op, tensor, *factors)
```