I would like to get the weighted_median of an unsorted, variable
length, eigen c++ vectorXf object. It seems i can use the boost
weighted_median function from boost's statistical accumulators
library to do that efficiently [?].
In essence, i'm trying to do something very similar to what is done
here. I'm not sure boost's accumulator are the right framework
for this task (if not please advice!), but i've not found another
out the shelf implementation of the O(n) weighted median out there.
My question at this point is whether there a way to replace the
"for(int i=0;i<100;i++)" loop below by a more elegant construct?
P.S. i've seen this SO question, but it's not
really clear how to turn the answer there unto an
operation-able solution.
#include <Eigen/Dense>
#include <iostream>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/median.hpp>
#include <boost/accumulators/statistics/weighted_median.hpp>
using namespace boost::accumulators;
using namespace Eigen;
int main(){
accumulator_set<float, stats<tag::median > > acc1;
accumulator_set<float, stats<tag::median >,int> acc2;
VectorXi rw=VectorXi::Random(100);
VectorXf rn=VectorXf::Random(100);
rw=rw.cwiseAbs();
for(int i=0;i<100;i++){
acc1(rn(i));
acc2(rn(i),weight=rw(i));
}
std::cout << " Median: " << median(acc1) << std::endl;
std::cout << "Weighted Median: " << median(acc2) << std::endl;
return 0;
}
What you're trying to do is to use the boost accumulators to accumulate values in a container of some sort. You'll notice that even passing std::vector<float> to an accumulator won't work. Accumulators are simply not meant to be used that way. You can use accumulators to accumulate vector- or matrix-valued values, of course - but that's not what you're after here.
You can use std::for_each to get rid of the explicit loop, and that's about it:
// median
using boost::bind;
using boost::ref;
std::for_each(rn.data(), rn.data()+rn.rows(), bind<void>( ref(acc1), _1 ) );
The question you link to is not relevant anymore in the latest release version of Eigen3. The code given there runs just fine and produces correct results.
Related
Is there a way to apply non-modifying standard library algorithms to discrete functions instead of containers?
For example, consider the following function
int sqr(int i)
{
return i*i;
}
How can I use std::find or std::lower_bound to search for the value 49, i.e. the algorithm should return 7? The easiest way would be to put the returns into a vector and apply the algorithm to the vector -- but this is obviously inefficient.
Hypothetically, you could use something like boost::iterator::counting_iterator. E.g., the following finds that 4 is the number whose square is 16:
#include <algorithm>
#include <iostream>
#include <boost/iterator/counting_iterator.hpp>
using namespace std;
int main(int, char**)
{
auto f = std::find_if(
boost::make_counting_iterator<int>(0),
boost::make_counting_iterator<int>(20),
[](int i){return i * i == 16;});
cout << std::distance(
boost::make_counting_iterator<int>(0),
f) << endl;
return 0;
}
I think that this approach is problematic in many ways. In the above, in particular, note that it searches for such numbers up to 20.
My question is rather short:
I need a vector which holds different types like:
std::vector<int,double> vec;
vec.emplace_back((int) 1);
vec.emplace_back((double) 2.0);
I tried using boost:variant, but the problem is that one has to visit/get the numbers out of the vector each time one wants to use the values.
I define initial values for the vector so the types are static and are defined at compile time. Moreover, I want to be able to iterate over them (that is why i use a vector- it could also be a map or any other container).
What I want is to use the vector entries like a int or double in the program without using boost::get or something of that kind. I think this should be possible because the type of each entry is totally defined at compile time but I do not know how to get it to work.
double d=vec[1]*3.0; //this should somehow work
int i=vec[0]*8; //this also without any get or anything
I tried using tuples, but I do not have much experience with them and it seems rather hard to iterate over them.
for(auto &elem : vec) std::cout << elem << std:endl; //this or sth. similar should also work
Any help is deeply appreciated.
You should use a tuple indeed. CPP is a strong typed language. Deal with it.
Now, if you want to iterate, consider using Boost Fusion:
Live On Coliru
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <boost/fusion/algorithm.hpp>
#include <boost/fusion/adapted/boost_tuple.hpp>
#include <boost/phoenix.hpp>
using namespace boost;
using namespace boost::phoenix::arg_names;
#include <iostream>
int main() {
tuple<int, double, std::string> demo(42, 3.1415, "hello pie universe");
fusion::for_each(demo, std::cout << arg1 << "\n");
auto& v2 = get<1>(demo);
v2 *= 10;
std::cout << "\nNew v2: " << v2 << "\n";
std::cout << "Tuple after edit: " << demo << "\n";
}
Which prints
42
3.1415
hello pie universe
New v2: 31.415
Tuple after edit: (42 31.415 hello pie universe)
I need a global variable in my C++ program. It is going to be a vector of bitsets. However, the size of the bitsets is determined at runtime by a function.
So basically, I would like to register the variable (in the top part of my code) and later define it properly by the function that determines the bitarrays' size.
Is there a way to do this in C++?
One way would be to use dynamic_bitset from boost:
#include <iostream>
#include <vector>
#include <boost/dynamic_bitset.hpp>
std::vector< boost::dynamic_bitset<> > bitsets;
int main() {
bitsets.push_back(boost::dynamic_bitset<>(1024));
bitsets.push_back(boost::dynamic_bitset<>(2048));
std::cout << bitsets[0].size() << std::endl;
std::cout << bitsets[1].size() << std::endl;
}
You could also use a vector<bool> instead, i.e. vector< vector<bool> > for a vector of bitsets. It is specialized to only use one bit per element.
bitsets sizes are fixed at compile time. just use static vector<vector<bool>> MyGlobalBits;
I want to know how I can assign multiple values to a vector at once:
#include <iostream>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/io.hpp>
using namespace boost::numeric::ublas;
int main()
{
vector<double> v1(3);
v1(0)=0;
v1(1)=0.1;
v1(2)=0.05;
v1(3)=0.25;
return 0;
}
I want to assign all the values at once.
something like:
v1 << 0,0.1,0.05,0.25;
I tried operator += and there is an error, but I think operator += works for std::vector not boost::....vector
Take a look at documentation examples http://svn.boost.org/svn/boost/trunk/libs/numeric/ublas/doc/samples/assignment_examples.cpp
Basically, you need v1 <<= 0, 1, 2;, see more examples in the docs. Unfortunately this library doesn't support initializer_list's yet: http://boost.2283326.n4.nabble.com/Initializing-from-an-initializer-list-td4647029.html
I am trying to return an iterator to the largest element in a filtered range. Here is what I have so far:
#include <boost/lambda/lambda.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <vector>
#include <iostream>
using namespace boost::adaptors;
using namespace boost::lambda;
using namespace std;
int main ()
{
vector<double> x = {100, 150, 200, 110};
auto it = boost::max_element(x | indexed(0) | filtered(_1>100)); /* problem here */
cout << it.index() << endl;
return 0;
}
I expected the code to print out the index in the vector x which has the largest element (ie 2), but unfortunately it does not compile (Linux 64bit, GCC 4.7.2), the problem being in the line indicated above. The first compilation error I get from the compiler (amongst others) is the following:
/boost/tuple/detail/tuple_basic.hpp:396:36: error: assignment of read-only member ‘boost::tuples::cons::head’
Any ideas what I am doing wrong? Or how else I can achieve what I am trying to do? Thanks in advance!
EDIT:
Changing the problematic line to :
auto it = boost::max_element<boost::return_found>(x | sliced(1,4) | filtered(boost::function<bool(double)>(_1>100)));
seems to return the iterator to the largest element. However, is there a way to check that the iterator is within the range? Comparing it with boost::end(x) gives me an error. The only thing I can think of is to return
auto another_range = boost::max_element<boost::return_found_end>(x | sliced(1,4) | filtered(boost::function<bool(double)>(_1>100)));
and check if boost::empty(another_range). Is this the only option? Thanks.
The specific error you've encountered appears because boost lambdas are not CopyAssignable. Here's a simpler way to achieve the same message:
auto f1 = _1 > 100;
auto f2 = f1;
f2 = f1; // same error
If you provide a CopyAssignable functor to filtered, boost.phoenix (which you should be using anyway, boost.lambda is on the road to deprecation in favor of phoenix), a hand-written struct, or the old faithful std::bind2nd(std::greater<double>(), 100), this line compiles with clang++:
bind2nd demo: http://liveworkspace.org/code/2xKZIf
phoenix demo: http://liveworkspace.org/code/18425g
It fails with gcc due to some boost.concept check, which is probably a bug, but it's a moot point because the result of filtered is boost::filtered_range, whose iterators don't have the .index() member function.
EDIT in response to comment:
comparing iterator into filtered_range with the iterator into the original vector wouldn't work. However, since you used vector, and since it's still accessible, you can compare addresses, since neither indexed nor filtered make copies
#include <vector>
#include <iostream>
#include <cassert>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/phoenix.hpp>
using namespace boost::adaptors;
using namespace boost::phoenix::placeholders;
int main ()
{
std::vector<double> x = {100, 150, 200, 110};
auto it = boost::max_element( x | indexed(0) | filtered(arg1 < 110) );
assert(&x[0] <= &*it && &*it < &x[0] + x.size());
std::cout << "Element " << *it << " is at index " << &*it - &x[0] << '\n';
}
demo http://liveworkspace.org/code/1zBIJ9
Or, for a more general solution, you could transform your vector into a vector of pairs (when boost gets zip adaptor, it could be neatly zipped with counting_range), and carry the original sequence index along with the value through all the transformations.