【问题标题】:Matrix with unknown number of rows and columns Eigen library具有未知行数和列数的矩阵特征库
【发布时间】:2014-05-01 18:44:15
【问题描述】:

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

MatrixXd A;

但现在如果我再这样做

A << 1, 2,
     4, 7;

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

【问题讨论】:

  • 你的意思是它不起作用? Here 您在文档中有一个相同的示例。
  • @luk32 不,他们在那里指定大小:3x3 矩阵。不起作用意味着它不接受它作为有效语法;换句话说,程序崩溃了。
  • 你点击here了吗? Matrix3f m; m &lt;&lt; 1, 2, 3, 4, 5, 6, 7, 8, 9; std::cout &lt;&lt; m; 那是代码。你能说出不起作用是什么意思吗?
  • @luk32 是的,当然。那你指的是哪个例子?那里的例子用Matrix3f初始化,这不一样,3已经指定了大小。
  • @luk32 不同的是他们通过Matrix3f直接指定为3x3矩阵。我不想那样做。如果您查看我的语法,我指定了MatrixXd,所以我有一个“X”,其中有一个“3”表示大小未知。

标签: c++ eigen


【解决方案1】:

如果你想要的是从一个没有明确指定矩阵大小的文件中读取数据,那么我建议将std::vector 中的条目推回并在解析结束时从@987654322 复制数据@使用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 高效得多。

【讨论】:

  • 听起来很有趣!您能否向我展示一些更详细的代码来说明如何做到这一点(因为您现在有了这些点)?如果这听起来真的很棒!
  • 只需用您自己的代码解析文件替换带有点的行。你说你已经实现了。
  • 是的,但我刚刚尝试过,当我读入数据文件时,有些东西仍然无法正常工作。我可以在 OP 中发布我的代码以便您查看吗?提前非常感谢。
  • 我已经在 OP 中添加了我的代码。如果你能看一下,那就太好了。我想从文件中读取的一行数据的示例是-0.016514677 0.500312859 -0.005198081 -0.020745313 6.968308391 -0.001030603 -0.006184097
  • 我目前遇到的问题如下:(1)对于我在上面评论中发布的值,我得到全零(尽管它适用于整数值)。 (2) map 类以错误的“顺序”读取数据:我希望特征矩阵中的数据与数据文件中的数据具有完全相同的形状,但现在它垂直读取行(列-我认为它的主要顺序)。你知道我可以做些什么来改变这个吗?
【解决方案2】:

来自关于 Matrix 的 Eigen Tutioral


当然,Eigen 不限于维度已知的矩阵 在编译时。 RowsAtCompileTime 和 ColsAtCompileTime 模板 参数可以采用特殊值 Dynamic 表示 大小在编译时未知,因此必须作为运行时处理 多变的。在本征术语中,这样的大小称为 动态尺寸;而在编译时已知的大小称为 固定大小。例如,方便的 typedef MatrixXd,表示一个 动态大小的双精度矩阵定义如下:

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;

【讨论】:

  • 谢谢。是的,我也读过,但是现在如何填充我定义为 MatrixXd A; 的矩阵,就像我的示例中一样?
  • @dreamer 教程说要像这样创建它Matrix&lt;float, 3, Dynamic&gt;
  • 你能告诉我如何为我在 OP 中列出的例子做这件事吗?因为我试过了,但它仍然对我不起作用,所以我认为我错过了一些东西。
  • 啊,这很好:),这就是我需要的。非常感谢:)!
  • Eigen::Matrix&lt;float, Eigen::Dynamic, Eigen::Dynamic&gt; 不需要它是MatixXf
【解决方案3】:

所以我有类似的(但不完全相同的问题),并且感谢这个情节和这个论坛的另一个问题的答案,我创建了那个代码。我有一个未知矩阵大小的文件作为输入,我需要稍后对其进行操作。

我们首先读取文件的第一行,获取数据,放入vector,读取列数。然后我们从文件中读取所有剩余数据,继续解析到向量。

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);

我很高兴看到一些关于效率方面的代码审查,但我认为目前还可以。输入文件是以“制表符/空格”分隔的矩阵。

【讨论】:

    【解决方案4】:

    按照你的要求做是不可能的。您希望库如何猜测数组的形状?怎么能确定不是4x11x4。对于 c++ 编译器,新行无关紧要,因此您的代码与 m &lt;&lt; 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';
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-17
      相关资源
      最近更新 更多