【问题标题】:Inverting a ZZ_p matrix in NTL在 NTL 中反转 ZZ_p 矩阵
【发布时间】:2018-01-11 00:08:41
【问题描述】:

我正在尝试生成一个随机二进制矩阵及其逆 mod q,其中 q 是 2 的幂。有时当我的矩阵的行列式是模 q 可逆时(因此 Z_q 上的矩阵是可逆的),我得到错误“InvMod:inverse undefined Aborted (core dumped)”和其他时候计算逆。我做错了什么?

#include <iostream>
//NTL files
#include <NTL/ZZ_p.h>
#include <NTL/vec_vec_ZZ_p.h>
#include <NTL/LLL.h>
#include <NTL/matrix.h>
#include <NTL/vector.h>
#include <NTL/tools.h>
#include <NTL/ZZ.h>
#include <NTL/vec_vec_ZZ.h>
using namespace std;
using namespace NTL;

int main(){//task generate a random matrix S with 0/1 entries stored as a ZZ_p matrix, then generate a random, invertible S 
int nn = 8;
ZZ n = ZZ(nn);
ZZ N = ZZ(0);
ZZ q; power2(q, 4);
ZZ_p::init(q);

mat_ZZ S; S.SetDims(nn,nn); 
for(int i = 0; i<nn; i++){
    for(int j = 0; j<nn; j++){
        S[i][j] = RandomBits_ZZ(1);     
    }
}
mat_ZZ_p S1; S1.SetDims(nn,nn);//copy to ZZ_P
mat_ZZ_p R; R.SetDims(nn,nn);//will set to inverse if 

cout<<"The random matrix is S = "<<endl; //print S
for(int i = 0; i<nn; i++){
    for(int j=0; j<n;j++){
        cout<<S[i][j]<<", ";
    } cout<<endl;
}

ZZ d; determinant(d,S); ZZ_p d1; conv(d1, d % q);
if(GCD(q,d) == 1){//convert to mod q datatype
    for(int i = 0; i<nn; i++){
        for(int j = 0; j<nn; j++){
            conv(S1[i][j], S[i][j]);        
        }
    }
    //let's invert the matrix and print it!
    cout<<"The random matrix is R = "<<endl; //print R
    R = inv(S1); //mul(R,R,S1);
    for(int i = 0; i<nn; i++){
        for(int j=0; j<n;j++){
            cout<<R[i][j]<<", ";
        } cout<<endl;
    }
}

cout<<endl<<"det of S is "<<d<<" and this mod q is "<<d1<<endl;
cout<<"Our modulus is "<< q <<endl;

return 0;
}

【问题讨论】:

    标签: linear-algebra number-theory ntl


    【解决方案1】:

    如果行列式是可逆的 mod q 这仅意味着存在逆矩阵。但是计算这个矩阵的算法仍然可能需要计算一个没有逆矩阵的元素。

    如果q 是素数,你就不会有这个问题。

    顺便说一下,这是您的代码的简化版本。

    #include <iostream>
    //NTL files
    #include <NTL/mat_ZZ_p.h>
    
    using namespace std;
    using namespace NTL;
    
    int main()
    {//task generate a random matrix S with 0/1 entries stored as a ZZ_p matrix, then generate a random, invertible S
        int nn = 8;
        ZZ q;
        power2(q, 4);
        ZZ_p::init(q);
    
        mat_ZZ_p S;
        S.SetDims(nn, nn);
    
        for(int i = 0; i < nn; i++)
        {
            for(int j = 0; j < nn; j++)
            {
                S[i][j] = conv<ZZ_p>(RandomBits_ZZ(1));
            }
        }
    
        mat_ZZ_p R;
        R.SetDims(nn, nn);//will set to inverse if
    
        cout << "The random matrix is S = " << endl << S;
    
        ZZ_p d;
        determinant(d, S);
    
        cout << endl << "det(S) = " << d << endl;
        cout << "q = " << q << endl;
    
        if(GCD(conv<ZZ>(d), q) == 1)
        {
            // let's invert the matrix and print it!
            R = inv(S);
            cout << "The random matrix is R = " << R << endl;
        }
    
        return 0;
    }
    

    【讨论】:

    • 所以当我们切换到素数 q 时错误就消失了。是否有适用于所有 q 的 NTL 算法?我觉得很奇怪说 Maple 有一个计算逆 mod n 的函数,但 NTL 没有。
    • @user11235 我不确定 NTL 是否实现了避免这种情况的算法。我认为这个想法是,这个函数只有在你想在有限域上的矩阵环内工作时才有意义。所以也许 Shoup 只是忽略了 q 不是素数的情况。
    • 矩阵求逆确实可以使用 zz_p 而不是 ZZ_p 的素数模幂,我最近发现,所以我的问题得到了解决。对于任意 q,我认为必须通过伴随项(包含所有未成年人行列式的矩阵)。这实现起来不会太糟糕,并且复杂度约为 O(n^5)。
    • @user11235 这很有趣,因为文档只说 zz_pZZ_p 相同,但 p 是单精度的。
    • 这是我正在查看的文档。它有一个“放松”版本的倒置和行列式,允许主幂。 mat_lzz_p.cpp PS-感谢您简化代码。所有包含的内容都非常混乱。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多