Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Block tridiagonal matrix python

I would like to create a block tridiagonal matrix starting from three numpy.ndarray. Is there any (direct) way to do that in python?

Thank you in advance!

Cheers

like image 587
Matteo Parsani Avatar asked Apr 30 '11 15:04

Matteo Parsani


People also ask

Is tridiagonal a matrix?

In linear algebra, a tridiagonal matrix is a band matrix that has nonzero elements only on the main diagonal, the subdiagonal/lower diagonal (the first diagonal below this), and the supradiagonal/upper diagonal (the first diagonal above the main diagonal).

What is tridiagonal matrix in data structure?

A tridiagonal matrix has nonzero elements only on the main diagonal, the diagonal upon the main diagonal, and the diagonal below the main diagonal. This special structure appears often in scientific computing and computer graphics [1, 2].

Is tridiagonal matrix invertible?

Let T be a tridiagonal operator on which has strict row and column dominant property except for some finite number of rows and columns. This matrix is shown to be invertible under certain conditions.


3 Answers

With "regular" numpy arrays, using numpy.diag:

def tridiag(a, b, c, k1=-1, k2=0, k3=1):
    return np.diag(a, k1) + np.diag(b, k2) + np.diag(c, k3)

a = [1, 1]; b = [2, 2, 2]; c = [3, 3]
A = tridiag(a, b, c)
like image 108
TheCorwoodRep Avatar answered Sep 19 '22 12:09

TheCorwoodRep


Use the function scipy.sparse.diags.

Example:

from scipy.sparse import diags
import numpy as np

n = 10
k = [np.ones(n-1),-2*np.ones(n),np.ones(n-1)]
offset = [-1,0,1]
A = diags(k,offset).toarray()

This returns:

array([[-2.,  1.,  0.,  0.,  0.],
       [ 1., -2.,  1.,  0.,  0.],
       [ 0.,  1., -2.,  1.,  0.],
       [ 0.,  0.,  1., -2.,  1.],
       [ 0.,  0.,  0.,  1., -2.]])
like image 44
Pink Flying Elephant Avatar answered Sep 20 '22 12:09

Pink Flying Elephant


You can also do this with "regular" numpy arrays through fancy indexing:

import numpy as np
data = np.zeros((10,10))
data[np.arange(5), np.arange(5)+2] = [5, 6, 7, 8, 9]
data[np.arange(3)+4, np.arange(3)] = [1, 2, 3]
print data

(You could replace those calls to np.arange with np.r_ if you wanted to be more concise. E.g. instead of data[np.arange(3)+4, np.arange(3)], use data[np.r_[:3]+4, np.r_[:3]])

This yields:

[[0 0 5 0 0 0 0 0 0 0]
 [0 0 0 6 0 0 0 0 0 0]
 [0 0 0 0 7 0 0 0 0 0]
 [0 0 0 0 0 8 0 0 0 0]
 [1 0 0 0 0 0 9 0 0 0]
 [0 2 0 0 0 0 0 0 0 0]
 [0 0 3 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0]]

However, if you're going to be using sparse matrices anyway, have a look at scipy.sparse.spdiags. (Note that you'll need to prepend fake data onto your row values if you're placing data into a diagonal position with a positive value (e.g. the 3's in position 4 in the example))

As a quick example:

import numpy as np
import scipy as sp
import scipy.sparse

diag_rows = np.array([[1, 1, 1, 1, 1, 1, 1],
                      [2, 2, 2, 2, 2, 2, 2],
                      [0, 0, 0, 0, 3, 3, 3]])
positions = [-3, 0, 4]
print sp.sparse.spdiags(diag_rows, positions, 10, 10).todense()

This yields:

[[2 0 0 0 3 0 0 0 0 0]
 [0 2 0 0 0 3 0 0 0 0]
 [0 0 2 0 0 0 3 0 0 0]
 [1 0 0 2 0 0 0 0 0 0]
 [0 1 0 0 2 0 0 0 0 0]
 [0 0 1 0 0 2 0 0 0 0]
 [0 0 0 1 0 0 2 0 0 0]
 [0 0 0 0 1 0 0 0 0 0]
 [0 0 0 0 0 1 0 0 0 0]
 [0 0 0 0 0 0 1 0 0 0]]
like image 28
Joe Kington Avatar answered Sep 19 '22 12:09

Joe Kington