1

I had a vector of real values:

vector<double> values;

and a discrete_distribution:

discrete_distribution<size_t> dis(values.begin(), values.end());

But now I need that the vector of double values becomes a vector of structures:

struct Data
{
   double value;
   int index;
};

vector<Data> values;

How can I build the corresponding discrete_distribution without making a copy of the values into a separated vector?

Nick
  • 10,309
  • 21
  • 97
  • 201
  • Template argument in `discrete_distribution` must be integral. – 101010 Oct 31 '15 at 19:20
  • @101010 you mean like `int`, why? – Nick Oct 31 '15 at 19:24
  • There's a list of types that are valid, and `size_t` isn't one of them. That said, on almost all platforms `size_t` is a typedef of one of the supported types, but that doesn't make the code strictly correct. http://en.cppreference.com/w/cpp/numeric/random/discrete_distribution – Adam Oct 31 '15 at 19:30

2 Answers2

1

It seems that you can use the following overload (number 4)

template< class UnaryOperation >
discrete_distribution(std::size_t count, double xmin, double xmax,
                      UnaryOperation unary_op);

like this.

std::discrete_distribution<int>
make_distribution(const std::vector<Data>& weights)
{
  const auto n = weights.size();
  const auto op = [&weights](double d){
    const auto index = static_cast<std::size_t>(d - 0.5);
    //std::cout << "weights[" << index << "].value == " << weights[index].value << "\n";
    return weights[index].value;
  };
  return std::discrete_distribution<int> {n, 0.0, static_cast<double>(n), op};
}

It should work but it is a kludge.

5gon12eder
  • 24,280
  • 5
  • 45
  • 92
  • Please, write how you would instantiate a discrete_distribution object considering N=100 values, which value is in the range [0, 1]. – Nick Oct 31 '15 at 19:40
  • @Nick Sorry, my initial thought was not correct. Please see the update answer. – 5gon12eder Oct 31 '15 at 20:02
  • Can you explain the value assigned to index? – Nick Oct 31 '15 at 21:17
  • @Nick The formula is in the documentation that can be found at the link given in my answer. If you put in these numbers, it happens to generate a sequence `0.5, 1.5, …, n - 0.5`. Subtract `0.5` and you'll get the index. – 5gon12eder Oct 31 '15 at 21:20
0

Boost has a transform_iterator that can convert the return value of an iterator:

const double get_value(const Data & d)  { return d.value; }


auto beg = boost::make_transform_iterator(values.begin(), get_value);
auto end = boost::make_transform_iterator(values.end(), get_value);
discrete_distribution<size_t> dis(beg, end);

(based on this answer)

Community
  • 1
  • 1
Adam
  • 16,808
  • 7
  • 52
  • 98