Поэлементное тензорное произведение для блочных матриц, элементами которого являются матрицы 2x2 - PullRequest
0 голосов
/ 01 марта 2020

У меня есть блочная матрица с ее элементами в виде матриц 2x2 * Массив 1025 *, например

X = np.array([[0, 1], [1, 0]], dtype=complex)
Y = np.array([[0, -1j], [1j, 0]], dtype=complex)
Z = np.array([[1, 0], [0, -1]], dtype=complex)

block_matrix = np.array([X,Y,Z])

Я ищу векторизованный способ (если он существует), где я мог бы вычислить np.kron() без необходимости l oop через каждый из элементов блочной матрицы (которые сами снова являются матрицами 2x2). Прямо сейчас у меня есть что-то вроде

def pl_rep_operation(matrix):

    op_sum = np.zeros((4,4), dtype=complex)
    tensored_seq = []
    for i in range(len(matrix)):
        tensored = np.kron(matrix[i], matrix[i].conj()) 
        op_sum += tensored
        tensored_seq.append(tensored)
    return op_sum, tensored_seq

, где tensored_seq возвращает исходную последовательность с тензорным элементом блочной матрицы, а op_sum возвращает поэлементную сумму всех тензорных матричных элементов. Например, выходные данные могут быть

op_sum, tensored_seq = pl_rep_operation(np.array([X,Y,Z]))
In[47]: op_sum
Out[47]: 
array([[ 1.+0.j,  0.+0.j,  0.+0.j,  2.+0.j],
       [ 0.+0.j, -1.+0.j,  0.+0.j,  0.+0.j],
       [ 0.+0.j,  0.+0.j, -1.+0.j,  0.+0.j],
       [ 2.+0.j,  0.+0.j,  0.+0.j,  1.+0.j]])

In[48]: tensored_seq
Out[48]: 
[array([[0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
        [0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],
        [0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j],
        [1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]]),
 array([[ 0.+0.j, -0.+0.j, -0.+0.j,  1.+0.j],
        [ 0.+0.j,  0.+0.j, -1.+0.j, -0.+0.j],
        [ 0.+0.j, -1.+0.j,  0.+0.j, -0.+0.j],
        [ 1.+0.j,  0.+0.j,  0.+0.j,  0.+0.j]]),
 array([[ 1.+0.j,  0.+0.j,  0.+0.j,  0.+0.j],
        [ 0.+0.j, -1.-0.j,  0.+0.j,  0.-0.j],
        [ 0.+0.j,  0.+0.j, -1.+0.j,  0.+0.j],
        [ 0.+0.j,  0.-0.j,  0.+0.j,  1.+0.j]])]

Элементы tensored_seq должны быть похожи на np.array([np.kron(X,X), np.kron(Y,Y), np.kron(Z,Z)]). Я ищу какую-то функцию np.func() или какой-нибудь способ векторизации, чтобы np.func(block_matrix, block_matrix) вернул np.array([np.kron(X,X), np.kron(Y,Y), np.kron(Z,Z)]). В идеале я хочу векторизованный способ, который также

block_mat = np.array([[X, Y, Z], [X, Z, Y], [Z, Y, X]])
np.func(block_mat)

должен возвращать

np.array([[np.kron(X,X), np.kron(Y,Y), np.kron(Z,Z)],
          [np.kron(X,X), np.kron(Z,Z), np.kron(Y,Y)],
          [np.kron(Z,Z), np.kron(Y,Y), np.kron(X,X)]])

например.

1 Ответ

0 голосов
/ 01 марта 2020

Исходя из моего недавнего ответа на

Почему Крон Нумпи такой быстрый?

In [472]: X = np.array([[0, 1], [1, 0]], dtype=complex) 
     ...: Y = np.array([[0, -1j], [1j, 0]], dtype=complex) 
     ...: Z = np.array([[1, 0], [0, -1]], dtype=complex) 
     ...:  
     ...: block_matrix = np.array([X,Y,Z])                                                     
In [473]: block_matrix.shape                                                                   
Out[473]: (3, 2, 2)
In [474]: temp=block_matrix[:,:,:,None]*block_matrix.conj()[:,:,None,:]                        
In [475]: temp.shape                                                                           
Out[475]: (3, 2, 2, 2)                                                                         
In [477]: temp = block_matrix.ravel()                                                          
In [478]: temp = block_matrix.reshape(3,4)                                                     
In [479]: temp = temp[:,:,None]*temp.conj()[:,None,:]                                          
In [480]: temp.shape                                                                           
Out[480]: (3, 4, 4)
In [481]: nz = temp.shape                                                                      
In [482]: temp = temp.reshape(3,2,2,2,2)                                                       
In [483]: temp = temp.transpose(0,1,3,2,4).reshape(nz)                                         
In [484]: temp.shape                                                                           
Out[484]: (3, 4, 4)
In [485]: temp                                                                                 
Out[485]: 
array([[[ 0.+0.j,  0.+0.j,  0.+0.j,  1.+0.j],
        [ 0.+0.j,  0.+0.j,  1.+0.j,  0.+0.j],
        [ 0.+0.j,  1.+0.j,  0.+0.j,  0.+0.j],
        [ 1.+0.j,  0.+0.j,  0.+0.j,  0.+0.j]],

       [[ 0.+0.j, -0.+0.j, -0.+0.j,  1.+0.j],
        [ 0.+0.j,  0.+0.j, -1.+0.j, -0.+0.j],
        [ 0.+0.j, -1.+0.j,  0.+0.j, -0.+0.j],
        [ 1.+0.j,  0.+0.j,  0.+0.j,  0.+0.j]],

       [[ 1.+0.j,  0.+0.j,  0.+0.j,  0.+0.j],
        [ 0.+0.j, -1.-0.j,  0.+0.j,  0.-0.j],
        [ 0.+0.j,  0.+0.j, -1.+0.j,  0.+0.j],
        [ 0.+0.j,  0.-0.j,  0.+0.j,  1.+0.j]]])

Что соответствует вашему tensored_seq. Если объединить в функцию, она должна быть быстрее, чем ваши 3 kron. Но я не знаю, достаточно ли этого для расширения. Штраф за 3 итерации в относительно сложной задаче невелик.

Я бы попытался построить последнюю матрицу с:

In [486]: res = np.array([[temp[0], temp[1], temp[2]], 
     ...:                 [temp[0], temp[2],...   

при условии, что вы хотите (3,3,4 4) результат. Это не более сложная работа, чем создание

np.array([[X,Y,Z],[X,Z...])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...