2017-01-21 4 views
2

У меня есть следующие матрицы:сочетание Матрица логики в numpythonic пути

,

и

.

Где каждый элемент представляет собой матрицу 3x3 (то есть A_01 является матрицей 3x3). Это означает, что тензоры A и B являются 9x9 матрицами. Не используя для команд, как можно совмещать предыдущие уравнения, чтобы получить:

.

Цель состоит в том, чтобы получить numpythonic решение, потому что в реальных случаях и B матрицы могут иметь размер (N, N).

+0

Итак, с A и B как '(N, N)' все равно будет каждый элемент '3 x 3'? – Divakar

+0

Каждый A и B является тензором 3x3. Это называется тензором по блокам, где каждый элемент является другим тензором. – NunodeSousa

+0

Итак, было бы 3 x 3 = 9 блоков в каждом A и B всегда? – Divakar

ответ

3

Вы могли бы попробовать что-то вроде

import numpy as np 

def checker_index(n, m=3): 
    """create an index vector that addresses m blocks of n consecutive 
    elements with the blocks separated by gaps of n elements 
    """ 
    # the next line creates the array 
    #/ 0 1 ... n-1 \ 
    # | 2n 2n+1 ... 3n-1 | 
    # \ 4n 4n+1 ... 5n-1/
    i = np.arange(m*n).reshape((m, n)) + n*np.arange(m)[:, None] 
    # next line just puts the rows side by side 
    # now observe the these are precisely the places where you want to 
    # put your first row of of A's (with a leading id) in the first 
    # row of the target structure, and similarly with columns 
    # also, observe that one just needs to add n to get indices 
    # suitable for placing the first row/column of B's 
    return i.ravel() 

def mingle(AA, BB, m=3): 
    """combine AA and BB into the target structure 

    here AA and BB are the full 3x3 block matrices you define in 
    your question 
    """ 
    n = len(AA) // m 
    i1 = checker_index(n, m) 
    # ix_ creates an "open grid" from its arguments 
    # so indexing with y1, x1 below will select nm x nm elements 
    # contrast this with ... 
    y1, x1 = np.ix_(i1, i1) 
    i2 = i1 + n 
    y2, x2 = np.ix_(i2, i2) 

    IAA = AA.copy() 
    # ... the following line which only selects the diagonal, 
    # thus just mn elements 
    IAA[np.arange(m*n), np.arange(m*n)] = 1 
    out = np.empty((2*m*n, 2*m*n)) 
    out[y1, x1] = IAA 
    out[y1, x2] = BB 
    out[y2, x1] = BB 
    out[y2, x2] = IAA 
    return out 

Numpythonic достаточно?

1

Вот подход -

def matrix_combination(A,B): 
    N = A.shape[0]//3 # Size of each block 
    A4D = A.reshape(3,N,3,N) 
    B4D = B.reshape(3,N,3,N) 

    r,c = np.nonzero(~np.eye(3,dtype=bool)) 
    out = np.zeros((6,N,6,N),dtype=A.dtype)  

    idx0 = 2*np.arange(3) 
    out[idx0[r],:,idx0[c]] = A4D[r,:,c] 
    out[idx0[r]+1,:,idx0[c]+1] = A4D[r,:,c] 

    out[idx0[r],:,idx0[c]+1] = B4D[r,:,c] 
    out[idx0[r]+1,:,idx0[c]] = B4D[r,:,c] 
    out = out.reshape(N*6,-1) 
    np.fill_diagonal(out,1) 
    return out 

Пример запуска -

In [41]: A 
Out[41]: 
array([[ 0, 0, 44, 98, 40, 69], 
     [ 0, 0, 22, 55, 51, 19], 
     [16, 58, 0, 0, 95, 95], 
     [90, 88, 0, 0, 47, 91], 
     [65, 96, 21, 50, 0, 0], 
     [15, 91, 23, 91, 0, 0]]) 

In [42]: B 
Out[42]: 
array([[ 0, 0, 20, 36, 85, 15], 
     [ 0, 0, 17, 78, 56, 55], 
     [86, 19, 0, 0, 60, 96], 
     [76, 30, 0, 0, 34, 36], 
     [73, 63, 28, 58, 0, 0], 
     [40, 19, 22, 96, 0, 0]]) 

In [43]: matrix_combination(A,B) 
Out[43]: 
array([[ 1, 0, 0, 0, 44, 98, 20, 36, 40, 69, 85, 15], 
     [ 0, 1, 0, 0, 22, 55, 17, 78, 51, 19, 56, 55], 
     [ 0, 0, 1, 0, 20, 36, 44, 98, 85, 15, 40, 69], 
     [ 0, 0, 0, 1, 17, 78, 22, 55, 56, 55, 51, 19], 
     [16, 58, 86, 19, 1, 0, 0, 0, 95, 95, 60, 96], 
     [90, 88, 76, 30, 0, 1, 0, 0, 47, 91, 34, 36], 
     [86, 19, 16, 58, 0, 0, 1, 0, 60, 96, 95, 95], 
     [76, 30, 90, 88, 0, 0, 0, 1, 34, 36, 47, 91], 
     [65, 96, 73, 63, 21, 50, 28, 58, 1, 0, 0, 0], 
     [15, 91, 40, 19, 23, 91, 22, 96, 0, 1, 0, 0], 
     [73, 63, 65, 96, 28, 58, 21, 50, 0, 0, 1, 0], 
     [40, 19, 15, 91, 22, 96, 23, 91, 0, 0, 0, 1]]) 
1

Просто для удовольствия (и одной до Divakar) здесь очень компактное решение:

def mingle(AA, BB, m=3): 
    n = len(AA) // m 
    out = np.empty((m, 2, n, m, 2, n)) 
    out[:, [0, 1], ..., [0, 1], :] = AA.reshape((1, m, n, m, n)) 
    out[:, [0, 1], ..., [1, 0], :] = BB.reshape((1, m, n, m, n)) 
    out.shape = m * 2 * n, m * 2 * n 
    out[np.arange(m * 2 * n), np.arange(m * 2 * n)] = 1 
    return out 
+0

Ницца, я думал об этом, просто не мог закончи это. – Divakar

+0

@Divakar Спасибо, очевидно, вдохновленный вашим решением. –