According to this page there should be a sum function provided in ublas, but I can't get the following to compile:
boost::numeric::ublas::matrix<double> mymatrix;
std::cout << boost::numeric::ublas::sum(mymatrix);
error is:
testcpp:146:144: error: no matching function for call to
‘sum(boost::numeric::ublas::matrix&)’
I'm #includeing:
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/matrix_proxy.hpp>
Am I missing an include, or did I misunderstand the docs? How would I achieve this (I'm trying to sum up all elements of a matrix and produce a single double)?
As pointed out in comments, sum only applies to vectors (see documentation)
You could certainly get at m.data() and sum the values that way, but you are using a linear algebra library! Multiply a row vector of 1's by your matrix, and sum the result:
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
namespace bls = boost::numeric::ublas;
int main()
{
bls::matrix<double> m(3, 3);
for (unsigned i = 0; i < m.size1(); ++i)
for (unsigned j = 0; j < m.size2(); ++j)
m(i, j) = 3 * i + j;
std::cout << "Sum of all elements of " << m << " is "
<< sum(prod(bls::scalar_vector<double>(m.size1()), m)) << '\n';
}
A more reusable approach would be to define a sum that takes a matrix_expression, as the shark library did.
Related
I have a 2d boost matrix (boost::numeric::ublas::matrix) of shape (n,m), with the first column being the timestamp. However, the data I'm getting is out of order. How can I sort it with respect to the first column, and what would be the most efficient way to do so? Speed is critical in this particular application.
As I commented ublas::matrix might not be the most natural choice for a task like this. Trying the naive approach using matrix_row and some range magic:
Live on Coliru
#define _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/matrix_proxy.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/irange.hpp>
#include <boost/range/algorithm.hpp>
#include <iomanip>
#include <iostream>
using namespace boost::adaptors;
using Matrix = boost::numeric::ublas::matrix<float>;
using Row = boost::numeric::ublas::matrix_row<Matrix>;
static auto by_col0 = [](Row const& a, Row const& b) { return a(0) < b(0); };
int main()
{
constexpr int nrows = 3, ncols = 4;
Matrix m(nrows, ncols);
for (unsigned i = 0; i < m.size1(); ++i)
for (unsigned j = 0; j < m.size2(); ++j)
m(i, j) = (10 - 3.f * i) + j;
std::cout << "before: " << m << "\n";
auto getrow = [&](int i) { return Row(m, i); };
sort(boost::irange(nrows) | transformed(getrow), by_col0);
std::cout << "after: " << m << "\n";
}
Does sadly confirm that the abstraction of the proxy doesn't hold:
before: [3,4]((10,11,12,13),(7,8,9,10),(4,5,6,7))
after: [3,4]((10,11,12,13),(10,11,12,13),(10,11,12,13))|
Oops.
Analysis?
I can't say I know what's wrong. std::sort is defined in terms of ValueSwappable which at first glance seems to work fine for matrix_row:
auto r0 = Row(m, 0);
auto r1 = Row(m, 1);
using std::swap;
swap(r0, r1);
Prints Live On Coliru
Maybe this starting point gives you something helpful. Since it's tricky like this, I'd highly consider using another data structure that is more conducive to your task (boost::multi_array[_ref] comes to mind).
I need to get the certain rows, when a element is a vector is one.
For an example:
std::vector<bool>index{}; //contains 6000 numbers of elements 0 and 1
Now I have a matrix mat of shape (6000,4)
How can I get the rows in a matrix mat, when the corresponding element is 1 in vector index.
mat = mat[index];
If I understand your question clearly, you may find good answer from this good reply:
Eigen3 select rows out based on column conditions
Using new feature (Eigen 3.4 or 3.3.90 development branch) and take the core code from the previous link:
#include <Eigen/Dense>
#include <iostream>
#include <vector>
using namespace Eigen;
int main() {
MatrixXd mat = MatrixXd::Random(10,5);
std::cout << "original:\n" << mat << std::endl;
std::vector<int> keep_rows;
for (int i = 0; i < mat.rows(); ++i) {
if (mat(i,mat.cols() - 1) > 0.3) {
keep_rows.push_back(i);
}
}
VectorXi keep_cols = VectorXi::LinSpaced(mat.cols(), 0,mat.cols());
MatrixXd mat_sel = mat(keep_rows, keep_cols);
std::cout << "selected:\n" << mat_sel << std::endl;
}
It uses the similar style of the Matlab:
MatrixXd mat_sel = mat(keep_rows, keep_cols);
But the columns and rows that should be kept are stored in an
Eigen::VectorXi
or in a
std::vector<int>
I use the eigen library to perform the sparse matrix operations, particularly, to fill a sparse matirx. But the rows and cols are very large in our case, which results in a long time for filling the sparse matrix. Is there any efficient way to do this (maybe by the other libraries)?
Below is the my code:
SparseMatrix mat(rows,cols);
mat.reserve(VectorXi::Constant(cols,6));
for each i,j such that v_ij != 0
mat.insert(i,j) = v_ij;
mat.makeCompressed();
The order in which a SparseMatrix is filled can make an enormous difference in computation time. To fill a SparseMatrix matrix quickly, the elements should be addressed in a sequence that corresponds to the storage order of the SparseMatrix. By default, the storage order in Eigen's SparseMatrix is column major, but it is easy to change this.
The following code demonstrates the time difference between a rowwise filling of two sparse matrices with different storage order. The square sparse matrices are relatively small and nominally identical. While the RowMajor matrix is almost instantly filled, it takes a much longer time (about 30 seconds on my desktop computer) in the case of ColMajor storage format.
#include <iostream>
#include <Eigen/Dense>
#include <Eigen/SparseCore>
#include <random>
using namespace Eigen;
typedef SparseMatrix<double, RowMajor> SpMat_RM;
typedef SparseMatrix<double, ColMajor> SpMat_CM;
// compile with -std=c++11 -O3
int main() {
const int n = 1e4;
const int nnzpr = 50;
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> randInt(0, n-1);
SpMat_RM m_RM(n,n);
m_RM.reserve(n);
SpMat_CM m_CM(n,n);
m_CM.reserve(n);
std::cout << "Row-wise filling of [" << n << " x " << n << "] sparse matrix (RowMajor) ..." << std::flush;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < nnzpr; ++j) {
int col = randInt(gen);
double val = 1. ; // v_ij
m_RM.coeffRef(i,col) = val ;
}
}
m_RM.makeCompressed();
std::cout << "done." << std::endl;
std::cout << "Row-wise filling of [" << n << " x " << n << "] sparse matrix (ColMajor) ..." << std::flush;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < nnzpr; ++j) {
int col = randInt(gen);
double val = 1.; // v_ij
m_CM.coeffRef(i,col) = val ;
}
}
m_CM.makeCompressed();
std::cout << "done." << std::endl;
}
I'm writing some numerical code in C++ and chose to use the Eigen library. One of the reasons for this that it seems to support band matrices.
The only info I've been able to find is this file http://eigen.tuxfamily.org/dox/BandMatrix_8h_source.html. But being new to C++, I'm not even sure how to #include it.
(I have a version of it on my file system, under /usr/include/eigen3/Eigen/src/Core/BandMatrix.h)
#include <Eigen/Core/BandMatrix>
doesn't work
#include <Eigen/Core>
does, but I can't find the BandMatrix class.
Can you provide some sample code that an initializes a - say tridiagonal - band matrix? Any help would be appreciated! Thanks
ps. I also tried working around this by using the unsupported Skyline module
#include <Eigen/Skyline>
(adding -I/usr/include/eigen3/unsupported switch) but this introduces a bunch of compilation errors starting with /usr/include/eigen3/unsupported/Eigen/src/Skyline/SkylineUtil.h:74:44: error: type/value mismatch at argument 2 in template parameter list for ‘template<class T, class StorageKind> struct Eigen::internal::eval’
To include it you would just #include <Eigen/Core> (assuming -I /usr/include/eigen3/) as it's included by that file (Eigen/Core: line ~341):
#include "src/Core/BandMatrix.h"
As for how to use it, I would refer to the test/bandmatrix.cpp file:
using Eigen::internal::BandMatrix;
void test_bandmatrix()
{
typedef BandMatrix<float>::Index Index;
for(int i = 0; i < 10*g_repeat ; i++) {
Index rows = internal::random<Index>(1,10);
Index cols = internal::random<Index>(1,10);
Index sups = internal::random<Index>(0,cols-1);
Index subs = internal::random<Index>(0,rows-1);
CALL_SUBTEST(bandmatrix(BandMatrix<float>(rows,cols,sups,subs)) );
}
}
After reading the BandMatrix.h file, I'm not sure it actually does what you really want. It appears to be just a storage class without any band specific operations. Any operations would have to be done after copying to a dense matrix with band.toDenseMatrix().
As for how to initialize a BandMatrix, here's a quick demo.
#include <Eigen/Core>
#include <iostream>
using Eigen::internal::BandMatrix;
int main()
{
int rows = 7;
int cols = 6;
int sups = 2;
int subs = 3;
BandMatrix<float> bm(rows,cols,sups,subs);
for(int i = -bm.subs(); i <= bm.supers(); ++i)
{
bm.diagonal(i).setConstant(0);
}
std::cout << bm.toDenseMatrix() << "\n\n";
bm.diagonal().setConstant(1010);
std::cout << bm.toDenseMatrix() << "\n\n";
for(int i = 1; i <= bm.supers(); ++i)
{
bm.diagonal(i).setConstant(i);
}
for(int i = 1; i <= bm.subs(); ++i)
{
bm.diagonal(-i).setConstant(-i);
}
std::cout << bm.toDenseMatrix() << "\n\n";
bm.diagonal(-2)(3) = 2345.f;
std::cout << bm.toDenseMatrix() << "\n\n";
}
Note that it doesn't appear that any operators besides operator= are implemented for the BandMatrix.
can someone please provide an example of how to use uBLAS product to multiply things? Or if there's a nicer C++ matrix library you can recommend I'd welcome that too. This is turning into one major headache.
Here's my code:
vector<double> myVec(scalar_vector<double>(3));
matrix<double> myMat(scalar_matrix<double>(3,3,1));
matrix<double> temp = prod(myVec, myMat);
Here's the error:
cannot convert from 'boost::numeric::ublas::matrix_vector_binary1<E1,E2,F>' to 'boost::numeric::ublas::matrix<T>'
I have exhausted my search. Stackoverflow has a question about this here. Boost documentation has an example here.
I've copied the code from example, but it's of no use to me because the template magic that works for stdout is useless to me.
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
int main () {
using namespace boost::numeric::ublas;
matrix<double> m (3, 3);
vector<double> v (3);
for (unsigned i = 0; i < std::min (m.size1 (), v.size ()); ++ i) {
for (unsigned j = 0; j < m.size2 (); ++ j)
m (i, j) = 3 * i + j;
v (i) = i;
}
std::cout << prod (m, v) << std::endl;
std::cout << prod (v, m) << std::endl;
}
The product of a vector and a matrix is a vector, not a matrix.
I haven't looked that much at Boost uBLAS, but Eigen sure is nice, and has good performance as well.