私の質問は、固有行列を初期化する方法ですが、[〜#〜] not [〜#〜]このように:
_matrix << 1,0,1,0,
1,0,1,0,
1,0,1,0,
_
上記のようなマトリックス(コンマまたはコンマなしは関係ありません)がtxtファイルに保存されています。
各行を読み取ってベクトルに入れる関数をすでに作成しました。このデータを使用して行列を作成します。
しかし、それは機能せず、値だけを書かずにデータを行列に割り当てる方法を説明するページを見つけることができません(上記の例のように)
必要なのは、固有行列のファイルからのデータだけです
私がこれまでに試したこと:(PS:イテレーターでアイデアを思いついたが、本当に大きな行列では時間がかかりすぎると思う。この例を1〜2次元の行列で試しただけだ)
_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;
}
_
残念ながら、機能しないMatrix.row(i) = vector.back()
とだけ言うことはできません。
次のコードは、任意のサイズの行列を含むファイルで機能します。
#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;
};
よろしく。
私はあなたが望むことのいくつかを行うEigenパッケージの拡張をリリースしました。 >>演算子を定義しているので、次のように言うことができます。
MatrixXd A(5,5); cin >> A;
また、VectorXdをstd :: vectorと等しくなるように割り当てることもできます。 Eigenの拡張バージョンは ここ にあります。ただし、(まだ)std :: vectorをベクターではないMatrixXdオブジェクトにコピーすることはできません。必要な機能は、EigenのMap関数です。
要素ごとの初期化を使用しました(nrowsと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;
私は解決策を見つけたと思います!高速でも効率的でもありませんが、機能します。
#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 ;
}
https://eigen.tuxfamily.org/dox/group__TutorialMapClass.html の例に基づいて、std :: vectorからデータをマッピングするためにEigen :: Mapのみを使用するバリエーション
#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);
イテレータを使用してデータをベクトルに収集し、行列を初期化しました。 vector<double>
への変換は、メソッドの時間のかかる部分のようです。これは、上記のソリューションとほぼ同じ速度です。これを改善する方法についてのアイデアは興味深いでしょう。
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;
}
これが私の解決策です:
#include <istream>
#include <string>
#include <sstream>
#include <vector>
#include <fstream>
#include <iostream>
#include <eigen>
using namespace std;
using namespace Eigen;
// load matrix from an ascii text file.
vector<vector<double>> LoadMatrix(istream* filePath, const string &delim = " \t")
{
string line;
string strnum;
auto data = vector<vector<double>>();
// clear first
data.clear();
// parse line by line
while (getline(*filePath, line))
{
data.Push_back(vector<double>());
for (string::const_iterator i = line.begin(); i != line.end(); ++i)
{
// If i is not a delim, then append it to strnum
if (delim.find(*i) == string::npos)
{
strnum += *i;
if (i + 1 != line.end()) // If it's the last char, do not continue
continue;
}
// if strnum is still empty, it means the previous char is also a
// delim (several delims appear together). Ignore this char.
if (strnum.empty())
continue;
// If we reach here, we got a number. Convert it to double.
double number;
istringstream(strnum) >> number;
data.back().Push_back(number);
strnum.clear();
}
}
return data;
}
Eigen::MatrixXd ConvertToEigenMatrix(std::vector<std::vector<double>> data)
{
Eigen::MatrixXd eMatrix(data.size(), data[0].size());
for (int i = 0; i < data.size(); ++i)
eMatrix.row(i) = Eigen::VectorXd::Map(&data[i][0], data[0].size());
return eMatrix;
}
MatrixXd LoadEigenMatrix(istream* filePath, const string &delim = " \t")
{
auto data = LoadMatrix(filePath, delim);
return ConvertToEigenMatrix(data);
}