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

前端 未结 7 1120
你的背包
你的背包 2020-12-25 08:00

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,


        
相关标签:
7条回答
  • 2020-12-25 08:36

    I think I found a solution! Its not fast or efficient but it works:

    #include "topo.h"
    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <Eigen/Dense>
    #include <Eigen/Sparse>
    #include <iterator>
    #include <algorithm>
    
    
    using namespace std;
    using namespace Eigen;
    
    /**Read data from File and store it in vector as string**/
    int readFromFile (const char * path, vector <string> & mv) // muss vector vorher resized werden? wenn ja lese zeilenanzahl
    {
        fstream file;
        string line;
        file.open(path);
    
        while (getline(file,line)) // lese zeile für zeile
        {
            mv.push_back(line); //fülle vector von hinten last in first
        }
        file.close();
        return 0;
    }
    
    
    typedef Matrix <int, 4, 4> MyMatrix; // Matrix später dynamisch
    
    /**Parsing data to be used as Eigen Matrix**/
    int fromVectoEigen (vector<string> & source, MyMatrix & target)
    {   /**convert string to int and write it to the two dimensional array **/
        int array [4][4]; // noch resize nach vectorsize -->matrizen sind quadratisch
        int i = source.size();
        for ( i= i-1 ; i >= 0 ; i-- ) // da nur von hintern auf vector zugreifbar auch von hinten bei array anfangen
        {
            string myString = source.back(); // leztzes Element von Vector als String
            stringstream ssin(myString);
            int j = 0;
            while (ssin.good() && j < 4) // auch hier vectorsize später dynamisch
                {
                ssin >> array[j][i]; // fülle spalten in i.ter zeile
                ++j;
                }
    
    
            source.pop_back(); //lösche letztes element
    
        }
    //        cout<<array[0][0]<<array[1][0]<<array[2][0]<<array[3][0]<<'\n';
    //        cout<<array[0][1]<<array[1][1]<<array[2][1]<<array[3][1]<<'\n';
    //        cout<<array[0][2]<<array[1][2]<<array[2][2]<<array[3][2]<<'\n';
    //        cout<<array[0][3]<<array[1][3]<<array[2][3]<<array[3][3]<<'\n';
    //
        /** from 2 dimensional array to one dimensional array**/
        int newarray [16]; // vectorsize * vectorsize
        int k = 0;
        for ( int i = 0 ; i< 4 ; i++) // vectorsize
        {   for (int j = 0 ; j<4; j++) // vectorsize
                {
                    newarray[k]=array[j][i];
                    k++;
                }
    
        }
        /**create Eigen Matrix from Array**/
        target= Map<Matrix4i>(newarray);
        target.transposeInPlace();
        cout<<target<<'\n';
    
    
    
    return 0 ;
    }
    
    0 讨论(0)
  • 2020-12-25 08:39

    I used element-wise initialization (assuming we know nrows and ncols):

    MatrixXf X = MatrixXf::Zero(nrows,ncols);
    ifstream fin ("./data.txt");
    
    if (fin.is_open())
    {
        for (int row = 0; row < nrows; row++)
            for (int col = 0; col < ncols; col++)
            {
                float item = 0.0;
                fin >> item;
                X(row, col) = item;
            }
        fin.close();
    }
    cout << "X = " << endl << X << endl;
    
    0 讨论(0)
  • 2020-12-25 08:41

    I used iterators to collect the data in a vector and then initialize the matrix. The conversion to the vector<double> seem to be the time-consuming part of the method, which approximately has the same speed as the solutions above. Ideas on how to improve this would be interesting.

    template <class T>
    using Tmat = Eigen::Matrix<T,Dynamic,Dynamic>;
    
    Tmat<double> txt_to_mat(std::string path, int rows, int cols)
    {
        std::ifstream fstr(path.c_str());
        std::vector<double> data_vec = std::vector<double>{
            std::istream_iterator<double>(fstr),
            std::istream_iterator<double>()
        };
    
        Tmat<double> mat(rows, cols);
        for(int i=0; i<rows; i++){
            for(int j=0; j<cols; j++){
                mat(i,j) = data_vec[i*cols + j];
            }
        }
    
        return mat;
    }
    
    0 讨论(0)
  • 2020-12-25 08:45

    A variation using only Eigen::Map for mapping data from std::vector, based on examples from https://eigen.tuxfamily.org/dox/group__TutorialMapClass.html

    #include <vector>
    #include <Eigen/Dense>
    
    std::vector<double> myStdVector;
    
    // Insert code for filling myStdVector here
    // ....
    
    // Detect or set number of rows/columns
    size_t numRows = 3;
    size_t numCols = 7;
    
    typedef Eigen::Map<Eigen::MatrixXd> Mapper;
    Mapper myMatrix(&myStdVector.data()[0], numRows, numCols);
    
    0 讨论(0)
  • 2020-12-25 08:51

    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.

    0 讨论(0)
  • 2020-12-25 08:51

    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.

    0 讨论(0)
提交回复
热议问题