Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eigen library --> initialize matrix with data from file or existing std::vector<string> content (c++)

My question is how to initialize an eigen Matrix, but NOT this way:

matrix << 1,0,1,0,
          1,0,1,0,
          1,0,1,0,

I have a Matrix that looks like the above one ( commas or no commas doesnt matter) stored in a txt file.

I already wrote a function to read in each line and put it into a vector now I want to create a matrix with this data

But it doesn' work and I cant find any page that explains how to assign data to a matrix without writing just the values.(like the example above)

All I need is the data from my file in an eigen Matrix

What I tried so far: (PS: had the idea with the iterators but i guess it will take too long with really big matrices, I just tried this example with a 1-2 dimensional matrix)

int readFromFile (const char * path, vector <string> & mv)
{
    fstream file;
    string line;
    file.open(path);

    while (getline(file,line))
    {
        mv.push_back(line);
    }
    file.close();
    return 0;
}


typedef Matrix <int, 1, 2> MyMatrix;

int fromVectoEigen (vector<string> & source, MyMatrix & target)
{   //for (int i = source.size(); i<0 ; i--)
    //{

        string valuerow = source.back();
        string::iterator it = valuerow.begin();
        target.row(0)<< *it;
        target.row(0)<<*it+1;
        //source.pop_back();
    //}

    return 0;
}

Unfortunately cant just say Matrix.row(i) = vector.back() that doesnt work.

like image 637
dieHellste Avatar asked Dec 26 '13 14:12

dieHellste


2 Answers

The following code works with files containing matrices of arbitrary size:

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

using namespace std;
using namespace Eigen;

#define MAXBUFSIZE  ((int) 1e6)

MatrixXd readMatrix(const char *filename)
    {
    int cols = 0, rows = 0;
    double buff[MAXBUFSIZE];

    // Read numbers from file into buffer.
    ifstream infile;
    infile.open(filename);
    while (! infile.eof())
        {
        string line;
        getline(infile, line);

        int temp_cols = 0;
        stringstream stream(line);
        while(! stream.eof())
            stream >> buff[cols*rows+temp_cols++];

        if (temp_cols == 0)
            continue;

        if (cols == 0)
            cols = temp_cols;

        rows++;
        }

    infile.close();

    rows--;

    // Populate matrix with numbers.
    MatrixXd result(rows,cols);
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < cols; j++)
            result(i,j) = buff[ cols*i+j ];

    return result;
    };

Regards.

like image 60
lackadaisical Avatar answered Sep 24 '22 18:09

lackadaisical


I just released an extension of the Eigen package that does some of what you want. It defines the >> operator, so you can say:

MatrixXd A(5,5); cin >> A;

It also lets you assign a VectorXd to equal a std::vector. The extended version of Eigen can be found here. However, it doesn't (yet) let you copy a std::vector into a MatrixXd object that isn't a vector. The functionality you want is the Map function in Eigen.

like image 45
Eigen Do Better Avatar answered Sep 22 '22 18:09

Eigen Do Better