user297883
user297883

Reputation: 3

Using C-style Arrays with Eigen for Matrix Inverse

I have about 1000 lines of code that I wrote in C for a linear programming solver (interior point algorithm). I realized that I need to use Eigen to calculate a matrix inverse, so now I am running my code in C++ instead (runs just fine, it seems). Now I have a bunch of arrays declared in C format, for example: A[30][30];

In my program, I do a bunch of matrix calculations and then need to find an inverse of a matrix at some point, let's call it matrix L[30][30]. To use Eigen, I need to have it in a special Eigen matrix format to call the function m.inverse like this:

//cout << "The inverse of L is:\n" << L.inverse() << endl;

My goal is to find a way... ANY way, to get my data from L to a format that Eigen will accept so I can run this thing. I've spent the last 2 hours researching this and have come up with nothing. :-( I'm fairly new to C, so please be as thorough as you can. I want the most simple method possible. I've read about mappings, but I'm not very clear on pointers sadly (which seems to be an integral part). Is there a way to just loop through each row and column and copy them into an Eigen matrix?

While I'm asking, will I need to take the resultant Eigen matrix and turn it back into a C array? How would that process work? Thanks in advance for any help! I've spent about 50-60 hours on this and it's due this week! This is the LAST thing I need to do and I'll be done with my term project. It's a math class, so the programming side of things are a little fuzzy for me but I'm learning a lot.

Possibly relevant information: -Running on Windows 10 i7 processor Sony VAIO -Compiling with CodeBlocks in C++, but originally written in C -This code is all in a while loop that may be iterated through 10 times or so. -The matrix inverse needs to be calculated for this matrix L each iteration, and the data will be different each time.

Please help! I'm willing to learn, but I need guidance and this class is online so I have virtually none. Thanks so much in advance!

Edit - I saw this and tried to implement it to no avail, but it seems like the solution if I can figure this out:

"Suppose you have an array with double values of size nRows x nCols.

double *X; // non-NULL pointer to some data

You can create an nRows x nCols size double matrix using the Map functionality like this:

MatrixXd eigenX = Map<MatrixXd>( X, nRows, nCols );

The Map operation maps the existing memory region into the Eigen’s data structures. A single line like this allows to avoid to write ugly code of matrix creation, for loop with copying each element in good order etc."

This seems to be a nice solution, but I am clueless on how to do anything with that "double *X" that says to "point to some data". I began looking up pointers and such and it didn't help clarify - I saw all kinds of things about pointing to multi-dimensional arrays that didn't seem to help.

I also don't quite understand the format of the second line. Is every capital X there just going to be the same as the matrix *X in the line before? What would I need to declare/create for that? Or is there an easier way that all of this?

EDIT2: Here is what I have in my program, essentially - this is significantly shrunken down, sorry if it's still too long.

#include <iostream>
#include <Eigen/Dense>

using namespace Eigen;
using namespace std;

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <math.h>

typedef Matrix<double, 30, 30> Matrix30d;

double L[30][30] ={{0}};
double Ax[30][30] = {{0}};          //[A] times [x]                                                        
double At[30][30] = {{0}};          //A transpose
double ct[30][30] = {{0}};         //c transpose                                                                   
double x[30][30] = {{0}};          //primal solution                                                                  
double w[30][30] = {{0}};          //omega, dual solution                                                                 
double s[30][30] = {{0}};          //dual slack                                                             
double u[30][30] = {{0}};          //[c]t - [A]t x [w] - [s]                                                                  
double Atxw[30][30] = {{0}};       //A transpose times omega                                                             
double t[30][30] = {{0}};          //RHS - [A]x[x]                                                              
double v[30][30] = {{0}};          //mu - xij * sij                                                               
double p[30][30] = {{0}};          //vij / xij                                                             
double D2[30][30] = {{0}};         //diagonal of xij/sij                                                               
double AD2[30][30] = {{0}};       //[A] x [D2]                                                                
double AD2xAt[30][30] = {{0}};      //[AD2] x [At]                                                           
double uminp[30][30] = {{0}};      //[u] - [p]                                                            
double AD2xuminp[30][30] = {{0}};    //[AD2] x [uminp]                                                         
double z[30][30] = {{0}};           //[AD2] x [uminp] + [t]                                                              
double Atxdw[30][30] = {{0}};      //[At] x [dw]                                                            
double xt[30][30] = {{0}};         //x transpose                                                            
double bt[30][30] = {{0}};        //b transpose                                                                
Matrix30d Inv;                  //C++ style matrix for Eigen, maybe needed?

int main(){

int r1;                      //rows of A
int c1;                      //columns of A                                                     
int i;                       //row and column counters
int j;                                                                             
int k;
double sum = 0;
double size;                 //size of square matrix being inverted [L]                                                         
double *pointer[30][30];

FILE *myLPproblem;                     

myLPproblem = fopen("LPproblem.txt", "r");   //Opens file and reads in data

float firstLine[4];
int Anz;

for (i = 0; i < 4; i++)
{
    fscanf(myLPproblem, "%f", &firstLine[i]);
}

r1 = firstLine[0];
c1 = firstLine[1];
Anz = firstLine[2];

double A[r1][c1];
double b[r1][1];
double c[1][c1];
int Ap[c1+1];
int Ai[Anz];
double Ax2[Anz];

for(i=0; i<r1; i++){
   for(j=0; j<c1; j++){
     A[i][j]=0;
   }
}

for (i = 0; i < (c1 + 1); i++)
{
    fscanf(myLPproblem, "%d", &Ap[i]);
}

for (i = 0; i < (Anz); i++)
{
    fscanf(myLPproblem, "%d", &Ai[i]);
}

for (i = 0; i < (Anz); i++)
{
    fscanf(myLPproblem, "%lf", &Ax2[i]);
}

for (i = 0; i < (r1); i++)
{
    fscanf(myLPproblem, "%lf", &b[i][0]);
}

for (i = 0; i < (c1); i++)
{
    fscanf(myLPproblem, "%lf", &c[0][i]);
}

fclose(myLPproblem);

int row;
double xval;
int Apj;
int Apj2;

for(j=0; j<c1; j++){

Apj = Ap[j];
Apj2 = Ap[j+1];

for(i=Apj; i<Apj2; i++){
    row = Ai[i];
    xval = Ax2[i];
    A[row][j] = xval;
}
}

size = r1;

for(i=0; i<c1; i++)                        //Create c transpose                                                            
{
    ct[i][0] = c[0][i];
}

for(i=0; i<r1; i++)                       //Create b transpose                                                        
{
    bt[i][0] = b[0][i];
}

for(i=0; i<c1; i++)                        //Create A transpose                                                          
   {
   for(j=0; j<r1; j++)
   {
    At[i][j] = A[j][i];
   }
}

while(1){                                   //Main loop for iterations

for (i = 0; i <= r1; i++) {               //Multiply [A] times [x]                                         
  for (j = 0; j <= 1; j++) {
     sum = 0;
     for (k = 0; k <= c1; k++) {
        sum = sum + A[i][k] * x[k][j];
     }
     Ax[i][j] = sum;
  }
}

sum = 0;                         //Multiply [At] times [w]                                                                   

for (i = 0; i <= c1; i++){
  for (j = 0; j <= 1; j++) {
     sum = 0;
     for (k = 0; k <= r1; k++) {
        sum = sum + At[i][k] * w[k][j];
     }
     Atxw[i][j] = sum;
  }
}

for(i=0; i<c1; i++)                 //Subtraction to create matrix u                                                  
{for(j=0; j<1; j++)
    {
     u[i][j] = (ct[i][j]) - (Atxw[i][j]) - (s[i][j]);
    }
}

for(i=0; i<r1; i++)                     //Subtraction to create matrix t                                                      
{for(j=0; j<1; j++)
    {
     t[i][j] = (b[i][j]) - (Ax[i][j]);
    }
}

for(i=0; i<c1; i++)              //Subtract and multiply to make matrix v                                                  
{for(j=0; j<1; j++)
    {
     v[i][j] = mu - x[i][j]*s[i][j];
    }
}

for(i=0; i<c1; i++)               //create matrix p                                                             
{for(j=0; j<1; j++)
    {
     p[i][j] = v[i][j] / x[i][j];
    }
}

for(i=0; i<c1; i++)                //create matrix D2                                                              
{for(j=0; j<c1; j++)
    {
     if(i == j){
     D2[i][j] = x[i][0] / s[i][0];
     }else{
     D2[i][j] = 0;
     }
    }
}

sum = 0;                                                                        

for (i = 0; i <= r1; i++) {           //Multiply [A] times [D2]
  for (j = 0; j <= c1; j++) {
     sum = 0;
     for (k = 0; k <= c1; k++) {
        sum = sum + A[i][k] * D2[k][j];
     }
     AD2[i][j] = sum;
  }
}

sum = 0;                                                                        

for (i = 0; i <= r1; i++) {     //Multiply [AD2] times [At], to be inverted!
  for (j = 0; j <= r1; j++) {
     sum = 0;
     for (k = 0; k <= c1; k++) {
        sum = sum + AD2[i][k] * At[k][j];
     }
     AD2xAt[i][j] = sum;
  }
}

//Here is where I need to calculate the inverse (and determinant probably)     of matrix AD2xAt.  I'd like to inverse to then be stored as [L]. 
//cout << "The determinant of AD2xAt is " << AD2xAt.determinant() << endl;
//cout << "The inverse of AD2xAt is:\n" << AD2xAt.inverse() << endl;

printf("\n\nThe inverse of AD2xAt, L, is : \n\n");   //print matrix L                               

 for (i=0; i<size; i++)
 {
     for (j=0; j<size; j++)
     {
         printf("%.3f\t",AD2xAt[i][j]);
     }
     printf("\n");
 }
}

return 0;
}

In a nutshell, it reads matrices from a file, calculates a bunch of matrices, then needs to invert AD2xAt and store it as L. The critical part is at the end, where I need to take the inverse (scroll to the bottom - I have it commented).

Upvotes: 0

Views: 789

Answers (1)

Armali
Armali

Reputation: 19415

Have you tried Map<MatrixXd>(A[0],30,30).inverse() ?? – ggael

What you're proposing seems like it would be doing both at once or something?

Right, the Map<MatrixXd>() returns the Eigen's MatrixXd, on which the method inverse() is called.

May I ask what the [0] is after A?

[0] is the array subscript operator [] designating the 0-th element; A[0] is the initial row of the matrix A[30][30] and is converted to the pointer to A[0][0] corresponding to the X you saw.

Upvotes: 1

Related Questions