我想从矩阵中提取线性组合,但要通过模数执行组合。
让我们考虑计算模数 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.
好了,现在我们有了背景,让我解释一下这个问题。 我开始使用犰狳库(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
是否有任何技术可以以模数方式执行计算?
编辑犰狳图书馆无法做到这一点。我开发了自己的模数 LU 分解,但那里仍然存在一个错误。我在这里问了一个新问题 线性组合 C++模数,希望能解决它。
首先:删除using namespace
s,如果你这样做,代码可能会变得完全不可读。
我还没有用过犰狳。但是我已经查看了文档,对我来说似乎是模板化的。
现在事情变得有点疯狂了。您使用的类型arma::mat
似乎是arma::Mat<double>
上的 typedef .
高级函数arma::lu
未正确记录。它显然进行了 LU 分解,但我不知道该函数是否是模板化的。如果是,即你不能只用double
垫子来调用它,还可以用其他类型的来调用它,你可能会使用表示计算模 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 分解可能需要找到好的枢轴元素(。如果你很幸运,并且库的编写方式适用于任何领域,而不仅仅是浮点数,你就有机会。
在完成所有工作之前,您应该使用一个简单的类,简单地包装双精度,并检查arma::Mat
或arma::lu
是否执行阻止您的任何类型检查。
如果其中任何一个失败,您可能需要编写自己的 LU 分解模 5 或找到另一个支持它的库。