Finding inverse of a matrix using Gauss-Jordan Elimination in Python - python-3.x

So I am trying to find inverse of a matrix (using Python lists) by Gauss-Jordan Elimination. But I am facing this peculiar problem. In the code below, I apply my code to the given matrix and it reduces to the identity matrix as intended.
M = [[0, 2, 1], [4, 0, 1], [-1, 2, 0]]
P = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
n = len(P)
def inverse(a):
for k in range(n):
if abs(a[k][k]) < 1.0e-12:
for i in range(k+1, n):
if abs(a[i][k]) > abs(a[k][k]):
for j in range(k, n):
a[k][j], a[i][j] = a[i][j], a[k][j]
break
pivot = a[k][k]
for j in range(k, n):
a[k][j] /= pivot
for i in range(n):
if i == k or a[i][k] == 0: continue
factor = a[i][k]
for j in range(k, n):
a[i][j] -= factor * a[k][j]
return a
inverse(M)
The output is
[[1.0, 0.0, 0.0], [0, 1.0, 0.0], [0.0, 0.0, 1.0]]
But when I apply the same code, after adding lines of code for my identity matrix (which is part of the augmented matrix with the given matrix), It is not giving me the correct inverse when it should (as I am applying same operation on it as I'm applying on the given matrix).
M = [[0, 2, 1], [4, 0, 1], [-1, 2, 0]]
P = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
n = len(P)
def inverse(a, b):
for k in range(n):
if abs(a[k][k]) < 1.0e-12:
for i in range(k+1, n):
if abs(a[i][k]) > abs(a[k][k]):
for j in range(k, n):
a[k][j], a[i][j] = a[i][j], a[k][j]
b[k][j], b[i][j] = b[i][j], b[k][j]
b[k], b[i] = b[i], b[k]
break
pivot = a[k][k]
for j in range(k, n):
a[k][j] /= pivot
b[k][j] /= pivot
for i in range(n):
if i == k or a[i][k] == 0: continue
factor = a[i][k]
for j in range(k, n):
a[i][j] -= factor * a[k][j]
b[i][j] -= factor * b[k][j]
return a, b
inverse(M, P)
The output is not the inverse matrix, but something else (though the last column has correct entries).
([[1.0, 0.0, 0.0], [0, 1.0, 0.0], [0.0, 0.0, 1.0]],
[[0.0, 0.25, 0.3333333333333333],
[1, 0.0, 0.6666666666666666],
[0.0, 0.25, -1.3333333333333333]])
I tried using print statements while debugging, and I think the line where I divide the rows by the pivot, has some issue. It works fine in the original matrix but doesn't work with the identity matrix. Also, note that only the last column of the identity matrix gets converted to the correct entries of the inverse matrix.
The correct inverse matrix for reference is
I = [[-1/3, 1/3, 1/3], [-1/6, 1/6, 2/3], [4/3, -1/3, -4/3]]
Any help would be much appreciated.
Thanks in advance!

I could not figure out the problem in my code though I found a workaround and I'll be instead posting that. Hope that might help someone else.
Instead of doing the same operations on the two matrices of which I formed the augmented matrix, I decided to deal it as a n x 2n matrix. Here is the fully working code:
def inverse(a):
n = len(a) #defining the range through which loops will run
#constructing the n X 2n augmented matrix
P = [[0.0 for i in range(len(a))] for j in range(len(a))]
for i in range(3):
for j in range(3):
P[j][j] = 1.0
for i in range(len(a)):
a[i].extend(P[i])
#main loop for gaussian elimination begins here
for k in range(n):
if abs(a[k][k]) < 1.0e-12:
for i in range(k+1, n):
if abs(a[i][k]) > abs(a[k][k]):
for j in range(k, 2*n):
a[k][j], a[i][j] = a[i][j], a[k][j] #swapping of rows
break
pivot = a[k][k] #defining the pivot
if pivot == 0: #checking if matrix is invertible
print("This matrix is not invertible.")
return
else:
for j in range(k, 2*n): #index of columns of the pivot row
a[k][j] /= pivot
for i in range(n): #index the subtracted rows
if i == k or a[i][k] == 0: continue
factor = a[i][k]
for j in range(k, 2*n): #index the columns for subtraction
a[i][j] -= factor * a[k][j]
for i in range(len(a)): #displaying the matrix
for j in range(n, len(a[0])):
print(a[i][j], end = " ")
print()

Related

Changing cells in a 4D numpy matrix subject to conditions on axis indexes

Suppose I have a 4D numpy array A with indexes i, j, k, l for the four dimensions, suppose 50 x 40 x 30 x 20. Also suppose I have some other list B.
How can I set all cells in A that satisfy some condition to 0? Is there a way to do it efficiently without loops (with vectorization?).
Example condition: All cells that have 3rd dimensional index k whereby B[k] == x
For instance,
if we have the 2D matrix A = [[1,2],[3,4]] and B = [7,8]
Then for the 2nd dimension of A (i.e. columns), I want to zero out all cells in the 2nd dimension whereby the index of the cell in that dimension (call the index i), satisfies the condition B[i] == 7. In this case, A will be converted to
A = [[0,0],[3,4]].
You can specify boolean arrays for specific axes:
import numpy as np
i, j, k, l = 50, 40, 30, 20
a = np.random.random((i, j, k, l))
b_k = np.random.random(k)
b_j = np.random.random(j)
# i, j, k, l
a[:, :, b_k < 0.5, :] = 0
# You can alsow combine multiple conditions along the different axes
# i, j, k, l
a[:, b_j > 0.5, b_k < 0.5, :] = 0
# Or work with the index explicitly
condition_k = np.arange(k) % 3 == 0 # Is the index divisible by 3?
# i, j, k, l
a[:, :, condition_k, :] = 0
To work with the example you have given
a = np.array([[1, 2],
[3, 4]])
b = np.array([7, 8])
# i, j
a[b == 7, :] = 0
# array([[0, 0],
# [3, 4]])
Does the following help?
A = np.arange(16,dtype='float64').reshape(2,2,2,2)
A[A == 2] = 3.14
I'm replacing the entry equal to 2 with 3.14. You can set it to some other value.

Finding maximal submatrix of all 1's - missing argument error

Program that finds the maximal rectangle containing only 1's of a binary matrix with the maximal histogram problem.
I am trying to do some tests on a code
def maximalRectangle(self, matrix):
if not matrix or not matrix[0]:
return 0
n = len(matrix[0])
height = [0] * (n + 1)
ans = 0
for row in matrix:
for i in range(n):
height[i] = height[i] + 1 if row[i] == '1' else 0
stack = [-1]
for i in range(n + 1):
while height[i] < height[stack[-1]]:
h = height[stack.pop()]
w = i - 1 - stack[-1]
ans = max(ans, h * w)
stack.append(i)
return ans
# Driver Code
if __name__ == '__main__':
matrix = [[0, 1, 0, 1],
[0, 1, 0, 1],
[0, 1, 1, 1],
[1, 1, 1, 1]]
print(maximalRectangle(matrix))
I get TypeError: maximalRectangle() missing 1 required positional argument: 'matrix' error
Solved by removing self and changing the print statement to:
print(maximalRectangle([
["1","0","1","0","0"],
["1","1","1","1","1"],
["1","1","1","1","1"],
["1","0","0","1","0"]]))

Compute distance metric in a complete graph

Suppose I have an array, namely Map. Map[i][j] means the distance between area i and area j. Under this definition, we get:
a) Map[i][i] always equals 0.
b) Map[i][k] <= Map[i][j] + Map[j][k] for all i,j,k
I want to build a function func(Map,k) returning a metric D, while D[i][j] is the shortest distance of a route from area i to area j, and this route should pass through at least k different area.
This is my python code to do so:
def func(Map,k):
n=len(Map)
D_temp = [list(x) for x in Map]
D = [list(x) for x in Map]
for m in range(k - 1):
for i in range(n):
for j in range(n):
tmp = [D[i][x] + Map[x][j] for x in range(n) if x != i and x != j]
D_temp[i][j] = min(tmp)
D = [list(x) for x in D_temp]
return D
func([[0, 2, 3], [2, 0, 1], [3, 1, 0]],2)
return a distance metric D which equals [[4, 4, 3], [4, 2, 5], [3, 5, 2]]
D[0][0] equals 4, because the shortest route from area0 to area0 which pass through at least 2 area is {area0-->area1-->area0}, and the distance of the route is Map[0][1]+Map[1][0]=2+2=4
Wanted to know what would be the best way to do that?
You can use the A* algorithm for this, using Map[i][j] as the heuristic for the minimum remaining distance to the target node (assuming that, as you said, Map[i][j] <= Map[i][x] + Map[x][j] for all i,j,x). The only difference to a regular A* would be that you only accept paths if they have a minimum length of k.
import heapq
def min_path(Map, k, i, j):
heap = [(0, 0, i, [])]
while heap:
_, cost, cur, path = heapq.heappop(heap)
if cur == j and len(path) >= k:
return cost
for other in range(len(Map)):
if other != cur:
c = cost + Map[cur][other]
heapq.heappush(heap, (c + Map[other][j], c, other, path + [other]))
Change your func to return a list comprehension using this min_path accordingly.
def func(Map, k):
n = len(Map)
return [[min_path(Map, k, i, j) for i in range(n)] for j in range(n)]
res = func([[0, 2, 3], [2, 0, 1], [3, 1, 0]], 2)
This gives me the result [[4, 4, 3], [4, 2, 3], [3, 3, 2]] for len(path) >= k, or [[4, 4, 3], [4, 2, 5], [3, 5, 2]] for len(path) == k.

calculate the sum of the intervals based on the binary array

I have two matrix:
Binary A = [[1, 0, 1, 0], [0, 0, 1, 0]];
Matrix of values B = [[100, 200, 300, 400], [400, 300, 100, 200]];
I want to calculate the sum of the intervals that are formed by the rows of the matrix A. For my exmpl. result will be follow: R = [[300, 0, 700, 0], [0, 0, 300, 0]] (generally, it is not necessary to set zeros [[300, 700], [300]] - it's right solution too)
I already wrote the code, but very very terrible (although it works correctly)
def find_halfsum(row1, row2):
i = 0
result = []
count = 0
for j in range(len(row1)):
if row1[j] == 1 and count == 0:
i = j
count += 1
elif row1[j] == 1:
count += 1
if count == 2:
if j == i + 1:
result.append(row2[i])
else:
result.append(sum(row2[i:j]))
i = j
count = 1
if j == len(row1) - 1:
result.append(sum(row2[i:j + 1]))
return result
Someone knows beautiful solutions (which will be faster)(preferably with the help of a numpy)?
Thanks
Not familiar with python, but I don't think you need that many lines
define halfSum(matrixA, matrixB):
sum = 0;
for i in range(len(matrixA)):
if matrixA[i] == 1:
sum += matrixB[i]
return sum;
You can use numpy.add.reduceat:
>>> A = np.array([[1, 0, 1, 0], [0, 0, 1, 0]])
>>> B = np.array([[100, 200, 300, 400], [400, 300, 100, 200]])
>>>
>>> [np.add.reduceat(b, np.flatnonzero(a)) for a, b in zip(A, B)]
[array([300, 700]), array([300])]

Dynamic Programming: Tabulation of a Recursive Relation

The following recursive relation solves a variation of the coin exchange problem. Count the number of ways in which we can sum to a required value, while keeping the number of summands even:
def count_even(coins, num_coins, req_sum, parity):
if req_sum < 0:
return 0
if req_sum == 0 and not parity:
return 1
if req_sum == 0 and parity:
return 0
if num_coins == 0:
return 0
count_wout_high_coin = count_even(coins, num_coins - 1, req_sum, parity)
count_with_high_coin = count_even(coins, num_coins, req_sum - coins[num_coins - 1], not parity)
return count_wout_high_coin + count_with_high_coin
This code would yield the required solution if called with parity = False.
I am having issues implementing a tabulation technique to optimize this algorithm. On a first attempt I tried to follow the same pattern as for other DP problems, and took the parity as another parameter to the problem, so I coded this triple loop:
def count_even_tabulation(S, m, n):
if m <= 0 or n < 0:
return 0
if n == 0:
return 1
table = [[[0 for x in range(m)] for x in range(n + 1)] for x in range(2)]
for j in range(m):
table[0][0][j] = 1
table[1][0][j] = 0
for p in range(2):
for i in range(1, n + 1):
for j in range(m):
y = table[p][i][j - 1] if j >= 1 else 0
x = table[1 - p][i - S[j]][j] if i - S[j] >= 0 else 0
table[p][i][j] = x + y
return table[0][n][m - 1]
However, this approach is not creating the right tables for parity equal to 0 and equal to 1:
[1, 1, 1]
[0, 0, 0]
[0, 0, 0]
[0, 0, 0]
[0, 0, 0]
[0, 0, 0]
[1, 1, 1]
[0, 1, 1]
[0, 0, 1]
[0, 0, 0]
How can I adequately implement a tabulation approach for the given recursion relation?

Resources