Reputation: 417
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
Upvotes: 0
Views: 57
Reputation: 53119
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]]
Upvotes: 1
Reputation: 1696
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]])
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.]])
Upvotes: 0