【问题标题】:Linear Combination C++ in modulus模数中的线性组合 C++
【发布时间】:2019-03-09 23:05:12
【问题描述】:

我想计算矩阵的 LU 分解并从中提取线性组合。

我首先使用库 Armadillo here 提出了一个问题,但正如一条评论所指出的,Armadillo 无法处理模数计算。

因此我开始从头开始使用素数模数开发 LU,这是我得到的,但仍然有一个我无法看到的错误。

这是我现在拥有的代码。 (不要想太多Matrix类,它只是暂时封装一个vector<vector<int>>的一种方式。

Matrix* Matrix::triangulation(Matrix & ident)
{
    unsigned int n = getNbLines();
    unsigned int m = getNbColumns();

    vector<vector<int>> mat = getMat();

    vector<vector<int>> identity = ident.getMat();
    vector<vector<int>> lower;
    vector<vector<int>> upper;

    /* ------------------------------------------------------------ */  

    /**
     * @brief
     * This code initialize a 'lower' matrix of size 'n x n'.
     * The matrix is fill with only '0'.
     */
    for(unsigned int i = 0; i < n; i++) {   
        vector<int> v(m);
        lower.push_back(v);

        for(unsigned int j = 0; j < m; j++) lower[i][j] = 0;            
    }   

    /**
     * @brief
     * This code initialize an 'upper' matrix of size 'n x m'.
     * The matrix is fill with only '0'.
     */
    for(unsigned int i = 0; i < n; i++) {   
        vector<int> v(m);
        upper.push_back(v);
        for(unsigned int j = 0; j < m; j++) upper[i][j] = 0;
    }

    /**
     * @brief
     * This code initialize an 'identity' matrix of size 'm x m'.
     * The matrix is fill with only '0'.
     */
    for(unsigned int i = 0; i < m; i++) {
        vector<int> v2(m);
        identity.push_back(v2);
        for(unsigned int j = 0; j < m; j++) identity[i][j] = 0;

        identity[i][i] = 1;
    }

    /* ------------------------------------------------------------ */

    // Decomposing matrix into Upper and Lower triangular matrix 
    for (unsigned int i = 0; i < n; i++) { 

        // Upper Triangular 
        for (unsigned int k = 0; k < m; k++) { 

            // Summation of L(i, j) * U(j, k) 
            int sum = 0; 
            for (unsigned int j = 0; j < n; j++) 
                sum = sum + ((lower[i][j] * upper[j][k])); 

            // Evaluating U(i, k)
            upper[i][k]    = (mat[i][k] - sum) % prime;
            identity[i][k] = (mat[i][k] - sum) % prime;
        } 

        // Lower Triangular 
        for (unsigned int k = 0; k < n; k++) { 
            if (i == k) {

                lower[i][i] = 1; // Diagonal as 1 
            }
            else { 

                // Summation of L(k, j) * U(j, i) 
                int sum = 0; 
                for (unsigned int j = 0; j < n; j++) 
                    sum = sum + ((lower[k][j] * upper[j][i])); 

                // Evaluating L(k, i) 
                lower[k][i] =    (((mat[k][i] - sum)) / upper[i][i]) % prime; 
                identity[k][i] = (((mat[k][i] - sum)) / upper[i][i]) % prime;                   
            } 
        } 
    }  

    ident.setMat(identity);

    return new Matrix(lower,prime);
}

我用对象来称呼它:Matrix mat({ { 2, 1, 3, 2, 0}, { 4, 3, 0, 1, 1 }},5); 所以基本上,我想要 LU 分解(尤其是下三角矩阵),我的所有计算都在模 5 中完成。

它可以提取下矩阵,但是,线性组合(只是对单位矩阵进行的所有操作)是不正确的。 这是我对我想要获得的内容的解释:

c |-------------------------------------------------------------------------------------------------------|
c | Prime Number: 5

c |-------------------------------------------------------------------------------------------------------|
c | Input Matrix: 

2 1 3 2 0 
4 3 0 1 1 

c |-------------------------------------------------------------------------------------------------------|
c | Lower Matrix: 

1 0 0 0 0 
2 1 0 0 0 

c |-------------------------------------------------------------------------------------------------------|
c | Linear Combination Matrix:

2 0 3 2 0 
0 1 0 3 1 
0 0 1 0 0 
0 0 0 1 0 
0 0 0 0 1 

c |-------------------------------------------------------------------------------------------------------|
c | Expected Solution: 

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

c |-------------------------------------------------------------------------------------------------------|
c | Explanations: 

c | 3 * c1 + 0 * c2 + 0 * c3 + 0 * c4 + 0 * c5 = c1 of Lower-Matrix
c | 2 * c1 + 1 * c2 + 0 * c3 + 0 * c4 + 0 * c5 = c2 of Lower-Matrix
c | 3 * c1 + 1 * c2 + 1 * c3 + 0 * c4 + 0 * c5 = c3 of Lower-Matrix
c | 0 * c1 + 3 * c2 + 0 * c3 + 1 * c4 + 0 * c5 = c4 of Lower-Matrix
c | 3 * c1 + 4 * c2 + 0 * c3 + 0 * c4 + 1 * c5 = c5 of Lower-Matrix

c +=======================================================================================================+

所以作为一个小总结:

  • 下矩阵没问题,结果是预期的。
  • 输出的线性组合不是预期的。
  • 最后小节给出了预期内容的解释。

问题:我在单位矩阵上应用修改的方式中的错误在哪里,为什么我没有得到正确的线性组合输出?

编辑

清楚地了解正常情况下应该发生的事情。但是我所做的算法(LU 分解)并不完全是我手工做的,即使它应该导致相同的结果。这才是真正的麻烦……

【问题讨论】:

  • 两件事:你有清楚的想象纸上的事情会怎样吗?假设-您是否逐步调试了算法?使用好的调试器,您可以检查每一步您的代码是否根据您的纸/笔草图计算出您期望的结果。另一件事有点过时:在vectors 中存储为vectors 的矩阵真的很难看。 (但是,这可能不是您的主要问题。)
  • [OT]: for(unsigned int j = 0; j &lt; m; j++) lower[i][j] = 0; 不需要,因为vector&lt;int&gt;(m) 已经初始化为0
  • @Scheff 我添加了我如何手动解决问题的纸质展示。但是,我要应用的算法效率更高,应该会导致相同的结果,但不幸的是不能轻易调试:/
  • lower[k][i] = (((mat[k][i] - sum)) / upper[i][i]) % prime;可能是你的问题,我认为这不是模数除法的正确方法
  • 你可能还想小心减法,因为 (-3)%5 == -3 在 c++ 中也可能不是你想要的

标签: c++ matrix linear-algebra algebra


【解决方案1】:

让我们把我的 cmets 放到一个实际的答案中:虽然加法和乘法模素数会做你期望的事情(注意下面),但减法有一个陷阱,模数将返回负输入的负结果(例如 (-3)%5 = = -3) 并且对于除法,您不能只使用整数除法,您必须实际实现乘法的逆(有关提示,请参阅 Demosthenes 在链接的上一个问题中的答案)。

注意:除非你溢出,如果 prime*prime > INT_MAX ,你也有乘法的麻烦

【讨论】:

  • 我认为这是这里的主要问题,是的。不久前我学到了一件有趣的事情:我曾经假设,由于大多数 python 解释器都是用 C 编写的,它们会像 C(通常是 C++)一样进行基本计算,并用于在实现阶段测试一些公式在我的程序将使用 python 编译之前。然后是取模,我发现这个基本操作,甚至与 C 中的语法相同,行为不同。在 python 中,(-3)%5 将是 2,在 C 中它将是 - 如此处所指出的 - -3。最好不要在这里假设任何事情。
  • 顺便说一句,我什至会考虑在这里实现 operator==(),2==(-3) 返回 true。
猜你喜欢
  • 1970-01-01
  • 2013-11-27
  • 1970-01-01
  • 2016-03-14
  • 1970-01-01
  • 2018-06-08
  • 1970-01-01
  • 2016-10-05
  • 2022-10-25
相关资源
最近更新 更多