Python 辛:有限域中矩阵的求解

Python 辛:有限域中矩阵的求解,python,matrix,sympy,modular-arithmetic,matrix-factorization,Python,Matrix,Sympy,Modular Arithmetic,Matrix Factorization,在我的项目中,我需要求解给定矩阵Y和K的矩阵X。(XY=K)每个矩阵的元素必须是随机256位素数模的整数。我第一次尝试解决这个问题时使用了SymPy的mod\u inv(n)函数。问题是我的内存不足,矩阵大小大约为30。我的下一个想法是执行矩阵分解,因为这可能会减少内存负担。然而,Symphy似乎不包含能够找到以数字为模的矩阵的解算器。任何我可以使用的变通方法或自制代码?sympy'sMatrix类支持模逆。下面是一个模5的示例: from sympy import Matrix, pprint

在我的项目中,我需要求解给定矩阵Y和K的矩阵X。(XY=K)每个矩阵的元素必须是随机256位素数模的整数。我第一次尝试解决这个问题时使用了SymPy的
mod\u inv(n)
函数。问题是我的内存不足,矩阵大小大约为30。我的下一个想法是执行矩阵分解,因为这可能会减少内存负担。然而,Symphy似乎不包含能够找到以数字为模的矩阵的解算器。任何我可以使用的变通方法或自制代码?

sympy
's
Matrix
类支持模逆。下面是一个模5的示例:

from sympy import Matrix, pprint

A = Matrix([
    [5,6],
    [7,9]
])

#Find inverse of A modulo 26
A_inv = A.inv_mod(5)
pprint(A_inv)

#Prints the inverse of A modulo 5:
#[3  3]
#[    ]
#[1  0]
from sympy import Matrix, Rational, mod_inverse, pprint

B = Matrix([
        [2,2,3,2,2],
        [2,3,1,1,4],
        [0,0,0,1,0],
        [4,1,2,2,3]
])

#Find row-reduced echolon form of B modulo 5:
B_rref = B.rref(iszerofunc=lambda x: x % 5==0)

pprint(B_rref)

# Returns row-reduced echelon form of B modulo 5, along with pivot columns:
# ([1  0  7/2  0  -1], [0, 1, 3])
#  [                ]
#  [0  1  -2   0  2 ]
#  [                ]
#  [0  0   0   1  0 ]
#  [                ]
#  [0  0  -10  0  5 ]  
查找行缩减梯队形式的
rref
方法支持关键字
iszerofunction
,该关键字指示矩阵中哪些条目应视为零。我相信预期用途是为了数值稳定性(将小数值视为零),尽管我不确定。我用它来减少模块化

下面是一个模5的示例:

from sympy import Matrix, pprint

A = Matrix([
    [5,6],
    [7,9]
])

#Find inverse of A modulo 26
A_inv = A.inv_mod(5)
pprint(A_inv)

#Prints the inverse of A modulo 5:
#[3  3]
#[    ]
#[1  0]
from sympy import Matrix, Rational, mod_inverse, pprint

B = Matrix([
        [2,2,3,2,2],
        [2,3,1,1,4],
        [0,0,0,1,0],
        [4,1,2,2,3]
])

#Find row-reduced echolon form of B modulo 5:
B_rref = B.rref(iszerofunc=lambda x: x % 5==0)

pprint(B_rref)

# Returns row-reduced echelon form of B modulo 5, along with pivot columns:
# ([1  0  7/2  0  -1], [0, 1, 3])
#  [                ]
#  [0  1  -2   0  2 ]
#  [                ]
#  [0  0   0   1  0 ]
#  [                ]
#  [0  0  -10  0  5 ]  
这有点正确,只是
rref[0]
返回的矩阵中仍然有5个和分数。通过取模并将分数解释为模逆来解决这个问题:

def mod(x,modulus):
    numer, denom = x.as_numer_denom()
    return numer*mod_inverse(denom,modulus) % modulus

pprint(B_rref[0].applyfunc(lambda x: mod(x,5)))

#returns
#[1  0  1  0  4]
#[             ]
#[0  1  3  0  2]
#[             ]
#[0  0  0  1  0]
#[             ]
#[0  0  0  0  0]

注意:此功能并不总是有效。例如Z_5中的矩阵([[4,3,1,3],[2,4,1,3]])。在这种情况下,使用lambda x:x%5==0的常规iszerofunc调用将给出一个分母包括5的矩阵。因为在Z_5中没有5的倒数,程序将退出。@Sympy 1.6中的brunston,这个例子现在可以工作了!(正如您在Sympy 1.0中描述的那样,它失败了)。我从来没有研究过为什么这个例子在1.0中失败,所以我不能肯定所有的例子现在都能工作,但令人高兴的是,这个方法现在看起来更可靠了。(我也不确定这是哪个版本开始工作的。)