【问题标题】:Finding all invertible square matrices查找所有可逆方阵
【发布时间】:2020-06-17 07:57:39
【问题描述】:

我想编写一个函数,其中给定两个整数“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 个元素的有限域上的一般线性群)

【问题讨论】:

    标签: python numpy matrix algebra


    【解决方案1】:

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

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

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

    【讨论】:

    • 整个学期都没有意识到这一点,我感到很愚蠢。非常感谢。
    • 如果我理解正确 - 这是因为 GL(n,p) 中的“可逆”表示“在具有 p 个元素的有限域上可逆”,而“det !=0”表示“在 R 上可逆^n"
    • (我已经编辑解释了那一点,如果我弄错了,请恢复或重新编辑)
    • @ItamarMushkin 我认为说(实际)det 是来自有限域的矩阵元素中的多项式会更正确。因此,从技术上讲,det 只能取 0 到 p-1 之间的值。
    • 或者更简洁——det modulo p 是有限域中的 det(其余都是隐含的)
    【解决方案2】:

    使用 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()
    

    返回:

    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))}
    

    【讨论】:

    • 为什么我们需要x=[y for y in range(p)]?它不能与a=[j for j in itertools.product(list(range(p)), repeat=n) 一起使用吗?
    • 非常感谢。我对 numpy 很陌生,我知道 np.isclose(a,b) 用于比较两个矩阵,但我不明白它在这里是如何工作的?如果我想将条件从“可逆矩阵”更改为“行列式等于 1 的矩阵”,我应该如何更改您的集合理解?
    • @ladypary 我重新编写了代码,因此您可以更轻松地获得行列式 ==1 或可逆矩阵,只需在新的主函数中更新您的调用即可。
    • 我将其修复为 """生成所有行列式为 1 的方阵。"""
    • @ladypary 干得好!我在顶部添加了一个辅助函数,inspect_matrix(),您可以使用它一次测试一个矩阵。
    猜你喜欢
    • 2016-08-16
    • 2016-11-13
    • 1970-01-01
    • 2017-11-24
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 2011-12-01
    相关资源
    最近更新 更多