Eigen and boost::serialize

前端 未结 3 2055
陌清茗
陌清茗 2020-12-17 20:29

I tried to write a generic serialize function which takes any dense matrix and serializes it: Some other questions which help but not to the end are here: Question1 Question

3条回答
  •  时光说笑
    2020-12-17 21:03

    I make use of Eigen's plugin based extension:

    /**
     * @file EigenDenseBaseAddons.h
     */
    #ifndef EIGEN_DENSE_BASE_ADDONS_H_
    #define EIGEN_DENSE_BASE_ADDONS_H_
    
    friend class boost::serialization::access;
    template
    void save(Archive & ar, const unsigned int version) const {
      derived().eval();
      const Index rows = derived().rows(), cols = derived().cols();
      ar & rows;
      ar & cols;
      for (Index j = 0; j < cols; ++j )
        for (Index i = 0; i < rows; ++i )
          ar & derived().coeff(i, j);
    }
    
    template
    void load(Archive & ar, const unsigned int version) {
      Index rows, cols;
      ar & rows;
      ar & cols;
      if (rows != derived().rows() || cols != derived().cols() )
        derived().resize(rows, cols);
      ar & boost::serialization::make_array(derived().data(), derived().size());
    }
    
    template
    void serialize(Archive & ar, const unsigned int file_version) {
      boost::serialization::split_member(ar, *this, file_version);
    }
    
    #endif // EIGEN_DENSE_BASE_ADDONS_H_
    

    Configure Eigen to use this pulgin:(simply define the macro before including any Eigen header)

    #ifndef EIGEN_CONFIG_H_
    #define EIGEN_CONFIG_H_
    
    #include 
    #define EIGEN_DENSEBASE_PLUGIN "EigenDenseBaseAddons.h"
    
    #include 
    
    #endif // EIGEN_CONFIG_H_
    

    Though I have not really tested this throughly, it works well and can also deal with Array or any other dense Eigen objects. It also works perfectly for expressions like vec.tail<4>() but may fail (without any compile error) for expression like mat.topRows<2>() or block operations. (See update: now works for sub matrices also)

    In comparison to the other current answer, this works for more set of expression and might avoid some temporary. A non-intrusive version is also probably possible by passing PlainObjectBase objects to the serialize functions..


    /// Boost Serialization Helper
    
    template 
    bool serialize(const T& data, const std::string& filename) {
      std::ofstream ofs(filename.c_str(), std::ios::out);
      if (!ofs.is_open())
        return false;
      {
        boost::archive::binary_oarchive oa(ofs);
        oa << data;
      }
      ofs.close();
      return true;
    }
    
    template 
    bool deSerialize(T& data, const std::string& filename) {
      std::ifstream ifs(filename.c_str(), std::ios::in);
      if (!ifs.is_open())
        return false;
      {
        boost::archive::binary_iarchive ia(ifs);
        ia >> data;
      }
      ifs.close();
      return true;
    }
    

    And some test code:

    VectorXf vec(100);
    vec.setRandom();
    serializeText(vec.tail<5>(), "vec.txt");
    
    MatrixXf vec_in;
    deSerialize(vec_in, "vec.bin");
    assert(vec_in.isApprox(vec.tail<5>()));
    
    serialize(Vector2f(0.5f,0.5f), "a.bin");
    Vector2f a2f;
    deSerializeBinary(a2f, "a.bin");
    assert(a2f.isApprox(Vector2f(0.5f,0.5f)));
    VectorXf axf;
    deSerialize(axf, "a.bin");
    assert(aXf.isApprox(Vector2f(0.5f,0.5f)));
    
    boost::shared_ptr b = boost::make_shared(Vector4f::Random());
    serialize(b, "b.tmp");
    boost::shared_ptr b_in;
    deSerialize(b_in, "b.tmp");
    BOOST_CHECK_EQUAL(*b, *b_in);
    
    Matrix4f m(Matrix4f::Random());
    serialize(m.topRows<2>(), "m.bin");
    deSerialize(m_in, "m.bin");
    

    Update: I made some minor modifications,now serialization of sub matrices also works.

提交回复
热议问题