本文介绍了我是否可以将Eigen稀疏矩阵用于一般存储要求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要模板化的稀疏矩阵实现,但只是为了减少内存占用,不是进行任何数值求解.因此,即使我不需要数学部分,我也尝试使用Eigen.为什么 ?它刚好在我的机器上,而我已经将它用于其他东西了.但是我肯定不是本征专家!

I need a templated sparse matrix implementation but only to reduce memory footprint, not do any numerical solving. So I tried to use Eigen, even though I don't need the math part. Why ? It just happened to be lying on my machine, and I already had used it a little for other stuff. But I am surely no Eigen expert!

上下文:我的类型为T(例如struct T{int a; float b; vector<int> c; };,我需要存储较大的矩阵(例如,大于1000x1000)),并且大多数值都是空值/不相关.

Context: I have a type T (say struct T{int a; float b; vector<int> c; }; and I need to store large matrices of this (say more than 1000x1000) and most of the values are null/irrelevant.

由于我不做任何数学运算,因此我可以提供一个赋值运算符来执行存储/检索操作,如下所示:

Since I don't do any math, I though it would be enough to provide an assignement operator to do storage / retrieval operations, like the following:

int main()
{
    Eigen::SparseMatrix<MyClass> mat(1000,1000); // 1000000 elements
    MyClass b{ 5, 1.2 };
    mat.insert( 3, 4 ) = b;
}

这是一个数据类型,我认为这是必需的:

So here is a datatype, with what I thought was necessary:

struct MyClass
{
    int a;
    float b;
    std::vector<int> v_things;

    MyClass( int aa, float bb ) : a(aa), b(bb) {}
    MyClass( const MyClass& other ) // copy constructor
    {
        a = other.a;
        b = other.b;
        v_things = other.v_things;
    }
    MyClass& operator=( const MyClass& arg )
    {
        if( this != &arg )
        {
            MyClass tmp(arg);
            std::swap( tmp, *this );
        }
        return *this;
    }
};

但这无法编译,因为它似乎要求某种特殊形式的赋值运算符:

But this fails to compile, because it seems to request some special form of the assignment operator:

/usr/include/eigen3/Eigen/src/SparseCore/SparseMatrix.h:1146:27: error: no match for ‘operator=’ (operand types are ‘Eigen::internal::CompressedStorage<MyClass, int>::Scalar {aka MyClass}’ and ‘int’)
    return (m_data.value(p) = 0);'

(编译器:带有-std = c ++ 11的GCC 5.3)

(compiler: GCC 5.3 with -std=c++11)

问题:

  • 是否可以使用Eigen做到这一点?
    • 如果是,我需要添加什么数据类型?这是最好的方法吗?
    • 如果没有,您会建议另一个libray吗?
    • Is it possible to do this with Eigen ?
      • If yes, what do I need to add to the data type ? Is this the best approach ?
      • If no, would you have suggestion on another libray?

      相关的本征手册页:

      • http://eigen.tuxfamily.org/dox/group__TutorialSparse.html
      • http://eigen.tuxfamily.org/dox/classEigen_1_1SparseMatrix.html
      • http://eigen.tuxfamily.org/dox/group__SparseQuickRefPage.html

      推荐答案

      实际上,由于它旨在存储数值,因此您的类型应该可以从文字0中构造/分配.需要确保insert(i,j)返回对初始化为0的标量的引用.

      Indeed, since it is designed to store numerical values, your type is supposed to be constructible/assignable from the literal 0. It is needed to make sure that insert(i,j) returns a reference to a scalar initialized to 0.

      因此您可以通过添加虚拟operator=来解决:

      So you can workaround by adding a dummy operator= :

       MyClass& operator=(int x) { assert(x==0); /* ... */ return *this; }
      

      要使用setFromTriplets,还需要提供operator+=.原因是默认情况下,重复的条目被加在一起.在Eigen 3.3中,将函子(例如lambda)传递给setFromTriplets来定义应如何合并重复项比较干净.在您的情况下,您可以通过一个函子来触发运行时断言,如果它被调用:

      In order to use setFromTriplets, you also need to provide operator+=. The reason is that by default, duplicate entries are summed together. In Eigen 3.3, it is cleaner to pass a functor (e.g.,a lambda) to setFromTriplets defining how duplicates should be merge. In your case, you could just pass a functor triggering a runtime assertion if it is called:

      mat.setFromTriplets(begin,end, [] (const MyClass& a,const MyClass &) {
          assert(false && "found duplicates"); return a; } );
      

      在这种情况下,您不需要定义MyClass::operator+=

      In this case, you don't need to define MyClass::operator+=

      这篇关于我是否可以将Eigen稀疏矩阵用于一般存储要求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-19 17:14