在Python中无numpy连接矩阵

1 投票
2 回答
4372 浏览
提问于 2025-04-29 18:58

我正在使用嵌套数组来表示矩阵。我创建了一个函数,用于将大小为2的k次方的方阵分成四个相等的部分(这是为了使用Strassen算法):

import itertools
def splitmat(mat):
    n = len(mat)
    return map( \
        lambda (x,y):map(lambda z:z[y[0]:y[1]],mat[x[0]:x[1]]), \
        itertools.product([(0,n/2),(n/2,n)],repeat=2)
    )

现在我想找一个反向函数,把这四个部分重新组合成一个完整的矩阵。我可以使用两个嵌套的循环来实现,但有没有什么更“pythonic”的方法呢?我更希望只使用内置模块,而不使用numpy。你有什么想法或者提示可以帮助我实现这个吗?

暂无标签

2 个回答

0

这里我有一个示例程序,使用两个循环的实现方式效果很好,而且意图非常明确;一个循环的实现方式也能工作,但在我看来稍微不那么清晰;而使用零个(明确说一下)循环的实现方式,结果却有问题。

我更倾向于使用两个循环……另外,我希望能有人告诉我我那个零循环的尝试哪里出错了。

代码

import itertools

def pm(m):
    for row in m: print row

mat = []
n = 8
for i in range(n):
    mat.append(range(i*n, i*n+n))

# this is shorthand for your splitmat function
res = map(lambda (x,y):
          map(lambda z:z[y[0]:y[1]],mat[x[0]:x[1]]),
          itertools.product([(0,n/2),(n/2,n)],repeat=2))
pm(res)

print "\n2 cycles"
mat = []
for i, j in ((0,1),(2,3)):
    for a, b in zip(res[i],res[j]):
        mat.append(a+b)
pm(mat)

print "\n1 cycle"
mat = []
for i, j in ((0,1),(2,3)):
    map(lambda x: mat.append(x[0]+x[1]), zip(res[i],res[j]))
pm(mat)

print "\n0 cycles"
mat =  map(lambda i_j: 
       map(lambda x: x[0]+x[1], zip(res[i_j[0]],res[i_j[1]])), ((0,1),(2,3)))
pm(mat)

输出

[[0, 1, 2, 3], [8, 9, 10, 11], [16, 17, 18, 19], [24, 25, 26, 27]]
[[4, 5, 6, 7], [12, 13, 14, 15], [20, 21, 22, 23], [28, 29, 30, 31]]
[[32, 33, 34, 35], [40, 41, 42, 43], [48, 49, 50, 51], [56, 57, 58, 59]]
[[36, 37, 38, 39], [44, 45, 46, 47], [52, 53, 54, 55], [60, 61, 62, 63]]

2 cicli
[0, 1, 2, 3, 4, 5, 6, 7]
[8, 9, 10, 11, 12, 13, 14, 15]
[16, 17, 18, 19, 20, 21, 22, 23]
[24, 25, 26, 27, 28, 29, 30, 31]
[32, 33, 34, 35, 36, 37, 38, 39]
[40, 41, 42, 43, 44, 45, 46, 47]
[48, 49, 50, 51, 52, 53, 54, 55]
[56, 57, 58, 59, 60, 61, 62, 63]

1 ciclo
[0, 1, 2, 3, 4, 5, 6, 7]
[8, 9, 10, 11, 12, 13, 14, 15]
[16, 17, 18, 19, 20, 21, 22, 23]
[24, 25, 26, 27, 28, 29, 30, 31]
[32, 33, 34, 35, 36, 37, 38, 39]
[40, 41, 42, 43, 44, 45, 46, 47]
[48, 49, 50, 51, 52, 53, 54, 55]
[56, 57, 58, 59, 60, 61, 62, 63]

0 cicli
[[0, 1, 2, 3, 4, 5, 6, 7], [8, 9, 10, 11, 12, 13, 14, 15], [16, 17, 18, 19, 20, 21, 22, 23], [24, 25, 26, 27, 28, 29, 30, 31]]
[[32, 33, 34, 35, 36, 37, 38, 39], [40, 41, 42, 43, 44, 45, 46, 47], [48, 49, 50, 51, 52, 53, 54, 55], [56, 57, 58, 59, 60, 61, 62, 63]]
1

你的反向操作可以分成两个更简单的操作:

  1. 把行拼接起来(用 numpy.vstack
  2. 把列拼接起来(用 numpy.hstack

所以,如果你有一个矩阵被分成了4个小矩阵:

M = |m1|m2| 
    |m3|m4|

那么可以用 M = hstack(vstack(m1, m2), vstack(m3, m4)) 来组合它们。

这些操作可以用下面的代码来实现:

import itertools
import math

# iterators
def ihstack(*matrixes):
    return map(lambda rows: itertools.chain(*rows), zip(*matrixes))

def ivstack(*matrixes):
    return itertools.chain(*matrixes)

# main function
def squarejoin(*matrixes):
    size = int(math.sqrt(len(matrixes)))
    assert size ** 2 == len(matrixes), 'Incorrect number of matrices'
    return _matrixjoin(matrixes, size, size)

def _matrixjoin(matrixes, hsize, vsize):
    print(matrixes, hsize, vsize)
    return ivstack(*(ihstack(*itertools.islice(matrixes, i*hsize, (i+1)*hsize)) for i in range(vsize)))

撰写回答