Elegant way to get a symmetric Torch Tensor over diagonal

Is there an elegant way to build a Torch.Tensor like this from a given set of values?

Here is an 3x3 example, but in my application I would have a matrix of any odd-size.

A function call gen_matrix([a, b, c, d, e, f]) should generate

enter image description here


EDIT: As of now, I implemented the following solution. A more elegant way is desirable without a for loop. Using plain torch operations is desirable.

def weights_to_symmetric(weights, N):
  assert(weights.ndim == 3)
  tensor = torch.zeros((*weights.shape[:2], N, N))

  idx = 0
  for diag in range(N):
    size = N - diag
    w = weights[:, :, idx:idx+size]

    tensor += torch.diag_embed(w, offset=diag)
    if diag > 0:
      tensor += torch.diag_embed(w, offset=-diag)

    idx += size

  return tensor

I’m not sure about pytorch, but gpytorch has something called toeplitz. Maybe that’s what you are looking for ? (look into sym_toeplitz)

Thank you for the suggestion. sym_toeplitz is a resembles want, but it is not quite the same thing.

from gpytorch import utils
c = torch.tensor([1, 6, 4, 5], dtype=torch.float)
res = utils.toeplitz.sym_toeplitz(c)
res
# tensor([[1., 6., 4., 5.],
#        [6., 1., 6., 4.],
#        [4., 6., 1., 6.],
#        [5., 4., 6., 1.]])

Here is a solution by swag2198 from stackoverflow.

>>> N = 5
>>> vals = torch.arange(N*(N+1)/2) + 1
 
>>> A = torch.zeros(N, N)
>>> i, j = torch.triu_indices(N, N)
>>> A[i, j] = vals
>>> A.T[i, j] = vals
  
>>> vals
 tensor([ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11., 12., 13., 14.,
         15.])
>>> A
 tensor([[ 1.,  2.,  3.,  4.,  5.],
         [ 2.,  6.,  7.,  8.,  9.],
         [ 3.,  7., 10., 11., 12.],
         [ 4.,  8., 11., 13., 14.],
         [ 5.,  9., 12., 14., 15.]])