我正在编写的函数将接收矩阵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应用一些排列来实现这一点。如何实现排列?
答案 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
。