I wish to create a random symmetric tensor such that for each permutation of indices i1, i2,...,ik
i will have:
a[i1][i2]...[ik] = a[pi(i1)][pi(i2)]...[pi(ik)]
Where pi
is a permutation function. For example:
a[1][2][3][4] = a[1][3][2][4] = a[4][2][1][3] = ...
In the 2 dim setting its the normal symmetry but i am unsure how implement this (without iterating over permutations) or if there is an automatic way of doing this using numpy / pytorch.
CodePudding user response:
AFAIK there is no function for that in either torch
nor numpy
, but one might add all dimensionality permutated tensors to make it symmetric across every dimension.
This has:
O(size^dims)
- memory complexity (as generators are used)O(dims! * size^dims)
- runtime complexity (althoughsize^dims
is vectorized and should be reasonably quick)
No idea how to improve runtime complexity though, sorry. Here is the code:
import functools
import itertools
import operator
import torch
def symmetricND(size: int, dims: int) -> torch.Tensor:
data = torch.randn(*[size] * dims)
return functools.reduce(
operator.add,
(
torch.permute(data, permutation)
for permutation in itertools.permutations(range(dims))
),
)
And example usage (4x4x4
symmetrical tensor):
symmetric = symmetricND(4, 3)
print(symmetric[0][1][2])
print(symmetric[2][1][0])
print(symmetric[1][2][0])
print(symmetric[1][0][2])
In general: will run as long as you can hold single tensor in your memory, but might take a lot of time ((3, 7)
is instant on my laptop, (3, 9)
takes around 1 minute though, not sure if this is satisfactory for your case).
You could also precompute these tensors (or even use multiple machines for that), save them and load as needed.