pythonmatrixlinear-algebradeterminants

a 5 by 5 zero-one matrix with determinant 5


I am looking for a python code to create a 5 by 5 zero-one matrix with determinant equal to 5. (Such a matrix does exist but it is a consequence of some mathematical theorems. I like to try to find an actual example of such matrix using computer)

Creating a simple search code is time consuming (at least for my little pc!) because there are 2^(25) 5 by 5 zero-one matrix.


Solution

  • Consider utilizing a hill-climbing approach:

    import numpy as np
    
    
    def generate_initial_matrix(size: int = 5) -> np.ndarray:
      """Generates an initial random matrix with elements 0 or 1.
      Args:
        size: The size of the matrix to generate. Defaults to 5.
      Returns:
        A size x size numpy array with random 0 or 1 entries.
      """
      return np.random.randint(0, 2, size=(size, size))
    
    
    def tweak_matrix(matrix: np.ndarray) -> np.ndarray:
      """Randomly tweaks a single element in the matrix.
      Args:
        matrix: The matrix to be tweaked.
      Returns:
        A new matrix with one element flipped (0 to 1 or 1 to 0).
      """
      i, j = np.random.randint(0, matrix.shape[0], 2)
      matrix[i, j] = 1 - matrix[i, j]  # Flip between 0 and 1
      return matrix
    
    
    def find_matrix_with_determinant(
        target_det: int = 5,
        size: int = 5,
        max_attempts: int = 10000,
    ) -> np.ndarray | None:
      """Trys to find a size x size zero-one matrix with a target determinant.
      Args:
        target_det: The target determinant. Defaults to 5.
        size: The size of the matrix. Defaults to 5.
        max_attempts: The maximum number of attempts. Defaults to 10000.
      Returns:
        A size x size np.ndarray with the target determinant or None if not found.
      """
      matrix = generate_initial_matrix(size)
      best_det = np.linalg.det(matrix)
      for _ in range(max_attempts):
        if int(best_det) == target_det:
          return matrix
        new_matrix = tweak_matrix(matrix.copy())
        new_det = np.linalg.det(new_matrix)
        new_matrix_closer = abs(new_det - target_det) < abs(best_det - target_det)
        accept_worse_solution_to_escape_local_minima = np.random.rand() < 0.01
        if new_matrix_closer or accept_worse_solution_to_escape_local_minima:
          matrix, best_det = new_matrix, new_det
      return None
    
    
    def main() -> None:
      target_det = 5
      size = 5
      max_attempts = 10000
      result_matrix = find_matrix_with_determinant(target_det,
                                                   size=size,
                                                   max_attempts=max_attempts)
      if result_matrix is not None:
        print(f'Found a matrix of size {size} x {size} with determinant {target_det}:\n', result_matrix)
      else:
        print(f'No matrix size {size} x {size} found with {target_det=} within {max_attempts=}.')
    
    
    if __name__ == '__main__':
      main()
    

    Example output matrix_size = 5:

    Found a matrix of size 5 x 5 with determinant 5:
     [[0 1 1 1 0]
     [1 1 0 0 1]
     [0 0 0 1 1]
     [1 0 1 1 0]
     [0 0 1 0 1]]
    

    Example output with matrix_size = 20:

    Found a matrix of size 20 x 20 with determinant 5:
     [[1 0 0 0 0 0 0 1 1 1 0 1 1 0 0 0 0 0 0 1]
     [1 0 0 1 0 1 1 1 0 0 1 1 1 0 1 0 1 1 1 1]
     [0 1 1 0 0 1 0 1 1 0 0 1 1 0 0 0 1 1 1 1]
     [1 1 0 1 0 1 0 1 1 1 0 0 0 0 0 1 1 0 0 1]
     [1 1 0 1 1 0 0 0 0 1 0 1 0 1 1 1 0 0 1 1]
     [1 1 1 0 0 0 1 1 0 0 1 1 1 0 1 0 1 0 1 1]
     [0 1 0 1 0 0 1 0 0 0 1 1 0 1 1 1 1 0 1 0]
     [0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 0 1 1 1 1]
     [1 1 1 1 1 1 1 0 1 0 1 1 1 1 1 1 1 1 0 0]
     [1 1 1 1 0 0 0 1 1 1 0 0 0 0 0 1 1 0 1 1]
     [0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 0 1 1 0 1]
     [1 0 0 0 1 1 0 0 0 0 0 1 1 1 1 0 0 0 0 0]
     [0 1 0 1 0 0 0 0 1 1 0 1 0 0 1 0 1 1 0 1]
     [1 1 0 1 1 1 0 0 0 1 1 1 1 1 0 1 0 0 0 1]
     [1 1 1 1 0 1 0 1 1 0 1 0 1 0 0 1 1 0 0 0]
     [1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 0 0 1 0 0]
     [1 0 1 1 0 1 1 1 1 0 1 1 1 0 1 0 1 1 1 1]
     [1 0 1 1 0 0 1 1 1 0 0 1 0 1 0 1 1 1 1 0]
     [0 1 0 1 0 0 0 1 1 0 1 1 1 1 1 1 0 1 1 0]
     [1 0 1 1 1 0 1 0 1 1 1 0 0 0 0 0 1 0 1 0]]