Question

I am doing a project in which I need to check whether a bool array 'vector' is linearly independent of the columns of the 'matrix'. In MATLAB it can be done by finding the rank of the augmented matrix [matrix vector] using the command rank(gf([matrix vector])). 'gf' because the matrix is Boolean. But how to do it in C++. This is what I have tried:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "engine.h"
#define  BUFSIZE 256

int main()
{
Engine *ep;
mxArray *M = NULL, *V = NULL, *result = NULL;
bool matrix[4][4]={1,1,1,0,0,1,1,0,0,1,0,0}, vector[4][1]={1,1,1,1};
double *rank;

if (!(ep = engOpen("\0"))) {
    fprintf(stderr, "\nCan't start MATLAB engine\n");
    return EXIT_FAILURE;
}

V = mxCreateDoubleMatrix(4, 1, mxREAL);
M = mxCreateDoubleMatrix(4, 4, mxREAL);
memcpy((void *)mxGetPr(V), (void *)vector, sizeof(vector));
memcpy((void *)mxGetPr(M), (void *)matrix, sizeof(matrix));
engPutVariable(ep, "V", V);
engPutVariable(ep, "M", M);

engEvalString(ep, "R = rank(gf([M V]));");
result = engGetVariable(ep, "R");
engClose(ep);
rank = mxGetPr(result);
printf("%f", *rank);

printf("Done with LI\n");
mxDestroyArray(M);
mxDestroyArray(V);
mxDestroyArray(result);
engEvalString(ep, "close;");
}

The above code works and I am getting the desired results. But it runs very slow. Can anyone suggest me a way to make it fast? Or suggest some other way to find the rank of a boolean matrix. Some libraries are out there, but they seem to have functions only for int or double matrices.

Was it helpful?

Solution

You can find the rank of the Boolean Matrix by finding rank in the Galois Field of 2 (as you are doing in your Matlab code), which is essentially mod 2 arithmetic.

The code below finds the rank of the Boolean Matrix using the same idea by using Gauss Elimination with partial pivoting.

#include <iostream>
#include <vector>

using namespace std;

class BooleanMatrix{
    vector< vector<bool> > mat; //boolean matrix
    int n, m;           //size of matrix nxm
    int rank;           //rank of the matrix

    public:

    /*Constructor
     * Required Parameters:
     * M ==> boolean matrix
     * n ==> number of rows
     * m ==> number of columns
     */
    template <size_t size_m>
    BooleanMatrix(bool M[][size_m], int n, int m){
        this -> n = n;
        this -> m = m;
        for (int i = 0; i < n; i++){
            vector<bool> row(m);
            for (int j = 0; j < m; j++) row[j] = M[i][j];
            mat.push_back(row);         
        }
        gaussElimination();
    }

    /* Does Gauss Elimination with partial pivoting on the matrix */
     void gaussElimination(){
        rank = n;
        for (int i = 0; i < n; i++){
            if (!mat[i][i]){
                int j;
                for (j = i+1; j < n && !mat[j][i]; j++);
                if (j == n){
                       rank--;
                       continue;
                }
                else
                    for (int k = i; k < m; k++){
                        bool t = mat[i][k];
                        mat[i][k] = mat[j][k];
                        mat[j][k] = t;
                    }
            }
            for (int j = i+1; j < n; j++){
                if (mat[j][i]){
                    for (int k = i; k < m; k++)
                        mat[j][k] = mat[j][k] - mat[i][k];
                }
            }
        }
    }

    /* Get the row rank of the boolean matrix
     * If you require the rank of the matrix, make sure that n > m.
     * i.e. if n < m, call the constructor over the transpose.
     */
    int getRank(){
        return rank;
    }
};

int main(){
    bool M1[3][3] = {   {1, 0, 1},
                {0, 1, 1}, 
                {1, 1, 0}   };
    BooleanMatrix booleanMatrix1(M1, 3, 3);
    cout << booleanMatrix1.getRank() << endl;   

    bool M2[4][4] = {   {1,1,1,0},
                {0,1,1,0},
                {0,1,0,0},
                {1,1,1,1}   };
    BooleanMatrix booleanMatrix2(M2, 4, 4);
    cout << booleanMatrix2.getRank() << endl;   
}

This gives result as expected for both the case. The algorithm should work well for all practical purposes. Trivial improvements & application specific changes could be made to suit as per your requirements.

I haven't tested it thoroughly though. If anybody finds any bug, please edit the answer to correct it.

Hope this helps.

OTHER TIPS

A simple solution is to solve the least square problem where operators are defined in the boolean sense:

min_x |matrix * x - vector|^2

Then, if vector is in the span of column vectors of the matrix, the solutions's residual error should be very small.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top