How to find sum of neighbor elements in a matrix - python

I am trying to find the sum of neighbors around an element in a matrix and wrote few functions to convert a boolean matrix to 1s and 0s and finding the neighbors. But I'm not sure why it is throwing the following error
matrix=[[True,False,False],[False,True,False],[False,False,False]]
def minesweeper(matrix):
matrix=[[1 if j==True else 0 for j in i] for i in matrix]
bin_mt = matrix.copy()
print(bin_mt)
for i in range(len(matrix)):
for j in range(len(matrix[0])):
matrix[i][j]=get_neighbors(i,j,matrix, bin_mt)
print('matrix: '+str(matrix))
print('bin_mt: '+str(bin_mt))
print(matrix)
return matrix
def get_neighbors(a, b, matrix, bin_mt):
sum=0
if bin_mt[a][b]==1:
return 1
else:
for i in find_neighbor_indices(matrix,a,b):
print(bin_mt[i[0]][i[1]], end=' ')
sum=sum+bin_mt[i[0]][i[1]]
print('--')
return sum
def find_neighbor_indices(matrix, i, j, dist=1):
neighbors = []
irange = range(max(0,i-dist), min(len(matrix), i+dist+1))
if len(matrix) > 0:
jrange = range(max(0, j - dist), min(len(matrix[ 0 ]), j + dist + 1))
else:
jrange = []
for icheck in irange:
for jcheck in jrange:
if icheck != i or jcheck != j:
neighbors.append((icheck, jcheck))
return neighbors
minesweeper(matrix)
PS: I have updated the code. However I created a matrix containing 1's and 0's for comparision and sum of neighbors. But I'm not sure why it is updating the both bin_mat and actual matrix instead of just actual matrix. Could someone help me with that.

No worries. I figured it out. The issue was binary matrix is a shallow copy of actual matrix. Whatever the changes I was making in actual matrix were getting updated in binary matrix. I needed a deep copy instead of shallow.
Solved it using below code.
import copy
bin_mt = copy.deepcopy(matrix)
instead of
bin_mt = matrix.copy()

Related

sparse matrix multipliction with dictionaris in python

A sparse matrix is a matrix whose most members have zero value. Therefore, in order to save memory and storage
The matrices, it is convenient to represent them using a dictionary in the following configuration: for each cell in the matrix that is not zero, a tuple key will be stored in the dictionary
which represents the coordinates of the cell, and the value represents the value of the cell in the matrix (some number of type int or float) as usual in mathematics,
The indices of the matrix start from one.
• The cell coordinate (j, i) contains natural numbers so that the coordinate represents the cell in the i-th row
and in the jth column.
• The order in the dictionary is not important.
Realize the function sparse_mult(n, mat2, mat1) which receives 2 dictionaries, mat1 and mat2, representing square sparse matrices
of size n×n, and returns a dictionary representing the mat2×mat1 matrix multiplication matrix.
pay attention:
There is no need to check the correctness of the matrices.
It can be assumed that n is a natural number < 1.
The repeated dictionary must represent a sparse matrix as defined above.
for i in range(1, n + 1):
temp = 0
for j in range(1, n + 1):
if (mat1.get((i, j), 0) != 0)|(mat2.get((j, i), 0) != 0):
temp += mat1.get((i, j), 0) * mat2.get((j, i), 0)
if temp !=0:
resultrow[(i, i)]=temp
That's my code, I know I got it wrong but i just don't have a clue
It is inefficient to iterate over all indices in the 2-dimensional index set when multiplying two sparse matrices. Instead, you can iterate over all pairs of keys where 1 pair is drawn from each sparse matrix. Given such a pair (i,j) and (k,l), it contributes a product of 2 numbers if and only if j == k. In this case the corresponding product goes towards entry (i,l) in the overall product. A final dictionary comprehension can get rid of any zero entries. This last step might be inadequate if the numbers are floats and some entries are non-zero only due to round-off error. In that case a threshold approach which removes entries close to zero and not merely equal to zero.
def sparse_multiply(a,b):
c = {}
for i,j in a.keys():
for k,l in b.keys():
if j == k:
p = a[(i,j)]*b[(k,l)]
if (i,l) in c:
c[(i,l)] += p
else:
c[(i,l)] = p
return {k:v for k,v in c.items() if v != 0}
Note that n plays no role here. The complexity is mk where m is the number of non-zero entries in the first matrix and k the number of such entries in the second. For matrices which are very sparse this will be substantially faster than the n^3 of using straight-forward matrix multiplication. There will be some threshold where mk will actually be larger than n^3, but at that stage the matrices are no longer sparse.
so i eventually got it, if anyone care:
initialize the result dictionary
result = {}
# iterate over the rows and columns of the result matrix
for i in range(1, n + 1):
for j in range(1, n + 1):
# initialize the sum to 0
sum = 0
# iterate over the columns of the first matrix and the rows of the second matrix
for k in range(1, n + 1):
# check if the cell (i, k) in the first matrix and the cell (k, j) in the second matrix are non-zero
if (i, k) in mat1 and (k, j) in mat2:
sum += mat1[(i, k)] * mat2[(k, j)]
# add the result to the dictionary if it is non-zero
if sum != 0:
result[(i, j)] = sum
# return the result dictionary
return result

Transpose of a matrix showing same results as original

I am trying to transpose the matrix but getting the same matrix, this seems to be happening everytime and what is more confusing is that the element of list are swapped but not on this instance.
What is problematic is that I see no change in the end result as the swapping was made for nXn times in the loop.
inp = int(input())
mat = []
for i in range(inp):
submat = list(map(int,input().split(',')))
mat.append(submat)
print(mat)
for i in range(len(mat)):
for j in range(len(mat[0])):
mat[i][j],mat[j][i] = mat[j][i],mat[i][j]
print(mat)
You need to loop in upper triangular matrix only ie from 0,1...len(mat) row wise and row+1, row+2, row+3..len(mat[0]) column wise
# your code goes here
inp = int(input())
mat = []
for i in range(inp):
submat = list(map(int,input().split(',')))
mat.append(submat)
print(mat)
for i in range(len(mat)):
for j in range(i+1, len(mat[0])):
mat[i][j],mat[j][i] = mat[j][i],mat[i][j]
Of course, you are swapping every i, j twice (i, j and later j, i).

Program to find determinant of a n x n matrix not working

when i give a 3X3 matrix as input,it returns index error at line: m[0][0]*m[1][1]-m[0][1]*m[1][0]
import copy
def matrixdeterminant(m):
if len(m)==1:
return m[0]
elif len(m)==2:
return m[0][0]*m[1][1]-m[0][1]*m[1][0]
else:
matrixdeterminantlist=copy.deepcopy(m)
determinantlist=[]
m.pop(0)
for i in range(len(matrixdeterminantlist[0])):
for j in range(len(m)):
m[j].pop(i)
determinantlist.append(matrixdeterminantlist[0][i]*matrixdeterminant(m)*(-1)**(i+2))
m=copy.deepcopy(matrixdeterminantlist)
return sum(determinantlist)
First issue I can spot: you wrote return m[0] rather than return m[0][0] for the case where len(m) == 1.
If m is a 1x1 matrix, then m looks something like [[x]], and you want to return x, not [x], so you have to return m[0][0], not m[0].
Another important issue in your code is the way you pop elements from m and then try to restore m from its copies. This is overly complicated and you restore m wrongly inside the loop, so at some points the dimensions of m are all screwed-up. I recommend to avoid using .pop at all, and instead, build the submatrices using list comprehensions.
Here is a simplified version:
def matrixdeterminant(m):
if len(m)==1:
return m[0][0]
elif len(m)==2:
return m[0][0]*m[1][1]-m[0][1]*m[1][0]
else:
determinantlist=[]
sign = 1
for i in range(len(m)):
submatrix = [row[1:] for j,row in enumerate(m) if j != i]
minor = matrixdeterminant(submatrix)
determinantlist.append(sign * m[i][0] * minor)
sign *= -1
return sum(determinantlist)
And here is yet another version:
from itertools import cycle
def matdet(m):
if len(m) == 1:
return m[0][0]
else:
return sum(
s * mj[0] * matdet([row[1:] for i,row in enumerate(m) if i != j])
for s,(j,mj) in zip(cycle([1,-1]), enumerate(m))
)
Once it's producing numerical values instead of error messages, I strongly encourage you to test your determinant function by comparing its output on big random matrices, against the output of a matrix determinant function from a standard python module such as numpy or sympy or scipy:
numpy: numpy.linalg.det;
scipy: scipy.linalg.det;
sympy: Matrix.det.

How to print a matrix with a certain pattern in python

How can we create a pattern using Python which will create a square Matrix it will put values of diagonal elements equal to zero change the value of elements above diagonal elements 29 and change the values below that a diagonal equals to 5.
For example:
Input: 4
Output:
0999
5099
5509
5550
Please Help. Thanks
If you just have to print, you can try following
for i in range(n):
for j in range(n):
# diagonal case
if i == j:
print(0, end='')
# upper diagonal case
elif i < j:
print(9, end='')
# lower diagonal case
else:
print(5, end='')
print('')
Try using the numpy library.
import numpy as np
np.identity(4) # This will print out 1 on the diagnoals and 0 on the rest.
After that just use a loop to change all the 1s (diagnoals) to 0s
Then use if statements and loops to identify whether a number is above the 0 or not
Or if you just want to use a matrix with a predefined list, then just use np.array(list)
The key phrases to search for are "upper triangle" and "lower triangle". Once that's done, we can compose the desired output like this:
import numpy as np
shape = (4, 4)
np.tril(np.full(shape, 5), -1) + np.triu(np.full(shape, 9), 1)
How this works:
np.full(shape, fill_value) constructs an array of the given shape, filled with the given number.
np.tril(m, k) returns the lower triangle of the matrix m, from the kth diagonal (with the rest zeroed).
Similarly, np.triu(m, k) returns the upper triangle of the matrix m, from the kth diagonal (with the rest zeroed).
I think this should do the trick
def pattern(size):
for i in range(size):
print('5'*i + '0' + '9'*(size-i-1))
pattern(4)
You need to check the condition for , diagonal (row_index == column_index), upper triangular matrix (column_index > row_index) and lower_triangular matrix (row_index > column_index) and then add values accordingly
def func(n):
l = []
for i in range(n):
tmp = []
for j in range(n):
if j==i:
tmp.append(0)
elif j>i:
tmp.append(9)
elif j<n:
tmp.append(5)
l.append(tmp)
return l

conditional sum over a range python

I have created X as folowing
num_locations = 2
X= [ ]
for n in range(num_locations):
X.append([0 for j in range(num_locations)])
Now I want to sum these X[n][m] values for the case n != m . Such that the result should be like
X[0][1]+X[1][0]
Is there a way to do that with the sum formulation ?
X[n][m] for n in range(num_locations)for m in range(num_locations))
This is effectively taking the sum of the non-diagonal elements of your 2D array. One option using Numpy could simply be to subtract the sum of the main diagonal (np.trace) from the sum of the entire array.
num_locations = 2
X= [[1,2],[2,1]]
import numpy as np
s = np.sum(X) - np.trace(X)
print(s)
Outputs:
4
You can simply use enumerate
>>> sum(o for i, a in enumerate(X) for j, o in enumerate(a) if i!=j)
0
Where i and j are row (1st dim) and column (2nd dim) indices respectively
This should work
sum([sum(row) - (row[i] if len(row) < i else 0) for i,row in enumerate(X)])
It runs over every row in the 2d array, and sums it, then take out the i cell (if exists) so it won't get into sum

Categories