具有未知行数和列数的矩阵特征库

时间:2014-05-01 18:44:15

标签: c++ eigen

我想将文件中的数据读入Eigen中的矩阵。我编写了所有内容,但遇到了一个问题。我事先还不知道文件中有多少数据点,所以我希望能够在不指定其大小的情况下初始化矩阵。我知道以下初始化矩阵的方法在Eigen中起作用:

MatrixXd A;

但现在如果我那么做

A << 1, 2,
     4, 7;

它不起作用。我希望它在这个例子中将它识别为2x2矩阵,这样我就可以使用它了。所以基本上我的问题是,如何将数据添加到A,而不必指定其大小?

4 个答案:

答案 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)

不可能按照你的要求去做。您希望库如何猜测阵列的形状?如何确定它不是4x11x4。新行与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';
}