Armadillo C++:线性组合与模数计算

Posted

技术标签:

【中文标题】Armadillo C++:线性组合与模数计算【英文标题】:Armadillo C++ : Linear Combination with modulus calculations 【发布时间】:2018-10-03 12:28:32 【问题描述】:

我想从矩阵中提取线性组合,但通过执行模数组合。

让我们考虑计算模数 5,然后我们有以下相加:

 + |  0 1 2 3 4
 --+-----------
 0 | 0 1 2 3 4
 1 | 1 2 3 4 0
 2 | 2 3 4 0 1
 3 | 3 4 0 1 2 
 4 | 4 0 1 2 3

和这个表的乘法:

 * | 0 1 2 3 4
 --+-----------
 0 | 0 0 0 0 0
 1 | 0 1 2 3 4
 2 | 0 2 4 1 3
 3 | 0 3 1 4 2
 4 | 0 4 3 2 1

让我们举个例子: 让我们考虑以下矩阵:

E = 2 1 3 2 0
    4 3 0 1 1

然后我们可以通过LU分解(https://en.wikipedia.org/wiki/LU_decomposition)(或高斯消元法)得到三角剖分矩阵,如下:

T = 1 0 0 0 0 
    2 1 0 0 0 

最后是我要提取的矩阵,也就是存储线性组合的矩阵:

CL = 3 2 3 0 3
     0 1 1 3 4
     0 0 1 0 0 
     0 0 0 1 0
     0 0 0 0 1

所以基本上,算法应该如下工作:

 Input: a matrix E with n rows and m columns, and p, a prime number.

 * We perform a Gaussian elimination/LU decomposition to obtain the lower-triangulation matrix T. 
   But all the calculus are done modulo 'p'. 

 Output: T (with the same size as E, n rows m columns). 
         CL (with a size m rows, m columns), 
         which is basically the identity matrix on which we 
         applied all the modifications that were performed on E to obtain T.

好的,现在我们有了上下文,让我解释一下问题。 我开始使用 Armadillo 库 (http://arma.sourceforge.net/) 来做这件事,但我没有在库上找到任何解决方案来对数学字段 p 执行微积分。我很容易找到LU的方法来获取下三角矩阵,但是计算是在真实中进行的。

#include <iostream>
#include <armadillo>

using namespace arma;
using namespace std;

int main(int argc,char** argv)


    mat A = mat(2,1,3,2,0,4,3,0,1,1);

    mat L, U, P;

    lu(L, U, P, A);

    cout << L << endl;

    return 0;

通过以下方法,您可以获得下三角矩阵“L”,但在实际微积分中。从而获得:

 T' =  1   0
       1/2 1

是否有任何技术可以以模数方式执行计算?

编辑 Armadillo 库无法做到这一点。我开发了自己的 LU 模数分解,但那里仍然存在错误。我在这里Linear Combination C++ in modulus提出了一个新问题,希望能解决。

【问题讨论】:

【参考方案1】:

首先:删除using namespaces,如果这样做,代码可能会变得完全不可读。

我还没用过犰狳。但我查看了文档,对我来说似乎是模板。

现在事情变得有点疯狂。您使用的类型arma::mat 似乎是arma::Mat&lt;double&gt; 上的typedef。

高级函数arma::lu 没有正确记录。它显然做了一个 LU 分解,但我不知道该函数是否被模板化。如果是这样,即,您不能只用double mats 调用它,也可以使用其他类型调用它,您可能会使用代表字段的自定义类型(因为 5 是素数,否则您将完全迷失)计算模数5. 意思是你写了一个类,我们称它为IntMod5 并为这个类定义所有必需的操作符,意思是IntMod5 使用的所有操作符。例如,您需要定义 operator/(),例如通过制作字段的 5 个元素中的 4 个的逆表(0 没有),即 1->1、2->3、3->2、4->4,并定义

IntMod5 operator/(const IntMod5& o) const

    return IntMod5((this->value*inverse(o.value))%5);

这只是一个示例,您可能需要定义所有算术运算符,二元和一元,可能还需要定义更多,例如比较(LU 分解可能会使用寻找好的枢轴元素)。如果您很幸运,并且该库的编写方式适用于任何领域,而不仅仅是浮点,那么您就有机会。

在你完成所有工作之前,你应该使用一个简单的类来简单地包装 double 并检查 arma::Matarma::lu 是否有任何类型检查阻止你。

如果其中任何一个失败,您可能必须编写自己的 LU 分解模 5 或寻找另一个支持它的库。

【讨论】:

犰狳库使用 LAPACK 来完成繁重的工作(“通过与 LAPACK 集成提供各种矩阵分解”)并且不适用于 c++ 自定义类型,因此此方法不适用于此库 我按照你的建议做了,但是现在我自己的LU分解模5还有一个问题。我在这里问了另一个问题:***.com/questions/52648687/…

以上是关于Armadillo C++:线性组合与模数计算的主要内容,如果未能解决你的问题,请参考以下文章

使用文件路径 c++ Linux OS 访问 Armadillo 库

将Matlab程序转化成C++程序

在 Microsoft Visual Studio 2015 的 C++ 项目中包含 Armadillo C++ 库

C ++ Armadillo:来自二维矩阵的索引数组

求组合数小结

bzoj-2219 数论之神