0

I am just learning python and want to define a function that returns a nxn square matrix, with predefined values for the main diagonal(i=j), upper diagonal (j=i+1)and lower diagonal (j=i-1) and all other elements to be equal 0.

Any help would be appreciated,

thanks


import numpy as np 
import scipy as sp 
n=6 
m=np.zeros((n,n)) 
for i in range(n): 
    m[i-1,i]=-1 
    m[i,i]=2 
    m[i,i-1]=1 
    m[0,n-1]=0 
    m[n-1,0]=0 
print m
4
  • Post the code that you have tried. Commented Mar 17, 2017 at 5:29
  • import numpy as np import scipy as sp n=6 m=np.zeros((n,n)) for i in range(n): m[i-1,i]=-1 m[i,i]=2 m[i,i-1]=1 m[0,n-1]=0 m[n-1,0]=0 print m Commented Mar 17, 2017 at 6:04
  • I moved your code to the question. It formats better there. Commented Mar 17, 2017 at 6:10
  • scipy.sparse has a couple of ways of setting multiple diagonals at once. The numpy.diag sets one diagonal at a time, but otherwise is easy to use. Commented Mar 17, 2017 at 6:12

2 Answers 2

2

If a,b,c are your three list for the upper diagonal, main diagonal, and lower diagonal respectively, you can write it as follows:

import numpy as np
a=[1,2,3,4]
b=[5,6,7,8,9]
c=[10,11,12,13]
n=len(b)
m=np.zeros((n,n))
for i in range(0,n-1):
    m[i,i+1]=a[i]
    m[i,i]=b[i]
    m[i+1,i]=c[i]
m[n-1,n-1]=b[n-1]
print(m)

In the code above you initialize a zero matrix, and then update only the upper,lower, and main diagonal entries according to your lists. The output is

[[  5.   1.   0.   0.   0.]
 [ 10.   6.   2.   0.   0.]
 [  0.  11.   7.   3.   0.]
 [  0.   0.  12.   8.   4.]
 [  0.   0.   0.  13.   9.]]

Edit: A shorter way, suggested by @hpaulj would be

m=np.diag(a,1)+np.diag(b,0)+np.diag(c,-1)

np.diag(r,k) create a matrix in which the k'th diagonal above the main diagonal (below if k is negative) is r and the rest of the entries are 0.

See documentation here: https://docs.scipy.org/doc/numpy/reference/generated/numpy.diag.html

Sign up to request clarification or add additional context in comments.

2 Comments

Play with np.diag(a,1)+np.diag(b,0)+np.diag(c,-1)
@hpaulj nice trick.. But, I guess this only works fine if the off-diagonal elements are zeros
0

Here's a method that takes in a list of items to add on the diagonal, using numpy.diag and taking advantage of the k parameter to specify which diagonal we want to modify.

import numpy as np

def create_diag(n, l):
    arr = np.zeros((n, n))

    # check that l contains an odd number of elements
    if len(l) % 2 != 1:
        return arr

    # check that we have at most the number of diagonals in the matrix
    if len(l) >= 2*n:
        return arr

    # set limits of diagonals to set. setting 3 diagonals means limits=[-1,0,1]. setting 1 diagonal means limits=[0]
    limit = int((len(l) - 1) / 2)
    limits = range(-limit, limit + 1)

    # maps k-->list of values on the diagonal
    diag_map = dict(zip(limits, l))
    for k, v in diag_map.items():
        diag = [v] * (n - abs(k))
        arr += np.diag(diag, k=k)
    return arr

# elements to put on the diagonal, centered about the main diagonal (i=j)
l = [-1,1,2]
n = 6

diag_arr = create_diag(n, l)

# [[ 1.  2.  0.  0.  0.  0.]
#  [-1.  1.  2.  0.  0.  0.]
#  [ 0. -1.  1.  2.  0.  0.]
#  [ 0.  0. -1.  1.  2.  0.]
#  [ 0.  0.  0. -1.  1.  2.]
#  [ 0.  0.  0.  0. -1.  1.]]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.