targeting jth-kth element in a matirx using python

Viewed 63

enter image description here

I would like to implement a matrix that satisfies the conditions shown in the image:

  1. The matrix is an m * n matrix
  2. The j, kth element will be 1 if either the kth index is j + 1 or kth index is 2 or the jth index is 2

Here is my latest code:

self.ylmaxvect = [1, 2, 3, 4]
self.ylmax = int(input('inputylmax'))
self.An = sum(self.ylmaxvect)
self.Am = sum(self.ylmaxvect)

# -------------declare a zero matrix first------------------------ #
self.matAL = np.zeros((self.An, self.Am))
for i in range(self.An - 1):
    if self.matAL[i][i + 1] == 0:
        if i  == self.ylmax:
            self.matAL[i][i + 1] = 1
        else:
   self.matAL[i][i + 1] = 0 
4 Answers

You're overthinking this. Start with

A = np.zeros((m, n))

The condition k = j + 1 is just the first diagonal above the main one. You can use np.fill_diagonal for that:

np.fill_diagonal(A[:, 1:], 1)

This works because the slice A[:, 1:] is a view into the original matrix, and therefore any modifications to it are visible in the underlying matrix.

The conditions k = 2 and j = 2 are just slices across the appropriate dimension:

A[:, 1] = 1
A[1, :] = 1

I'm assuming that your matrix notation is one-based, while numpy is zero based. If not, change the ones in the index to two.

You can visualize what fill_diag is doing by generating the j and k indices yourself. k goes 1, 2, 3, .... j goes 0, 1, 2, .... How far do they go? Well, the lesser of m - 1 and n, since it depends on the shape:

j = np.arange(min(m - 1, n))
k = j + 1
A[j, k] = 1

If you want to use loops, you can do this in O(m + n) rather than O(m * n) time. The key is that you know where the ones go: you don't need to check each element:

for j in range(m):
    A[j, 2] = A[j, j + 1] = 1
for k in range(n):
    A[2, k] = 1

A slightly less numpy-specific method:

import numpy as np

m = int(input("m: "))
n = int(input("n: "))
mat = np.zeros((m,n))
for j in range(0, m):
    for k in range(0, n):
        if (k == j + 1) or k == 2 or j == 2:
            mat[j, k] = 1
print(mat)

You could also flatten the array and explicitly update the values:

import numpy as np
m,n     = 14,9
D       = np.arange(n,min(n**2+n,n*m),n+1)
X       = np.zeros(m*n,'int')
X[D]    = 1
X.shape = (m,n)
X[:,2]  = 1
X[2,:]  = 1
print(X)

creating a zeros array

>>> m, n = 5, 4
>>> 
>>> 
>>> arr = np.zeros(shape= [m, n])
>>> arr
array([[0., 0., 0., 0.],
       [0., 0., 0., 0.],
       [0., 0., 0., 0.],
       [0., 0., 0., 0.],
       [0., 0., 0., 0.]])

assigning 1 to second row and column, and to the main diagonal offset by 1

>>> arr[2, :] = 1
>>> arr[:, 2] = 1
>>> arr.ravel()[1::n+1] = 1
>>> 
>>> arr
array([[0., 1., 1., 0.],
       [0., 0., 1., 0.],
       [1., 1., 1., 1.],
       [0., 0., 1., 0.],
       [1., 0., 1., 0.]])

Related