Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mapping a 2d delay vector from a 1d vector in numpy

I am trying to generate a 2D vector from a 1D vector where the element is shifted along the row by an increment each row.

i would like my input to look like this:

input:
t = [t1, t2, t3, t4, t5]

out = 
[t5,  0,  0,  0,  0]
[t4, t5,  0,  0,  0]
[t3, t4, t5,  0,  0]
[t2, t3, t4, t5,  0]
[t1, t2, t3, t4, t5]
[ 0, t1, t2, t3, t4]
[ 0,  0, t1, t2, t3]
[ 0,  0,  0, t1, t2]
[ 0,  0,  0,  0, t1]

im unaware of a way to do this without using a for loop, and computational efficieny is important for the task im using this for. Is there a way to do this without a for loop?

this is my code using a for loop:

import numpy as np

t = np.linspace(-3, 3, 7)
z = np.zeros((2*len(t) - 1, len(t)))

diag = np.arange(len(t))
for index, val in enumerate(np.flip(t, 0)):
    z[diag + index, diag] = val

print(z)
like image 617
zonzon510 Avatar asked Jul 01 '18 00:07

zonzon510


1 Answers

What you're asking for here is known as a Toeplitz Matrix, which is:

a matrix in which each descending diagonal from left to right is constant

The one difference is that you want the lower triangle of your matrix.

You happen to be in luck, you can use scipy.linalg.toeplitz to construct your matrix, and then np.tril to access the lower triangle.

import numpy as np
from scipy.linalg import toeplitz

v = np.array([1, 2, 3, 4, 5])
t = np.pad(v[::-1], (0, 4), mode='constant')

Solve the matrix and access the lower triangle:

np.tril(toeplitz(t, v))

And our output!

array([[5, 0, 0, 0, 0],
       [4, 5, 0, 0, 0],
       [3, 4, 5, 0, 0],
       [2, 3, 4, 5, 0],
       [1, 2, 3, 4, 5],
       [0, 1, 2, 3, 4],
       [0, 0, 1, 2, 3],
       [0, 0, 0, 1, 2],
       [0, 0, 0, 0, 1]])

To generalize this method, simply calculate the necessary padding for t from the shape of v:

v = # any one dimension array
t = np.pad(v[::-1], (0, v.shape[0]-1), mode='constant')
like image 109
user3483203 Avatar answered Oct 13 '22 00:10

user3483203