pythonnumpysymmetry

Exploiting Symmetry in Large Numpy Array


Want to make large array, B, that is made up of a smaller numpy array, A, flipped in different ways:

B[0,:,:,:,:]   = A
B[1,:,:,:,:]   = B[0,:,::-1,:,:]
B[2:4,:,:,:,:] = B[0:2,:,:,::-1,:]
B[4:8,:,:,:,:] = B[0:4,:,:,:,::-1]

Is there a way to only store A in memory, but keep some of the functionality of a numpy array for B? I was primarily interested in two things:


Solution

  • What I ended up doing was creating a class to return a view of an arbitrarily reflected portion of A. I was doing scaling by C, as well as sums, after returning this view, which seemed quick enough for now. This is it without error checking:

    class SymmetricArray:
        '''
        Attributes:
            A (np.ndarray): an [m, (a,b,c...)] array.
            idx (np.ndarray): an [n,] array where idx[n] points to A[idx[n], ...]
                to be used.
            reflect (np.ndarray): an [n, d] array where every entry is 1 or -1 and
                reflect[n, i] indicates whether or not the ith dimension of
                A[idx[n], ...] should be reflected, and d = len(A.shape - 1).
        '''
        def __init__(self, A, idx, reflect):
            self.A = np.asarray(A)
            self.idx = np.asarray(idx, dtype=int)
            self.reflect = np.asarray(reflect, dtype=int)
    
        def __getitem__(self, ii):
            '''
            Returns:
                np.ndarray: appropriately reflected A[idx[ii], ...]
            '''
            a_mask = [slice(None, None, a) for a in self.reflect[ii, :]]
            return self.A[self.idx[ii], ...][a_mask]