Линейная комбинация C ++ по модулю - PullRequest
0 голосов
/ 04 октября 2018

Я хочу вычислить LU-разложение матрицы и извлечь из нее линейные комбинации.

Сначала я задал вопрос, используя библиотеку 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 +=======================================================================================================+

Таким образом, в качестве небольшой суммы:

  • нижняя матрица в порядке, результат ожидаемый.
  • Выведенные линейные комбинации не являются ожидаемыми.
  • Объяснение ожидаемого дано в последнем подразделе.

Вопрос: Где ошибка в моем способе применения модификации к матрице тождеств и почему я не получаю в выводе правильные линейные комбинации?

EDIT

Четкое представление о том, что должно происходить в обычном режиме.Но алгоритм, который я сделал (разложение LU), не совсем тот, который я делаю вручную, хотя он должен привести к тем же результатам.Это настоящая проблема здесь ...

enter image description here

1 Ответ

0 голосов
/ 04 октября 2018

Давайте поместим мои комментарии в реальный ответ: хотя сложение и умножение по модулю простого будет делать то, что вы ожидаете (примечание ниже), вычитание имеет ловушку, где по модулю будет возвращать отрицательные результаты для отрицательного ввода (например, (-3)% 5 == -3) и для деления вы не можете просто использовать целочисленное деление, вам нужно реализовать обратное умножение (подсказки см. В ответе Демосфена в связанном предыдущем вопросе).

Примечание: если вы не переполнены, если простое * простое> INT_MAX, у вас тоже проблемы с умножением

...