我可以将Eigen稀疏矩阵用于一般存储要求

keb*_*ebs 4 c++ matrix sparse-matrix eigen

我需要一个模板化的稀疏矩阵实现,但只是为了减少内存占用,而不是做任何数值求解.所以我尝试使用Eigen,即使我不需要数学部分.为什么?它碰巧躺在我的机器上,我已经用它来做其他东西了.但我肯定不是本征专家!

背景:我有一个类型T(比如struct T{int a; float b; vector<int> c; };,我需要存储的大型矩阵这个(比如超过1000×1000)和大部分值为null /无关.

由于我没有做任何数学运算,我认为提供存储/检索操作就足以提供存储/检索操作,如下所示:

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

所以这是一个数据类型,我认为是必要的:

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;
    }
};
Run Code Online (Sandbox Code Playgroud)

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

/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);'
Run Code Online (Sandbox Code Playgroud)

(编译器:GCC 5.3,-std = c ++ 11)

问题:

  • 是否可以用Eigen做到这一点?
    • 如果是,我需要添加什么数据类型?这是最好的方法吗?
    • 如果不是,你会对另一个图书馆有什么建议吗?

相关的本征手册页:

gga*_*ael 5

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

所以你可以通过添加一个虚拟来解决operator=:

 MyClass& operator=(int x) { assert(x==0); /* ... */ return *this; }
Run Code Online (Sandbox Code Playgroud)

编辑:

为了使用setFromTriplets,您还需要提供operator+=.原因是默认情况下,重复的条目汇总在一起.在Eigen 3.3中,传递函子(例如,lambda)以setFromTriplets定义重复应该如何合并更为清晰.在您的情况下,如果调用它,您可以传递一个触发运行时断言的仿函数:

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

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