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.
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).
Please tell me what is wrong in my approach.
When I run the code, it is taking too long to compute to see the result.
#include <iostream>
#include <vector>
using namespace std;
vector<int> vec;
vector<int> sort(vector<int> x) {
vector<int> y;
int i = 1;
reset:for(i = 1; i <= x.size(); i++){
for (int j = 1; j <= x.size();) {
if (j == i) {
j++;
}
else {
if (x[i - 1] > x[j - 1]) {
j++;
}
else {
i++;
goto reset;
}
}
}
y.push_back(x[i - 1]);
x.erase(x.begin() + i - 1);
}
return y;
}
int main(){
vec.push_back(5);
vec.push_back(9);
vec.push_back(3);
vec.push_back(6);
vec.push_back(2);
for (int i = 1; i <= vec.size(); i++) {
cout << sort(vec)[i-1] << " ";
}
}
I am sorting this given sequence of 5 integers into descending order. Please help.
My plan was to search for the greatest integer in the whole vector x and move to it to the vector y and repeat the process.
Simple bubble-sort example
I think that your sort function is entering an infinite loop because of the goto reset statement. If you want to implement a simple bubble-sort algorithm, you can do it like this:
#include <iostream>
#include <utility>
#include <vector>
void bubble_sort(std::vector<int>& v) {
if(v.size() == 0) return;
for(int max = v.size(); max > 0; max--) {
for(int i = 1; i < max; i++) {
int& current = v[i - 1];
int& next = v[i];
if(current < next)
std::swap(current, next);
}
}
}
This function takes a vector, and for every consecutive pair of elements in the vector, if they're out of order, it swaps them. This results in the smallest element "bubbling" to the top of the vector. The process is repeated until all the elements are in order.
If we test it, we see that it prints the right answer:
int main() {
std::vector<int> test = {5, 9, 3, 6, 2};
bubble_sort(test);
for(int i : test) {
std::cout << i << ' ';
}
std::cout << '\n';
}
Using std::sort to do this faster
The standard library provides a sort function that'll sort pretty much anything. std::sort is really well implemented, it's more efficient than bubble sort, and it's really easy to use.
By default, std::sort orders things in ascending order, although it's easy to change it so that it works in descending order. There are two ways to do this. The first way sorts the vector using the reverse iterators (which allow you to pretend the vector is in reverse order), and the second way sorts the vector using std::greater, which tells std::sort to sort things in reverse order.
// Way 1:
std::sort(test.rbegin(), test.rend());
// Way 2:
auto compare_func = std::greater<>();
std::sort(test.begin(), test.end(), compare_func);
We can re-write the program using std::sort:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> test = {5, 9, 3, 6, 2};
auto compare_function = std::greater<>();
std::sort(test.begin(), test.end(), compare_function);
for(int i : test) {
std::cout << i << ' ';
}
std::cout << '\n';
}
Why can't you just use std:sort? You can do this:
sort(vec.begin(), vec.end(), [](const int a, const int b) {return a > b; }); //1
As suggested in the comments, there are two alternatives to the above:
std::sort(vec.begin(), vec.end(), std::greater<>()); //2
and:
std::sort(vec.rbegin(), vec.rend()); //3
(2) and (3) avoid a custom comparison function, and (2) is arguably more explicit about it's intent. But I was interested in the performance, and so I did a quick bench comparison of the three.
With Clang 12.0, (1) was fastest:
Clang results here
However, with GCC 10.3 all three were near identical:
GCC results here
Interesting results! With GCC, it's your choice as to which version you prefer; otherwise I would go for (1) or (2).
I'm looking for a clean way to shed non-contiguous indices in using the Armadillo linear algebra library for C++. I have some code included below, but it seems like there is probably a better way to do it. Any advice appreciated.
The following code works for removing indexes in ind from (column) vector a, but feels clunky.
for(uword k = ind.n_elem; k>0; k--){
a.shed_row(ind(k-1));
}
Any thoughts?
Here is one way using a templated function for dropping rows based on a (sorted) uvec of indexes to exclude. You get the missing indexes from std::set_difference and then go from there.
#define ARMA_USE_CXX11
#include <armadillo>
#include <iostream>
template <class T>
T drop_rows(T a, arma::uvec exclude) {
arma::uvec full_range = arma::regspace<arma::uvec>(0, a.n_rows - 1);
std::vector<int> diff;
std::set_difference(full_range.begin(), full_range.end(),
exclude.begin(), exclude.end(),
std::inserter(diff, diff.begin()));
T b = a.rows(arma::conv_to<arma::uvec>::from(diff));
return b;
}
int main() {
arma::uvec exclude = {0, 1, 4};
arma::vec a = arma::linspace<arma::vec>(100, 500, 5);
arma::vec b = drop_rows(a, exclude);
std::cout << b << std::endl;
arma::mat A = arma::mat(5, 5, arma::fill::eye);
arma::mat B = drop_rows(A, exclude);
std::cout << B << std::endl;
return 0;
}
I'm trying to do something like:
#include <iostream>
#include <vector>
#include <ctime>
class Clickomania
{
public:
Clickomania();
std::vector<std::vector<int> > board;
};
Clickomania::Clickomania()
: board(12, std::vector<int>(8,0)) <<<<<<<
{
srand((unsigned)time(0));
for(int i = 0; i < 12; i++)
{
for(int j = 0; j < 8; j++)
{
int color = (rand() % 6) + 1;
board[i][j] = color;
}
}
}
However, apparently I can't initialize the "board" vector of vectors this way.
How can I create a public member of a 2d vector type and initialize it properly?
you should use the constructor that allows you to specify size and initial value for both vectors which may make it a bit easier altogether.
something like:
vector<vector<int>> v2DVector(3, vector<int>(2,0));
should work.
Use a matrix instead:
(Basic example from boost documentation)
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
int main () {
using namespace boost::numeric::ublas;
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 << m << std::endl;
}
Compiling your code with g++, the error I get is that neither srand() nor rand() were declared. I had to add #include <cstdlib> for the code to compile. But once I did that, it worked just fine. So, I'd say that other than adding that include statement, your code is fine. You're initializing the vector correctly.
Perhaps the code you have doesn't quite match what you posted? I would assume that if your actual code didn't include cstdlib, that you would have quickly understood that that was the problem rather than something with vector. So, if your code doesn't quite match what you posted, maybe that's the problem. If not, what compiler are you using?
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.