问题
I want to create a toeplitz matrix of toeplitz matrix.
H1, H2 and H3 are toeplitz matrices already. My result should look like that:
H1 0 0
H2 H1 0
H3 H2 H1
0 H3 H2
0 0 H3
The existing toeplitz-function only accepts vector, so I can't use it for matrix. Currently I'm using vstack to create the first column, then second column etc. and then I use hstackto merge all columns. This takes a lot of effort, since I have to specifically add np.zeros matrices at certain places. I can't think of a better way to concatenate numpy arrays, since there are only a few functions for that and none of them really fits my problem.
回答1:
Instead of nested calls to vstack and hstack, it will be more efficient to preallocate the final array, and then use a nested loop to fill in the array. You can initially use a higher dimensional array to keep the code clean.
For example, this script
import numpy as np
H1 = np.array([[11, 11], [11, 11]])
H2 = np.array([[22, 22], [22, 22]])
H3 = np.array([[33, 33], [33, 33]])
inputs = (H1, H2, H3)
# This assumes all the arrays in `inputs` have the same shape,
# and that the data type of all the arrays is the same as H1.dtype.
nh = len(inputs)
nrows = 2*nh - 1
m, n = H1.shape
# T is a 4D array. For a given i and j, T[i, :, j, :] is a 2D array
# with shape (m, n). T can be intepreted as a 2D array of 2D arrays.
T = np.zeros((nrows, m, nh, n), dtype=H1.dtype)
for i, H in enumerate(inputs):
for j in range(nh):
T[i + j, :, j, :] = H
# Partially flatten the 4D array to a 2D array that has the desired
# block structure.
T.shape = (nrows*m, nh*n)
print(T)
prints
[[11 11 0 0 0 0]
[11 11 0 0 0 0]
[22 22 11 11 0 0]
[22 22 11 11 0 0]
[33 33 22 22 11 11]
[33 33 22 22 11 11]
[ 0 0 33 33 22 22]
[ 0 0 33 33 22 22]
[ 0 0 0 0 33 33]
[ 0 0 0 0 33 33]]
(Note that the result is not a Toeplitz matrix; it is a block Toeplitz matrix.)
回答2:
Here's an alternative approach, for anyone interested in this problem
from pylab import *
import scipy.linalg
H1 = array([[11, 11], [11, 11]])
H2 = array([[22, 22], [22, 22]])
H3 = array([[33, 33], [33, 33]])
# Setup blocks
t = array([zeros_like(H1), H1, H2, H3])
# Create index to each block, using toeplitz
idx = scipy.linalg.toeplitz(r_[1, 2, 3, zeros(2)], r_[1, zeros(2)]).astype(int)
# Index into blocks, transpose and reshape to get re-ordered array
# copy is used to ensure memory is nicely ordered
T = t[idx].transpose(0, 2, 1, 3).reshape(10, 6).copy()
Most of the time is spent in scipy.linalg.toeplitz, making it slower than filling in memory in an array for the small matrices used here, so I'd recommend profiling before using this approach.
来源:https://stackoverflow.com/questions/36464191/toeplitz-matrix-of-toeplitz-matrix