5

I'm trying to make a simulation of something like a Markov chain and using discrete_distribution to simulate the change of state s_i to s_j. But of course, this is a Matrix, not a vector. So I try.

std::vector <uint16_t> v {{...},
                          {...},
                           ...
                          {...},};

std::vector <std::discrete_distribution <uint16_t> > distr(n, std::distribution <uint16_t> (v.begin(), v.end()) );

but this doesn't work.

note: if I try just 1 vector, this is a vector of uint16_t works

// CHANGE v by v[0]
std::vector<std::discrete_distribution <uint64_t>> distr(1, std::discrete_distribution <uint64_t> (vecs[0].begin(), vecs[0].end()));

based on this answer

I know that

std::vector <std::discrete_distribution <uint16_t> > distr(n, std::distribution <uint16_t> (v.begin(), v.end()) );

is not correct, but I say about the change v1 to v. to demonstrate that is possible use a vector of discrete distributions

Moises Rojo
  • 371
  • 2
  • 14
  • Instead of creating these throw-away vectors called `v1` and so on, why not initialize the nested vector in one shot? – tadman Dec 28 '17 at 20:15
  • 1
    Because I did not know how to do it. But with the answer below now I know. – Moises Rojo Dec 28 '17 at 20:30
  • It's a pretty simple thing, and Vittorio explains it well. Is this question primarily about that, or is there still a problem with the `discrete_distribution` part? – tadman Dec 28 '17 at 21:01
  • the main issue is the **discrete_distribution** part and is not solved. – Moises Rojo Jan 03 '18 at 21:25
  • @tadman I post an answer, but I want to know if there is an "easy" way to do it, without creating a template, and initialize the distribution in the declaration. – Moises Rojo Feb 12 '18 at 06:31

2 Answers2

5

You can use list initialization to initialize nested vectors. E.g.:

std::vector<std::vector<int>> v{
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};
Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • Be aware that the list initialization will still create temporaries. See [The cost of std::initializer_list](https://akrzemi1.wordpress.com/2016/07/07/the-cost-of-stdinitializer_list/) – Thomas Dec 28 '17 at 22:56
2

I find a way to do it like in this answer

using this template

template<typename T>
void set_distributions(std::vector< std::discrete_distribution <T> > &distr,  const std::vector< std::vector<T> > &vecs){
  for (uint64_t i = 0; i < vecs.size(); ++i) {
    distr.push_back( std::discrete_distribution <uint64_t> (vecs[i].begin(), vecs[i].end()) );
  }

}

and with this function, when you have emptied vectors of distributions

std::vector<std::discrete_distribution <uint64_t>> distr;
  set_distributions(distr, vecs);
Moises Rojo
  • 371
  • 2
  • 14
  • 1
    Your code can use `std::transform` along with `std::back_inserter`: https://godbolt.org/g/DcxeUv – Justin Feb 13 '18 at 22:53
  • Is it possible using just one line? like `std::discrete_distribution dist(v.begin(), v.end());` I know... that a want all with just one line and its absurd but.. I need ask absurd questions to learn. like genetic algorithm with random mutations. – Moises Rojo Feb 13 '18 at 22:58
  • 1
    Actually, since you are basically using an out-parameter, it may be better to just [directly return the result, rather than take a non-const reference](https://godbolt.org/g/okm2fg) – Justin Feb 13 '18 at 23:01
  • I can't think of a one-liner for it. The standard containers and algorithms are made to be general, and this is kind-of a more specific case. Unfortunately, `std::discrete_distribution` isn't constructable directly from a container or this would be possible, but as it is, there is no way to do it in one line that I can see – Justin Feb 13 '18 at 23:02
  • [This](https://wandbox.org/permlink/jYBvQmAUZoQYMfX3) is the closest to a one-liner I could come up with, using boost. – Justin Feb 13 '18 at 23:07