我想将文件中的数据读入Eigen中的矩阵。我编写了所有内容,但遇到了一个问题。我事先还不知道文件中有多少数据点,所以我希望能够在不指定其大小的情况下初始化矩阵。我知道以下初始化矩阵的方法在Eigen中起作用:
MatrixXd A;
但现在如果我那么做
A << 1, 2,
4, 7;
它不起作用。我希望它在这个例子中将它识别为2x2矩阵,这样我就可以使用它了。所以基本上我的问题是,如何将数据添加到A,而不必指定其大小?
答案 0 :(得分:5)
如果您想要的是从未明确指定矩阵大小的文件中读取数据,那么我建议在std::vector
中推回条目,并在解析副本的末尾推回来自std::vector
使用Map
:
MatrixXf A;
std::vector<float> entries;
int rows(0), cols(0);
while(...) { entries.push_back(...); /* update rows/cols*/ }
A = MatrixXf::Map(&entries[0], rows, cols);
这比每次调用conservativeResize
都要高效。
答案 1 :(得分:2)
关于Matrix
的本征论文当然,Eigen不限于尺寸已知的矩阵 在编译时。 RowsAtCompileTime和ColsAtCompileTime模板 参数可以取特殊值Dynamic表示 大小在编译时是未知的,因此必须作为运行时处理 变量。在Eigen术语中,这种大小称为a 动态尺寸;而在编译时已知的大小称为a 固定大小。例如,方便typedef MatrixXd,意思是a 具有动态大小的双精度矩阵定义如下:
typedef Matrix<double, Dynamic, Dynamic> MatrixXd;
同样,我们将一个自解释的typedef VectorXi定义为 如下:
typedef Matrix<int, Dynamic, 1> VectorXi;
你可以完美地拥有,例如具有动态的固定行数 列数,如:
Matrix<float, 3, Dynamic>
以下是我刚刚做的一个例子:
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> myMatrix;
myMatrix.resize(1, 1);
myMatrix(0, 0) = 1.0;
myMatrix.resize(2, 2);
myMatrix(1, 1) = 1.0;
myMatrix.resize(3, 3);
myMatrix(2, 2) = 1.0;
myMatrix.resize(4, 4);
myMatrix(3, 3) = 1.0;
答案 2 :(得分:1)
因此,我遇到了类似(但不完全相同的问题)的问题,并感谢此图并回答了该论坛的另一个问题,我创建了该代码。我有一个未知矩阵大小的文件作为输入,以后需要对其进行操作。
我们首先读取文件的第一行,获取数据,放入向量中,读取列数。然后,我们从文件中读取所有其余数据,继续解析为向量。
void getTimeSeries(const char* TimeSeriesFileName1)
{
std::ifstream ifile(TimeSeriesFileName1, std::ios::in);
std::vector<double> LineOfTimeSeriesFile;
std::string line;
int rows(0), cols(0);
double number;
//get number of columns you have to read the first line
if (ifile.good())
{
std::getline(ifile, line);
std::stringstream ss(line);
while (ss>>number)
{
++cols;
LineOfTimeSeriesFile.push_back(number);
}
std::cout << cols << std::endl;
}
// consume and discard token from stream.
if (ifile.fail())
{
ifile.clear();
std::string token;
ifile >> token;
}
//Read all the data into a one big vector
do
{
// read as many numbers as possible.
for (number = 0; ifile >> number;) {
LineOfTimeSeriesFile.push_back(number);
}
// consume and discard token from stream.
if (ifile.fail())
{
ifile.clear();
std::string token;
ifile >> token;
}
}
while (!ifile.eof());
//get the number of rows
rows = LineOfTimeSeriesFile.size()/cols;
for (std::size_t i=0; i < LineOfTimeSeriesFile.size(); ++i)
{
std::cout << LineOfTimeSeriesFile[i] << std::endl;
std::cout << "Rows: " << cols << ", Cols: " << rows << ", points: " << LineOfTimeSeriesFile.size() << std::endl;
}
//Here we map the matrix
timeSeriesMatrix = MatrixXd::Map(&LineOfTimeSeriesFile[0], rows, cols);
我很高兴看到对此代码进行一些效率方面的审查,但我认为目前还可以。输入文件是用“制表符/空格”分隔的矩阵。
答案 3 :(得分:0)
不可能按照你的要求去做。您希望库如何猜测阵列的形状?如何确定它不是4x1
或1x4
。新行与c ++编译器无关,因此您的代码与m << 1,2,3,4;
相同。
动态数组是动态的,因为它们的大小在编译时并不知道,而是在运行时。但是,在放入元素之前,您仍需要设置矩阵的大小/形状,因为库需要知道需要为矩阵分配多少空间。
默认情况下,Matrix m;
的大小为0x0
。在放入元素之前,您需要调整它的大小。
例如
#include<Eigen/Core>
#include<iostream>
int main(){
Eigen::MatrixXd m;
m.resize(2,2);
m << 1, 2, 3, 4;
std::cout << m << '\n';
m.resize(1,4);
std::cout << m << '\n';
}