Gauss-based Linear Independence Test for Binary vectors

372 views Asked by At

I programmed a version of Gaussian Elimination to verify linear independence of a set of Binary vectors. It inputs a matrix (mxn) to evaluate and return:

  • True (Linear Independent): No zero row was found.
  • False (Linear Dependent): If the last row is zero.

It seems to work well always, or at least almost. I found that it doesn't work when the matrix has two duplicated vectors in the last row:

std::vector<std::vector<int>> A = {
    {1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1 },
    {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0 },
    {0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0 },
    {0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0},   // <---- duplicated
    {0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0},}; // <---- duplicated
gaussianElimination_binary(A);

The function says the matrix is "Linear Independent" because no zero row was found, and indeed there is any in the result. But debugging I found that at some point a row becomes zero, but then after some row operations it gets back to "normal".

I double-checked the code and the only way to make it work was to return "false" also when a "zero row" is found before the end of the process, more precisely, during row operations:

// perform XOR in "k-th" row against "row-th" row
    for (int k = 0; k <= max_row; ++k) //k=col_pivot?
    {
        if ( (k != row)   )
        {
            int check_zero_row = 0; // <---- APPLIED PATCH
            for (std::size_t j = 0; j <= max_col; j++) {
                B[k][j] = B[k][j] ^ B[row][j];
                check_zero_row = check_zero_row | B[k][j];
            }
            if (check_zero_row == 0 ) // <---- APPLIED PATCH
            {
                return false;
            }
        }
    }

I want to know if this is right, or if I'm just "patching" a bad code.

Thank you!

Here below the full code:

#include vector
bool gaussianElimination_binary(std::vector<std::vector<int>> &A) {
std::vector<std::vector<int>> B = A;
std::size_t max_col = B[0].size() - 1;      //cols
std::size_t max_row = B.size() -1 ;     //rows
std::size_t col_pivot = 0;

//perform "gaussian" elimination
for (std::size_t row = 0; row <= max_row; ++row) //for every column
{
    if (col_pivot > max_col)
        break;

    // Search for first row having "1" in column "lead"
    std::size_t i = row; //Start searching from row "i"=row
    while (B[i][col_pivot] == 0)
    {
        ++i;
        if (i > max_row) // no "1" was found across rows
        {
            i = row;        // set "i" back to "row"
            ++col_pivot;    // move to next column
            if (col_pivot > max_col) //if no more columns
                break;
        }
    }

    // swap "i" and "row" rows
    if ((0 <= i) && (i <= max_row) && (0 <= row) && (row <= max_row)) {
        for (std::size_t col = 0; col <= max_col; ++col) {
            std::swap(B[i][col], B[row][col]);
        }
    }

    // perform XOR in "k-th" row against "row-th" row
    for (int k = 0; k <= max_row; ++k) //k=col_pivot?
    {
        if ( (k != row)   )
        {
            int check_zero_row = 0;
            for (std::size_t j = 0; j <= max_col; j++) {
                B[k][j] = B[k][j] ^ B[row][j];
                check_zero_row = check_zero_row | B[k][j];
            }
            if (check_zero_row == 0 )
            {
                return false;
            }
        }
    }
}

return true;
}
0

There are 0 answers