input: 
  class Matrix:
      def __init__(self, m, n, lst):
          self.m = m             
          self.n = n             
          self.mat = [] 
    
          c = 0
          for i in range(self.m): 
              a =[] 
              for j in range(self.n): 
                  a.append(lst[c]) 
                  c += 1
              self.mat.append(a) 
    
      def __str__(self): 
          output = ""
          for i in self.mat: 
              for j in i: 
                  output += str(j) + " "
              output += '\n'
          return output 
    
      def add(self, mat2): 
          for i in range(self.m): 
              for j in range(self.n): 
                  self.mat[i][j] += mat2.mat[i][j] 
    
      def sub(self, mat2): 
          for i in range(self.m): 
              for j in range(self.n): 
                  self.mat[i][j] -= mat2.mat[i][j]
      
      def mul(self, mat2): 
          result = [] 
          for i in range(self.m): 
              a =[] 
              for j in range(mat2.n): 
                  s = 0
                  for k in range(self.n): 
                      s += self.mat[i][k] * mat2.mat[k][j] 
                  a.append(s) 
              result.append(a) 
          self.mat = result 
          self.m = len(result) 
          self.n = len(result[0]) 
    
      def transpose(self):
          result = [[self.mat[j][i] for j in range(len(self.mat))] for i in range(len(self.mat[0]))]
          self.mat = result 
          self.m = len(result) 
          self.n = len(result[0])
  
  # Example test case
  m1 = Matrix(2, 2, [1, 2, 3, 4])
  m2 = Matrix(2, 2, [5, 6, 7, 8])
  m1.add(m2)
  print(m1)
  # Expected output:
  # 6 8 
  # 10 12 
  
output:     
      def scalar_mul(self, scalar): 
          for i in range(self.m): 
              for j in range(self.n): 
                  self.mat[i][j] *= scalar 
    
      def get_element(self, i, j): 
          return self.mat[i][j] 
    
      def set_element(self, i, j, value): 
          self.mat[i][j] = value 
    
      def is_square(self): 
          return self.m == self.n 
    
      def is_symmetric(self): 
          if not self.is_square(): 
              return False 
          for i in range(self.m): 
              for j in range(i+1, self.n): 
                  if self.mat[i][j] != self.mat[j][i]: 
                      return False 
          return True 
    
      def is_identity(self): 
          if not self.is_square(): 
              return False 
          for i in range(self.m): 
              for j in range(self.n): 
                  if i == j and self.mat[i][j] != 1: 
                      return False 
                  elif i != j and self.mat[i][j] != 0: 
                      return False 
          return True 
    
      def trace(self): 
          if not self.is_square(): 
              return None 
          return sum(self.mat[i][i] for i in range(self.m)) 
    
      def determinant(self): 
          if not self.is_square(): 
              return None 
          if self.m == 1: 
              return self.mat[0][0] 
          if self.m == 2: 
              return self.mat[0][0] * self.mat[1][1] - self.mat[0][1] * self.mat[1][0] 
          det = 0 
          for c in range(self.n): 
              sub_mat = [row[:c] + row[c+1:] for row in self.mat[1:]] 
              sub_matrix = Matrix(self.m-1, self.n-1, [item for sublist in sub_mat for item in sublist]) 
              det += ((-1) ** c) * self.mat[0][c] * sub_matrix.determinant() 
          return det 
  