How to set a vector of "discrete_distribution" c++
Asked Answered
S

2

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

Sparkle answered 28/12, 2017 at 20:13 Comment(5)
Instead of creating these throw-away vectors called v1 and so on, why not initialize the nested vector in one shot?Spreader
Because I did not know how to do it. But with the answer below now I know.Sparkle
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?Spreader
the main issue is the discrete_distribution part and is not solved.Sparkle
@Spreader 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.Sparkle
K
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}
};
Kulsrud answered 28/12, 2017 at 20:21 Comment(1)
Be aware that the list initialization will still create temporaries. See The cost of std::initializer_listAntinomy
S
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);
Sparkle answered 12/2, 2018 at 6:16 Comment(5)
Your code can use std::transform along with std::back_inserter: godbolt.org/g/DcxeUvTheotheobald
Is it possible using just one line? like std::discrete_distribution<unsigned> 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.Sparkle
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 referenceTheotheobald
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 seeTheotheobald
This is the closest to a one-liner I could come up with, using boost.Theotheobald

© 2022 - 2024 — McMap. All rights reserved.