Python Kronecker乘积的置换串

Python Kronecker乘积的置换串,python,numpy,matrix,Python,Numpy,Matrix,我正在编写的函数将接收一个矩阵H=A x B x I x I作为输入,其中每个矩阵都是正方形,尺寸为d,十字表示Kronecker乘积np.kron,I表示标识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(

我正在编写的函数将接收一个矩阵H=A x B x I x I作为输入,其中每个矩阵都是正方形,尺寸为d,十字表示Kronecker乘积
np.kron
,I表示标识
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,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产品与重塑和轴洗牌的关系

两个1D因素:

>>> 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)

回到克罗内克,交换中轴线

=>全轴置换:(1,0,3,2)


使用相同的原则,我们可以得出四因素原始问题的答案。

这个答案扩展了保罗·潘泽的正确答案,记录了如何更普遍地解决类似问题

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


np.kron
排列数据的方式意味着
ABDC
的索引顺序对应于其组成部分的索引顺序,如下所示:
du0c\u0b\u0a\u0d\u1c\u1b\u1a\u1
,例如
du0
du1
)是
D
中振荡最快(最慢)的索引。对于
CADB
,索引顺序改为(
B_0 D_0 A_0 C_0 B_1 D_1 A_1 C_1
);您只需对较快的索引向后读取字符串一次,对较慢的索引向后读取字符串一次。因此,在这种情况下,合适的排列字符串是
(2,0,3,1,6,4,7,5)

您熟悉
vec
操作吗?你们需要解一个线性系统,而不是一个置换。这似乎是可行的,尽管为什么它对我来说很神秘。你能解释一下你是怎么想出来的吗?
>>> np.all(np.kron(A2, B2).reshape(2,2,2,2).transpose(1,0,3,2).reshape(4,4) == np.kron(B2, A2))
True