简体   繁体   中英

Generate specific matrix using numpy

say n = 4:

then i want to generate the following matrix:

1 0 0 0  1 0 0 1  1 0 1 1
0 1 0 0  1 1 0 0  1 1 0 1
0 0 1 0  0 1 1 0  1 1 1 0
0 0 0 1  0 0 1 1  0 1 1 1

which you can get by appending 3 matrices, (A0, A1, A2) horizontaly

if I'=

0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0

then:

A0 = I'^0
A1 = I'^1 + I'^0
A2 = I'^2 + I'^1 + I'^0

how can i achieve this efficiently using numpy for any n?

EDIT:

when n = 3 for ex

I' would become

0 0 1
1 0 0
0 1 0

and the desired result would be A0 appended to A1

You can use the modulo operator:

>>> n = 4
>>> i,j,k = np.ogrid[:n, :n-1, :n]
>>> ((j-i+k)%n <= j).reshape(n, -1).view(np.int8)
array([[1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1],
       [0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1],
       [0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0],
       [0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1]], dtype=int8)

Sandwiched between columns of 0 s and 1 s:

>>> i, jk = np.ogrid[:n, :n*n - n + 2]
>>> j, k = divmod(jk + n - 1, n)
>>> print(((j-i+k-1)%n < j).view(np.int8))
[[0 1 0 0 0 1 0 0 1 1 0 1 1 1]
 [0 0 1 0 0 1 1 0 0 1 1 0 1 1]
 [0 0 0 1 0 0 1 1 0 1 1 1 0 1]
 [0 0 0 0 1 0 0 1 1 0 1 1 1 1]]

Using some list comprehensions (I assume you know that concept, otherwise please google it, it's really helpful in this case) and np.linalg.matrix_power , np.sum and np.concatenate :

In [47]: n = 4
In [48]: np.concatenate(
    ...:     [
    ...:         np.sum(
    ...:             [np.linalg.matrix_power(I, i) for i in range(exp+1)],
    ...:             axis=0  # sum them correct over the axis not the whole data
    ...:         )
    ...:         for exp in range(n-1)
    ...:     ],
    ...:     axis=1  # concat horizontal not vertical
    ...: )
Out[48]:
array([[1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1],
       [0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1],
       [0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0],
       [0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1]])

This variably works with other n values too:

In [49]: n = 5
In [50]: np.concatenate(
    ...:     [
    ...:         np.sum([np.linalg.matrix_power(I, i) for i in range(exp+1)], axis=0)
    ...:         for exp in range(n-1)
    ...:     ], axis=1)
Out[50]:
array([[1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1],
       [0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1],
       [0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1],
       [0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1]])

In [51]: n = 3
In [52]: np.concatenate(
    ...:     [
    ...:         np.sum([np.linalg.matrix_power(I, i) for i in range(exp+1)], axis=0)
    ...:         for exp in range(n-1)
    ...:     ], axis=1)
Out[52]:
array([[1, 0, 0, 0, 1, 0, 0, 1],
       [0, 1, 0, 0, 1, 1, 0, 0],
       [0, 0, 1, 0, 0, 1, 1, 0],
       [0, 0, 0, 1, 0, 0, 1, 1]])

EDIT:

You can generate your I like requested with eye:

In [68]: n=3

In [69]: I = np.eye(n, k=-1) + np.eye(n, k=n-1)

In [70]: I
Out[70]:
array([[0., 0., 1.],
       [1., 0., 0.],
       [0., 1., 0.]])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM