寻找所有可逆方阵

Finding all invertible square matrices

我想编写一个函数,给定两个整数 "n" 和 "p",它生成所有 n 阶可逆矩阵,其中元素来自 {0,1,... ,p-1}。 我有以下代码:

import itertools 
import numpy as np 

def invertible_matrices(n, p):
    invertibleMatrices = set()
    # generates all the possible matrices
    x = [y for y in range(p)]
    a = [j for j in itertools.product(x, repeat=n)]
    b = {k for k in itertools.product(a, repeat=n)}
    for each in b:
        if np.linalg.det(each) != 0:
            invertibleMatrices.add(each)
    return invertibleMatrices

对于 n=2p=2 它工作正常但是对于 n=2p=3 我得到 50 而答案是 48。 任何帮助将不胜感激。

p.s:如果您熟悉群论,我正在尝试找到 GL(n, p) 的所有元素(具有 p 个元素的有限域上的一般线性群)

我猜你想要行列式模 p(这是 GL(n,p) 上下文中的行列式,即在具有 p 个元素的有限域上)。

if not np.isclose((np.linalg.det(each)+1)%p,1):
    invertibleMatrices.add(each)

注意:+1 是为了避免出现小的数值错误。

使用 inspect_matrix() 进行调试,使用 get_invertible_matrices() 使用集合推导来确定所有可逆矩阵,使用 get_determinant_1_matrices() 获得具有行列式 1 的矩阵:

import itertools
import numpy as np


def inspect_matrix(n, p):
    """Examine a single, square matrix."""
    a = list(itertools.product(list(range(p)), repeat=n))
    matrices = {k
                for k in itertools.product(a, repeat=n)
               }
    matrix = next(iter(matrices))  # Inspect one of the matrices
    determinant = np.linalg.det(matrix)
    print(f"{matrix = }\n{determinant = }")
    print(f"inverse = {(inverse:=np.linalg.inv(matrix))}") if determinant != 0.0 else print("Matrix is not invertible")
    return inverse 


def get_invertible_matrices(n, p):
    """Generates all the possible matrices."""
    a = list(itertools.product(list(range(p)), repeat=n))
    invertible_matrices = {k
                           for k in itertools.product(a, repeat=n)
                           if not np.isclose((np.linalg.det(k) + 1) % p, 1)
                           }
    print(f"{len(invertible_matrices) = }")
    return invertible_matrices


def get_determinant_1_matrices(n, p):
    """Generates all the square matrices with determinant 1."""
    a = list(itertools.product(list(range(p)), repeat=n))
    if p==2:
            det_1_matrices = {k
                              for k in itertools.product(a, repeat=n)
                              if np.isclose((np.linalg.det(k))%p,1)
                              }
    else:
            det_1_matrices = {k
                              for k in itertools.product(a, repeat=n)
                              if np.isclose((np.linalg.det(k)+1)%p,2)
                              }
    print(f"{len(det_1_matrices) = }")
    return det_1_matrices


def main():
    print(get_invertible_matrices(n=2, p=2))
    print(get_invertible_matrices(n=2, p=3))
    print(get_determinant_1_matrices(n=2, p=2))
    print(get_determinant_1_matrices(n=2, p=3))


if __name__ == '__main__':
    main()

returns:

len(invertible_matrices) = 6
{((1, 1), (0, 1)), ((1, 0), (0, 1)), ((1, 0), (1, 1)), ((0, 1), (1, 0)), ((0, 1), (1, 1)), ((1, 1), (1, 0))}
len(invertible_matrices) = 48
{((1, 0), (0, 1)), ((1, 2), (0, 2)), ((2, 1), (1, 0)), ((0, 2), (2, 0)), ((0, 1), (2, 0)), ((1, 1), (1, 0)), ((2, 1), (1, 1)), ((2, 2), (2, 0)), ((1, 1), (2, 1)), ((1, 2), (1, 0)), ((2, 1), (2, 2)), ((2, 0), (0, 2)), ((1, 2), (1, 1)), ((2, 2), (0, 2)), ((1, 0), (0, 2)), ((1, 1), (1, 2)), ((1, 2), (2, 2)), ((2, 1), (0, 1)), ((1, 1), (0, 1)), ((0, 2), (1, 0)), ((0, 1), (1, 0)), ((2, 0), (2, 1)), ((0, 2), (2, 1)), ((2, 2), (1, 0)), ((0, 1), (2, 1)), ((1, 2), (0, 1)), ((0, 2), (1, 1)), ((2, 0), (1, 1)), ((0, 1), (1, 1)), ((2, 2), (2, 1)), ((2, 0), (2, 2)), ((0, 2), (2, 2)), ((2, 1), (2, 0)), ((0, 1), (2, 2)), ((1, 0), (2, 1)), ((1, 0), (1, 1)), ((1, 1), (2, 0)), ((2, 0), (1, 2)), ((0, 2), (1, 2)), ((0, 1), (1, 2)), ((1, 0), (2, 2)), ((2, 0), (0, 1)), ((1, 2), (2, 0)), ((2, 2), (1, 2)), ((2, 1), (0, 2)), ((1, 0), (1, 2)), ((2, 2), (0, 1)), ((1, 1), (0, 2))}
len(det_1_matrices) = 6
{((0, 1), (1, 1)), ((0, 1), (1, 0)), ((1, 0), (0, 1)), ((1, 0), (1, 1)), ((1, 1), (0, 1)), ((1, 1), (1, 0))}
len(det_1_matrices) = 24
{((2, 2), (0, 2)), ((0, 2), (1, 2)), ((1, 1), (0, 1)), ((1, 2), (2, 2)), ((2, 1), (2, 0)), ((1, 0), (0, 1)), ((2, 0), (2, 2)), ((2, 1), (1, 1)), ((1, 1), (2, 0)), ((1, 0), (2, 1)), ((1, 2), (0, 1)), ((1, 2), (1, 0)), ((2, 0), (0, 2)), ((1, 0), (1, 1)), ((1, 1), (1, 2)), ((0, 2), (1, 0)), ((0, 1), (2, 2)), ((0, 2), (1, 1)), ((0, 1), (2, 1)), ((2, 0), (1, 2)), ((0, 1), (2, 0)), ((2, 2), (2, 1)), ((2, 2), (1, 0)), ((2, 1), (0, 2))}