I am going to make the following matrix:
s= [[s11 s12 s13]
[s21 s22 s23]
[s31 s32 s33]]
where I can obtain each array of the matrix s by:
sii = a(i) ; for s11, s22, and s33
sij = a(i)**2 + 10 ; for s12=s21, s23=s32, and s13=s31
here, ai is a list of data:
a = [0.1, 0.25, 0.12]
So when I use the following:
import numpy as np
s = np.ones([3,3])
def matrix(s):
a = [0.1, 0.25, 0.12]
s[np.diag_indices_from(s)] = ai
s[~np.eye(s.shape[0],dtype=bool)] = ai**2 + 10
It gives me an error. How can I solve this problem? Thanks.
Here is a hint for you on how to manipulate the diagonal and non-diagonal values.
import numpy as np
s = np.ones([3,3])
def matrix(s):
a = [1,2,3]
for i in range(len(a)):
s[i,i] = a[i] # sii = a(i)
rc = (i + 1) % len(a)
val = a[i] ** 2 + 10
s[i, rc] = val # sij = a(i)**2 + 10
s[rc, i] = val # sij = a(i)**2 + 10
return s
print(matrix(s))
input:
[[ 1. 1. 1.]
[ 1. 1. 1.]
[ 1. 1. 1.]]
output:
[[ 1. 11. 19.]
[ 11. 2. 14.]
[ 19. 14. 3.]]
Related
I am trying to calculate the inverse matrix using the Gauss-Jordan Method. For that, I need to find the solution X to A.X = I (A and X being N x N matrices, and I the identity matrix).
However, for every column vector of the solution matrix X I calculate in the first loop, I have to use the original matrix A, but I don't know why it keeps changing when I did a copy of it in the beginning.
def SolveGaussJordanInvMatrix(A):
N = len(A[:,0])
I = np.identity(N)
X = np.zeros([N,N], float)
A_orig = A.copy()
for m in range(N):
x = np.zeros(N, float)
v = I[:,m]
A = A_orig
for p in range(N): # Gauss-Jordan Elimination
A[p,:] /= A[p,p]
v[p] /= A[p,p]
for i in range(p): # Cancel elements above the diagonal element
v[i] -= v[p] * A[i,p]
A[i,p:] -= A[p,p:]*A[i,p]
for i in range(p+1, N): # Cancel elements below the diagonal element
v[i] -= v[p] * A[i,p]
A[i,p:] -= A[p,p:]*A[i,p]
X[:,m] = v # Add column vector to the solution matrix
return X
A = np.array([[2, 1, 4, 1 ],
[3, 4, -1, -1],
[1, -4, 7, 5],
[2, -2, 1, 3]], float)
SolveGaussJordanInvMatrix(A)
Does anyone know how turn A back to its original form after the Gauss-Elimination loop?
I'm getting
array([[ 228.1, 0. , 0. , 0. ],
[-219.9, 1. , 0. , 0. ],
[ -14.5, 0. , 1. , 0. ],
[-176.3, 0. , 0. , 1. ]])
and expect
[[ 1.36842105 -0.89473684 -1.05263158 1. ]
[-1.42105263 1.23684211 1.13157895 -1. ]
[ 0.42105263 -0.23684211 -0.13157895 -0. ]
[-2. 1.5 1.5 -1. ]]
I am trying to write PLU (LUP) decomposition using Gaussian elimination. I found this article with this algorithm:
def plu(A):
#Get the number of rows
n = A.shape[0]
#Allocate space for P, L, and U
U = A.copy()
L = np.eye(n, dtype=np.double)
P = np.eye(n, dtype=np.double)
#Loop over rows
for i in range(n):
#Permute rows if needed
for k in range(i, n):
if ~np.isclose(U[i, i], 0.0):
break
U[[k, k+1]] = U[[k+1, k]]
P[[k, k+1]] = P[[k+1, k]]
#Eliminate entries below i with row
#operations on U and #reverse the row
#operations to manipulate L
factor = U[i+1:, i] / U[i, i]
L[i+1:, i] = factor
U[i+1:] -= factor[:, np.newaxis] * U[i]
return P, L, U
With normal matrix it's running well but when on main diagonal appears 0 it breaks. For example with this matrix:
[[1, 0, 26, 10],
[60, 0, 75, 50],
[45, 90, 31, 100],
[30, 45, 10, 0]]
P
[[1. 0. 0. 0.]
[0. 0. 1. 0.]
[0. 1. 0. 0.]
[0. 0. 0. 1.]]
L
[[ 1. 0. 0. 0.]
[60. 1. 0. 0.]
[45. 0. 1. 0.]
[30. 0.5 0.13501684 1.]]
U
[[1. 0. 26. 10. ]
[0. 90. -1139. -350. ]
[0. 0. -1485. -550. ]
[0. 0. 0. -50.74074074]]
Multiplication of PLU will not give the original matrix.
So I tried to fix the algorithm: when rows swapping they are swapping only in P and U, so I add L[[k, k + 1]] = L[[k + 1, k]] in the inner loop to swap it in the L too. Also I changed the initialization of L: in the start I fill L with zeros L = np.zeros_like(A) and add identity matrix in the end L += np.eye(n, dtype=np.double).
But fixed version of algorithm give wrong result when top left element is 0. Any ideas what I'm doing wrong?
I think I fix it.
def get_plu_decomposition(A):
n = A.shape[0]
U = csr_matrix(A.copy())
L = csr_matrix(np.zeros_like(A))
P = csr_matrix(np.eye(n, dtype=np.double))
for i in range(n - 1):
index = np.argmax(abs(U[i:, i]))
if not U[i:, i][index] != 0:
continue
index += i
if index != i:
U[[index, i]] = U[[i, index]]
P[[index, i]] = P[[i, index]]
L[[index, i]] = L[[i, index]]
factor = U[i + 1:, i] / U[i, i]
L[i + 1:, i] = factor
U[i + 1:] -= factor * U[i]
L += csr_matrix(np.eye(n, dtype=np.double))
P = P.transpose()
assert (np.allclose(A, (P#L#U).toarray()))
return P, L, U
The problem was in swapping rows and transposing P matrix
here is my matrix setup:
for a in b:
size_x = len(a) + 1
size_y = len(b) + 1
matrix = np.zeros ((size_x, size_y))
for x in range(size_x):
matrix [x, 0] = x
for y in range(size_y):
matrix [0, y] = y
for x in range(1, size_x):
for y in range(1, size_y):
if a[x-1] == b[y-1]:
matrix [x,y] = min(
matrix[x-1, y] + 1,
matrix[x-1, y-1],
matrix[x, y-1] + 1
)
else:
matrix [x,y] = min(
matrix[x-1,y] + 1,
matrix[x-1,y-1] + 1,
matrix[x,y-1] + 1
)
print(matrix)
This would give outputs such as
t e s t
[[ 0. 1. 2. 3. 4.]
t [ 1. 0. 1. 2. 3.]
e [ 2. 1. 0. 1. 2.]
x [ 3. 2. 1. 1. 2.]
t [ 4. 3. 2. 1. 1.]]
In which the bottom right-hand corner is the final value. How do I take this out and add it to a list?
You can access the ith index of an array arr by using this expression: arr[i] .
In order to answer your question -> accessing the bottom-right value of a 2d matrix simply use,
matrix[matrix.length-1][matrix[matrix.length-1].length-1]
or better
lastRowIndex = matrix.length-1;
lastColIndex = matrix[lastRowIndex].length-1;
bottomRightValue = matrix[lastRowIndex][lastColIndex]
I found some problems in calculating the symmetric normalised laplacian matrix in python.
Suppose to have the matrix S and its diagonal degree matrix D:
[ [ 1 , 0.5, 0.2] [ [1.7, 0, 0 ]
S = [0.5, 1 , 0.5] D = [ 0 , 2, 0 ]
[0.2, 0.5, 1 ] ] [ 0 , 0,1.7] ]
When calculating L as
I obtain this result:
[[ 0.41176471 -0.27116307 -0.11764706]
L = [-0.27116307 0.5 -0.27116307]
[-0.11764706 -0.27116307 0.41176471]]
Using this code:
S = np.array([[1,0.5,0.2],[0.5,1,0.5],[0.2,0.5,1]])
print("Similiarity Matrix: \n",S)
print("\n\n")
D = np.zeros((len(S), len(S)))
#H = np.sum(G[0])
for id, x in enumerate(S):
D[id][id] = np.sum(x)
I = np.identity(len(S))
L = I - ((sqrtm(inv(D))).dot(S)).dot(sqrtm(inv(D)))
print("\n\n")
print("Laplacian normalized: \n",L)
This differ from using the function csgraph.laplacian(S, normed=True) that return:
[[[ 1. -0.5976143 -0.28571429]
L = [-0.5976143 1. -0.5976143 ]
[-0.28571429 -0.5976143 1. ]]
why this happen? Am i doing something wrong?
I noticed that the ratio between the unnormalized and normalized matrixes returned by csgraph.laplacian is closely related to the ratio of the unnormalized matrix and your L:
In [20]: csgraph.laplacian(S, normed=False) / L - 1
Out[20]:
array([[0.7 , 0.84390889, 0.7 ],
[0.84390889, 1. , 0.84390889],
[0.7 , 0.84390889, 0.7 ]])
In [21]: csgraph.laplacian(S, normed=False) / csgraph.laplacian(S, normed=True)
Out[21]:
array([[0.7 , 0.83666003, 0.7 ],
[0.83666003, 1. , 0.83666003],
[0.7 , 0.83666003, 0.7 ]])
0.84390889 ≠ 0.83666003 but other numbers match. Could the difference be simply due to normalization?
That's because you have 1s in the diagonal of S:
# weighted adjacency
S = np.array([[1,0.5,0.2],[0.5,1,0.5],[0.2,0.5,1]])
np.fill_diagonal(S, 0.0)
# strength diagonal matrix
D = np.diag(np.sum(S,axis=1))
# identity
I = np.identity(S.shape[0])
# D^{-1/2} matrix
D_inv_sqrt = np.linalg.inv(np.sqrt(D))
L = I - np.dot(D_inv_sqrt, S).dot(D_inv_sqrt)
L
array([[ 1. , -0.5976143 , -0.28571429],
[-0.5976143 , 1. , -0.5976143 ],
[-0.28571429, -0.5976143 , 1. ]])
I'm trying to constrain the values of a numpy array so that no values lie between -0.5 and 0.5. So if I had an array shaped (6,2) with values like this:
array([[ 0.49873803, -1.66316398],
[ -0.36091764, 2.0635736 ],
[ -1.09922111, -2.49380792],
[ 0.92724579, -5.19540319],
[ 1.49726584, -0.22718924],
[ 60. , 60. ]])
How can I get numpy to change the values that are from -0.5 -> 0.0 to be -0.5, and
from 0.5 -> 0.0 to be 0.5 so that the example array would be:
array([[ 0.5, -1.66316398],
[ -0.5, 2.0635736 ],
[ -1.09922111, -2.49380792],
[ 0.92724579, -5.19540319],
[ 1.49726584, -0.5],
[ 60. , 60. ]])
I tried using np.clip but that didnt work, or I couldn't figure it out, so here I am!
For your a just run:
a[( 0. <= a) & (a < 0.5)] = 0.5
a[(-0.5 < a) & (a < 0. )] = -0.5
or simply:
np.putmask(a, np.abs(a) < .5, np.sign(a) * .5)
The first one can be adjusted to handle 0. according to your needs. The second one leaves it to 0.
Have you tried just iterating through the Array?
i = 0
j = 0
while ( i < len(A)):
while (j < len(i)):
if -0.5 <= A[i][j] <= 0:
A[i][j] = -0.5
if 0 <= A[i][j] <= 0.5:
A[i][j] = 0.5
j = j + 1
i = i +1
Or something like that... forgive me if the syntax isn't all right...