def lu(M, info=None): if not isinstance(M, Matrix): return None rows, cols = M.size() if rows != cols: raise ArithmeticError("LU factorization requires a square matrix (rows == cols)") A = copy.deepcopy(M) L = Matrix(rows, cols, mtype='i') U = Matrix(rows, cols) P = Matrix(rows, cols, mtype='i') # Adjust rows of A so largest element is in the pivot of each row l = 0 swaps = 0 for i in range(rows): max_l = abs(A[i][l]) swap = i for j in range(i + 1, rows): if abs(A[j][l]) > max_l: max_l = abs(A[j][l]) swap = j if i != swap: P.swap(i, swap) swaps += 1 l += 1 # Swap rows to get larger pivots A = P * A # Keep track of the current pivot we are at to determine side of diagonal l = 0 for i in range(rows): for j in range(cols): # Upper diagonal of U, including diagonal if j >= l: U[i][j] = A[i][j] - __ludot(i, U, L, i, j) # Lower diagonal of L, not including the diagonal else: L[i][j] = 1 / U[j][j] * (A[i][j] - __ludot(j, U, L, i, j)) l += 1 if info and info == 's': return [L, U, P, swaps] return [L, U, P]
def test_det(self): # Test property that determinant of identity matrix is 1 A = Matrix(10, 10, mtype="i") self.assertAlmostEqual(lalg.det(A), 1, delta=0.001) # Test property row exchanges case that determinant is (-1)^swaps A.swap(1, 2) self.assertAlmostEqual(lalg.det(A), -1, delta=0.001) A.swap(3, 4) self.assertAlmostEqual(lalg.det(A), 1, delta=0.001) # Multiplying one row of a matrix by t results in the determinant being multiplied by t # | t*a t*b | = t * |a b| # | c d | |c d| A = Matrix([4 * 2, 4 * 8], [3, 9]) B = Matrix([2, 8], [3, 9]) self.assertAlmostEqual(lalg.det(A), 4 * lalg.det(B), delta=0.001) # Adding to one row of a matrix results in a linear combination of the matrix and addition # | a+da b+db | = |a b| + |da db| # | c d | |c d| |c d | A = Matrix([8 + 9, -2 + 7], [-5, 12]) B = Matrix([8, -2], [-5, 12]) C = Matrix([9, 7], [-5, 12]) self.assertAlmostEqual(lalg.det(A), lalg.det(B) + lalg.det(C), delta=0.001) # If A has a row of all zeros the determinant should be 0 A = Matrix(12, 12) for i in range(12): for j in range(12): A[i][j] = random.randint(-1000, 1000) A.set_row(3, [0] * 12) self.assertAlmostEqual(lalg.det(A), 0) # If two rows are equal the determinant is 0 A = Matrix(12, 12) for i in range(12): for j in range(12): A[i][j] = random.randint(-1000, 1000) A.set_row(random.randint(0, 5), [i for i in range(12)]) A.set_row(random.randint(6, 11), [i for i in range(12)]) self.assertAlmostEqual(lalg.det(A), 0)
def test_swap(self): m = Matrix([1, 2, 3], [4, 5, 6]) m.swap(0, 1) self.assertEqual(m, Matrix([4, 5, 6], [1, 2, 3])) m = Matrix([1, 2], [3, 4], [5, 6], [7, 8], [9, 10]) m.swap(0, 4) m.swap(1, 3) # Middle row shouldn't move m.swap(2, 2) self.assertEqual(m, Matrix([9, 10], [7, 8], [5, 6], [3, 4], [1, 2]))