I need to solve a systems of linear equations in the complex domain, in a backpropagable way.
As stated in this research report (https://hal-ens-lyon.archives-ouvertes.fr/ensl-00125369v2/document 1), complex numbers can be represented as real 2x2 matrices and complex systems of linear equations can be solved using real solver on 2 times bigger matrices.
So, I’m converting vectors containing concatenated real and imaginary parts to these type of matrices. I have a working example :
import torch

def vec_to_cmat(vec, dim=-1):
    """ Expects tensor with shape 2*(N**2) on dim 'dim'"""
    # Get matrix size (before CR tranform)
    vec_shape = list(vec.shape)
    mtxc_size = int((vec_shape[dim]/2)**0.5)
    # Keep all remaining dimensions (matrix goes last)
    vec_shape.pop(dim)
    mat_shape = vec_shape + [2 * mtxc_size, 2 * mtxc_size]
    mat = vec.new_zeros(mat_shape)
    # Create indexes
    line_idx = torch.LongTensor([2 * m for _ in range(mtxc_size) for
                                 m in range(mtxc_size)])
    col_idx = torch.LongTensor([2 * n for n in range(mtxc_size) for
                                _ in range(mtxc_size)])
    # Split real and imaginary parts
    re, im = torch.split(vec, [mtxc_size**2, mtxc_size**2], dim=dim)
    # re, im = torch.chunk(vec, 2, dim=dim)  # works as well

    # Assign the re or im parts.
    mat[..., line_idx, col_idx] = re
    mat[..., line_idx+1, col_idx+1] = re
    mat[..., line_idx+1, col_idx] = im
    mat[..., line_idx, col_idx+1] = -im
    return mat

inp = torch.randn(10, 2, 18)
complex_mat = vec_to_cmat(inp)  # (10, 2, 6, 6)

I’ve been looking for a nicer way to assign the values without luck until now. Could anybody help please?
Also, this only works for dim=-1 for now, any idea (except transposing vec) on how to make it work for any dim