置换Kronecker产品串

时间:2018-06-15 23:27:23

标签: python numpy matrix

我正在编写的函数将接收矩阵H = A x B x I x I作为输入,其中每个矩阵是正方形且维度为d,交叉指的是Kronecker乘积np.kron而我是身份np.eye(d)。因此

I = np.eye(d)
H = np.kron(A, B)
H = np.kron(H, I)
H = np.kron(H, I)

给定H和上述形式,但不知道A和B,我想构造G = I x A x I x B,例如

的结果
G = np.kron(I, A)
G = np.kron(G, I)
G = np.kron(G, B)

应该可以通过对H应用一些排列来实现这一点。如何实现排列?

2 个答案:

答案 0 :(得分:1)

转换为(2,0,3,1,6,4,7,5)(扩展到8轴后)似乎是这样做的:

>>> from functools import reduce
>>>
>>> A = np.random.randint(0,10,(10,10))
>>> B = np.random.randint(0,10,(10,10))
>>> I = np.identity(10, int)
>>> G = reduce(np.kron, (A,B,I,I))
>>> H = reduce(np.kron, (I,A,I,B))
>>> 
>>> 
>>> (G.reshape(*8*(10,)).transpose(2,0,3,1,6,4,7,5).reshape(10**4,10**4) == H).all()
True

说明:让我们看一个最小的例子来了解Kronecker产品如何与重塑和轴改组相关。

两个一维因素:

>>> A, B = np.arange(1,5), np.array(list("abcd"), dtype=object)
>>> np.kron(A, B)
array(['a', 'b', 'c', 'd', 'aa', 'bb', 'cc', 'dd', 'aaa', 'bbb', 'ccc',
       'ddd', 'aaaa', 'bbbb', 'cccc', 'dddd'], dtype=object)

我们可以观察到排列是主要的,所以如果我们重塑,我们实际上得到了外部产品:

>>> np.kron(A, B).reshape(4, 4)
array([['a', 'b', 'c', 'd'],
       ['aa', 'bb', 'cc', 'dd'],
       ['aaa', 'bbb', 'ccc', 'ddd'],
       ['aaaa', 'bbbb', 'cccc', 'dddd']], dtype=object)
>>> np.outer(A, B)
array([['a', 'b', 'c', 'd'],
       ['aa', 'bb', 'cc', 'dd'],
       ['aaa', 'bbb', 'ccc', 'ddd'],
       ['aaaa', 'bbbb', 'cccc', 'dddd']], dtype=object)

如果我们对交换的因素做同样的事情,我们会得到转置:

>>> np.kron(B, A).reshape(4, 4)
array([['a', 'aa', 'aaa', 'aaaa'],
       ['b', 'bb', 'bbb', 'bbbb'],
       ['c', 'cc', 'ccc', 'cccc'],
       ['d', 'dd', 'ddd', 'dddd']], dtype=object)

使用2D因素,情况类似

>>> A2, B2 = A.reshape(2,2), B.reshape(2,2)
>>> 
>>> np.kron(A2, B2)
array([['a', 'b', 'aa', 'bb'],
       ['c', 'd', 'cc', 'dd'],
       ['aaa', 'bbb', 'aaaa', 'bbbb'],
       ['ccc', 'ddd', 'cccc', 'dddd']], dtype=object)
>>> np.kron(A2, B2).reshape(2,2,2,2)
array([[[['a', 'b'],
         ['aa', 'bb']],

        [['c', 'd'],
         ['cc', 'dd']]],


       [[['aaa', 'bbb'],
         ['aaaa', 'bbbb']],

        [['ccc', 'ddd'],
         ['cccc', 'dddd']]]], dtype=object)

但是有一个小的复杂因素,相应的外部产品的轴排列不同:

>>> np.multiply.outer(A2, B2)
array([[[['a', 'b'],
         ['c', 'd']],

        [['aa', 'bb'],
         ['cc', 'dd']]],


       [[['aaa', 'bbb'],
         ['ccc', 'ddd']],

        [['aaaa', 'bbbb'],
         ['cccc', 'dddd']]]], dtype=object)

我们需要交换中轴以获得相同的结果。

>>> np.multiply.outer(A2, B2).swapaxes(1,2)
array([[[['a', 'b'],
         ['aa', 'bb']],

        [['c', 'd'],
         ['cc', 'dd']]],


       [[['aaa', 'bbb'],
         ['aaaa', 'bbbb']],

        [['ccc', 'ddd'],
         ['cccc', 'dddd']]]], dtype=object)

因此,如果我们想换掉交换的Kronecker产品,我们可以交换中轴:(0,2,1,3)

现在我们有外部产品。交换因子用前两个轴交换前两个轴:(1,3,0,2)

回到Kronecker,交换中轴

=>总轴排列:(1,0,3,2)

>>> np.all(np.kron(A2, B2).reshape(2,2,2,2).transpose(1,0,3,2).reshape(4,4) == np.kron(B2, A2))
True

使用相同的原则导致四因素原始问题的配方。

答案 1 :(得分:0)

这个答案扩展了Paul Panzer的正确答案,记录了如何更普遍地解决类似问题。

假设我们希望将矩阵字符串reduce(kron, ABCD)映射到例如reduce(kron, CADB),其中每个矩阵具有维d列。因此,两个字符串都是d**4, d**4矩阵。或者它们是[d,]*8形状的阵列。

np.kron排列数据的方式意味着ABDC的索引顺序与其成分的排序顺序如下:D_0 C_0 B_0 A_0 D_1 C_1 B_1 A_1例如D_0({{1} }}是D_1中最快(最慢)的振荡指数。对于D,索引排序是(CADB);你只需向后读一次字符串一次用于更快,一次用于慢速索引。因此,在这种情况下,适当的排列字符串是B_0 D_0 A_0 C_0 B_1 D_1 A_1 C_1