checking if a matrix is diagonally dominant in python - python

I know that my code is wrong because np.sum(abs(X),axis=1)) also sums the diagonal value, therefore my code will always return 'NOT diagonally dominant'. I have tried putting '-np.diag(X)' but i get an error message. Thank you in advance!
import numpy as np
A=np.array([[ 40., 7., 5.],
[ 5., 90., 7.],
[20., 7., 50.]])
def dd(X):
Sum_values_in_given_row = np.sum(abs(X),axis=1)
if np.all(((abs(np.diag(X)))) >= np.sum(abs(X),axis=1)):
print 'matrix is diagonally dominant'
else:
print 'NOT diagonally dominant'
return
dd(A)

To determine if a matrix is diagonally dominant, you have to check if the sum of the row coefficients excluding the diagonal coefficient is larger than the diagonal coefficient. Obviously you take the absolute values as part of the test. You are not doing this and you are including the diagonal coefficient instead. As you mentioned, you should subtract this the summation of each element with the diagonal coefficient to ensure the check is correct, but you didn't put that in your code for some reason:
def dd(X):
D = np.diag(np.abs(X)) # Find diagonal coefficients
S = np.sum(np.abs(X), axis=1) - D # Find row sum without diagonal
if np.all(D > S):
print 'matrix is diagonally dominant'
else:
print 'NOT diagonally dominant'
return
Note that the code takes advantage of broadcasting to facilitate subtracting the row sums with the corresponding diagonal coefficient.

The matrix A is diagonally dominant if |Aii| ≥ ∑j≠i |Aij|, or equivalently, 2|Aii| ≥ ∑j |Aij|.
def is_diagonally_dominant(x):
abs_x = np.abs(x)
return np.all( 2*np.diag(abs_x) >= np.sum(abs_x, axis=1) )
# ^^

What's wrong with
matrix = [[ 40., 7., 5.],
[ 5., 90., 7.],
[20., 7., 50.]]
def dd(mat):
for numb, i in enumerate(mat):
if mat[numb][numb]<sum(i)-mat[numb][numb]:
return False
return True
print(dd(matrix))

Related

Creating a NumPy array out of another array with shifted indices

I would like to produce a 4D array from a 2D one by periodic shifts, in a way that can be summarized by the following:
uuvv[kx,ky,qx,qy] = uu[kx+qx,ky+qy]
This is easiest to illustrate with a "2D from 1D" MWE:
def pc(idx):
return idx - Npts*int(idx/Npts)
uu = np.square(np.arange(Npts))
uv = np.zeros((Npts,Npts))
for kx in np.arange(Npts):
for qx in np.arange(Npts):
uv[kx,qx] = uu[pc(kx+qx)]
Here, the periodicity condition pc just brings the index back into the allowed range. The output for Npts=4 is:
array([[0., 1., 4., 9.],
[1., 4., 9., 0.],
[4., 9., 0., 1.],
[9., 0., 1., 4.]])
So that each value is shifted slightly. For the "4D from 2D" case, I could obviously use:
def pbc(idx):
return idx - Npts*int(idx/Npts)
uv = np.zeros((Npts,Npts,Npts,Npts))
for kx in np.arange(Npts):
for ky in np.arange(Npts):
for qx in np.arange(Npts):
for qy in np.arange(Npts):
uv[kx,ky,qx,qy] = uu[pbc(kx+qx),pbc(ky+qy)]
However, using four loops is going to be slow, as I will be doing this multiple times for much larger arrays. How can I do this more efficiently?
Please note that, although the MWE example could be reproduced by applying the square function to a 2D array, that would not be a helpful solution. Using the MWE to illustrate, the goal is to apply the function as few times as possible (i.e. only on the 1D array) and then to create the 2D array without for loops. Ultimately, I will need to do this to generate a 4D array from a 2D array. How can I do this?
You can replicate the 2D array and then extract the shifted 2D sub-arrays (avoiding modulus and conditionals). Here is how to do that:
uuRep = np.tile(uu, (2,2))
uv = np.zeros((Npts,Npts,Npts,Npts))
for kx in np.arange(Npts):
for ky in np.arange(Npts):
uv[kx,ky,:,:] = uuRep[kx:kx+Npts,ky:ky+Npts]
With Npts=64, this solution is about 1000 times faster.

Numpy: select along axis of 3d array using 2d array

I've been struggling with this for a few hours and can't quite get my head around it. The setup is something like this:
A.shape # (T,N,K)
B.shape # (L,K) L < N
Each of the K columns of the 2D B array index one of the N columns along that same K row. I can grab along any specific k slice easily via
A[:,B[:,k],k].shape # (T,L)
However, looping over K isn't ideal because A is a very large matrix
I'm sure someone has a really simple answer, but I am stumped.
Edit: I should also add that I need to preserve the 3D structure of the A matrix. I figured out how to grab the individual values, but only in a (TxLxK,) array.
You can use np.take_along_axis
np.take_along_axis(A,B[None,...],axis=1)
For example,
A = np.linspace(1,24,24).reshape(3,4,2)
B = np.repeat([[0,1]],3,axis=0)
np.take_along_axis(A,B[None,...],axis=1)
the result is
array([[[ 1., 4.],
[ 1., 4.],
[ 1., 4.]],
[[ 9., 12.],
[ 9., 12.],
[ 9., 12.]],
[[17., 20.],
[17., 20.],
[17., 20.]]])

How to implement a certain operation on some specific bins of histogram?

In the following code hist shows the values of counts of a histogram. In to implement certain operation only on the bins having counts grater than zero and grater than 1. But when I store the files and print E_bin it also prints the empty arrays which is because it considers hist having values zero. How can I overcome this problem and store only those files where hist values are grater than 0 and one?
`hist: [3., 0., 0., 0., 0., 0., 1,. 2., 0., 3.]
for j in range(len(hist)):
val =hist[j]
E_bin =[]
for k in range(len(w)):
if j<len(hist)-1 and val>0 and bin_edges[j]<= w[k] <bin_edges[j+1]:
E_bin.append(w[k])
elif j==len(hist)-1 and val>0 and bin_edges[j]<= w[k]<=
bin_edges[j+1]:
E_bin.append(w[k])
E_bin = np.array(E_bin)
print("E_bin: ",E_bin)
np.save("./InputData/Samples/Sample_%s_bin_%s"%(i,j),E_bin)`
use numpy.nonzero to get the indices of values which are non zero and implement your logic on that.
for i in np.nonzero(hist):
#rest of the code

python how to get proper distance value out of scipy condensed distance matrix

I am using python 2.7 with scipy to calculate a distance matrix for an array.
I don't get how to find the wanted distance values in the returned condensed matrix.
See example
from scipy.spatial.distance import pdist
import numpy as np
a = np.array([[1],[4],[0],[5]])
print a
print pdist(a)
will print
[ 3. 1. 4. 4. 1. 5.]
I found here that the ij entry in the condensed matrix should store the distance between the i and j entries where ithread wondering if they mean ij as i*j or str.join(i,j) e.g 1,2 -> 2 or 12.
I can't find a consistent way to know the wanted index.
see my example, you should expect that all of the distances from entry 0 to anywhere else will be stored in entry 0 if the first option is valid.
can anyone shed some light on how can i extract my wanted distance from entry x to entry y? which index am i looking for?
Thanks!
This vector is in condensed form. It enumerates all pairs of indices in a natural order (in your example 0,1 0,2 0,3 0,4 1,2 1,3 1,4 2,3 2,4 ) and yields the distance between the elements at these array entries.
There is also the squareform function, which transforms the condensed form into a square matrix form (and vice versa). The square matrix form is exactly what you expect, i.e. at entry ij (row i, column j), it stores the distance between the i-th and j-th entry. For example, if you add print squareform(d) at the end of you code, the output will be:
array([[ 0., 3., 1., 4.],
[ 3., 0., 4., 1.],
[ 1., 4., 0., 5.],
[ 4., 1., 5., 0.]])

Finding upper/lower triangular form of arbitrary matrix n*n - python

every matrix can be written in upper or lower triangular form simply just by rotating the basis. Is there a simple routine in python (numpy) to do it? I was unable to find it and I cant believe that there is no such thing. To ilustrate it:
matrix = numpy.array([[a,b,c],
[d,e,f],
[g,h,i]])
to
matrix2 = numpy.array([[z,0,0],
[y,x,0],
[v,u,t]])
letters are floats. So how to make this change, but not simply just by zeroing numbers b, c and f, but by correct rotation of basis in the most simple way.
Thank you!
You are looking for Schur decomposition. Schur decomposition decomposes a matrix A as A = Q U Q^H, where U is an upper triangular matrix, Q is a unitary matrix (which effects the basis rotation) and Q^H is the Hermitian adjoint of Q.
import numpy as np
from scipy.linalg import schur
a = np.array([[ 1., 2., 3.], [4., 5., 6.], [7., 8., 9.]])
u, q = schur(a) # q is the unitary matrix, u is upper triangular
repr(u)
# array([[ 1.61168440e+01, 4.89897949e+00, 1.58820582e-15],
# [ 0.00000000e+00, -1.11684397e+00, -1.11643184e-15],
# [ 0.00000000e+00, 0.00000000e+00, -1.30367773e-15]])

Categories

Resources